Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/huang2002/hstorage

A storage lib.
https://github.com/huang2002/hstorage

3h localstorage sessionstorage storage store

Last synced: 5 days ago
JSON representation

A storage lib.

Awesome Lists containing this project

README

        

# hstorage

> A storage lib.

## TOC

- [Introduction](#introduction)
- [Usage](#usage)
- [API Reference](#api-reference)
- [Links](#links)

## Introduction

`hstorage` is a storage lib which has a custom type system and is rather lightweight(<10KB after minification WITHOUT zipping). With your store declared, type checking and conflict detecting will be available out of the box.

## Usage

### npm

1. Use npm to install it as a dependency:

```bash
npm install hstorage
```

2. Import the exports of this lib:

```js
import { /* ... */ } from "hstorage";
// or
const { /* ... */ } = require("hstorage");
```

3. Use them in your code.

### CDN

1. Include one of the following script tags in your HTML file:

via jsdelivr:

```html

```

or via unpkg:

```html

```

2. Access the APIs via the `HS` global.

```js
const { /* ... */ } = HS;
```

If you want a specified version, just replace `latest` with that in the url. By the way, it is recommended to use a specified version in production.

For more information about these two CDN sites, visit [www.jsdelivr.com](https://www.jsdelivr.com) and [unpkg.com](https://unpkg.com).

## API Reference

(The API reference is written in [TypeScript](https://www.typescriptlang.org/).)

```ts
/**
* @desc The type of storage-like objects.
*/
interface StorageLike {

/**
* @desc Get the item value by giving the key to it.
*/
getItem(key: string): string | null;

/**
* @desc Set the item value by giving the key to it.
*/
setItem(key: string, value: string): void;

}

/**
* @desc The type of store options. (These are all
* partial properties on store instances, so you can
* refer to the property details for more information.)
*/
interface StoreOptions {
defaultValue?: T | null;
type?: Type | null;
delay?: number;
storage?: StorageLike;
lazyLoad?: boolean;
strictLoad?: boolean;
secure?: boolean;
autoFix?: boolean;
onInvalid?: StoreInvalidCallback | null;
onConflict?: StoreConflictCallback | null;
pathSeparator?: string;
}

/**
* @desc The class for store instances.
*/
class Store {

/**
* @desc The defaults of store options.
*/
static defaults: StoreOptions;

/**
* @desc The constructor which accepts a required name and optional options.
*/
constructor(name: string, options?: StoreOptions);

/**
* @desc The name which is used as the key to the store.
*/
name: string;

/**
* @desc The default value of the store. If this is omitted but the `type` property
* is given, `type.defaultValue` will be adopted.
*
*/
defaultValue: T | null;

/**
* @desc The type of the store. (See the `Type` interface and built-in types below.)
* If this is omitted but the `defaultValue` is given, an inferred type generated by
* `inferType`(see below) will be adopted.
*/
type: Type | null;

/**
* @desc The delay of saving in milliseconds. (If zero, save synchronously.)
*/
delay: number;

/**
* @desc The storage to use.
* @default localStorage
*/
storage: StorageLike;

/**
* @desc Whether not to load immediately when the store is being created.
* @default false
*/
readonly lazyLoad: boolean;

/**
* @desc Whether to do type checking while loading the store from storage.
* @default true
*/
strictLoad: boolean;

/**
* @desc Whether to check conflicts while saving.
* @default true
*/
secure: boolean;

/**
* @desc Whether to try to fix invalid value automatically.
* @default true
*/
autoFix: boolean;

/**
* @desc The invalidation callback. (If not given, errors will be thrown instead.)
* @param paths The invalid property paths. (Path `[]` means the root.)
*/
onInvalid: ((this: Store, paths: string[][]) => void) | null;

/**
* @desc The conflict callback. (If not given, errors will be thrown instead.)
* @param newSource The current source in the storage.
* @param oldSource The copy of the old source in the storage.
* @example
* ```js
* onConflict(newSource, oldSource) {
* if (youWantTheNewSource) {
* this.load(newSource);
* } else {
* this.storage.setItem(this.name, oldSource);
* this.save();
* }
* }
* ```
*/
onConflict: ((this: Store, newSource: string | null, oldSource: string | null) => void) | null;

/**
* @desc The path separator to use.
* @default '.'
*/
pathSeparator: string;

/**
* @desc Manually save the store. (synchronously)
* @returns Whether the saving is successful. (`false` if conflict occurs
* or no `storage` given.)
*/
save(): boolean;

/**
* @desc Reset the specific value.
* @param selector A path string or a path array.
* @returns Whether the reset is successful. (`false` if the default value can't be found.)
* @example
* ```js
* store.reset('foo.bar');
* store.reset(['foo', 'bar']);
* ```
*/
reset(selector: string | string[]): boolean;

/**
* @desc Load the store from source.
* @param source The source string. If omitted, read the source from `storage`.
* @returns Whether the loading is successful. (`false` both on invalidation
* if it can't be fixed and no storage presence.)
*/
load(source?: string | null): boolean;

/**
* @desc Check whether the sources conflict.
* @returns `true` if conflict; `false` otherwise.
*/
checkConflict(): boolean;

/**
* @desc Get the specific store value by giving a property path string or
* a path array. Invoke it without arguments to get the whole store value.
*/
get(path?: string | string[]): unknown;

/**
* @desc Set the specific value by giving a path and a new value or
* an updating callback which accepts the old value and returns a new one.
* @returns Whether the operation is successful. (`false` on invalidation if it can't fixed.)
*/
set(path: string | string[], patch: unknown | (this: Store, oldValue: unknown) => unknown): boolean;

}

/**
* @desc The type of validating results.
*/
interface ValidatingResult {

/**
* @desc Whether the value is valid.
*/
valid: boolean;

/**
* @desc The path of invalid properties if there is any.
*/
paths?: string[][];

}

/**
* @desc The type of type class instances.
*/
interface Type {

/**
* @desc The default value.
*/
defaultValue: T;

/**
* @desc Validate the given result.
*/
validate(value: unknown): ValidatingResult;

}

/**
* @desc Turn an object into a map of corresponding type class instances.
*/
type Types = {
[K in Extract]: Type;
};

/**
* @desc The type class of any types. (always valid)
*/
class Any implements Type {
constructor(defaultValue?: any);
defaultValue: any;
validate(): ValidatingResult;
}

/**
* @desc Create an any type instance.
*/
function any(defaultValue?: any): Any;

/**
* @desc The type class of booleans.
*/
class Boolean implements Type {
defaultValue: boolean;
constructor(defaultValue?: boolean);
validate(value: unknown): ValidatingResult;
}

/**
* @desc Create a boolean type instance.
*/
function boolean(defaultValue?: boolean): Boolean;

/**
* @desc The type of string options. (See property details.)
*/
interface StringOptions {
defaultValue?: string;
minLength?: number;
maxLength?: number;
pattern?: RegExp | null;
}

/**
* @desc The type class of strings.
*/
class String implements Type {

static defaults: StringOptions;

constructor(options?: StringOptions);

defaultValue: string;

/**
* @desc The minimum string length.
* @default 0
*/
minLength: number;

/**
* @desc The maximum string length.
* @default Infinity
*/
maxLength: number;

/**
* @desc The string pattern. (`null` means any pattern.)
*/
pattern: RegExp | null;

validate(value: unknown): ValidatingResult;

}

/**
* @desc Create a string type instance.
*/
function string(options?: StringOptions): String;

/**
* @desc The type of number options. (See property details.)
*/
interface NumberOptions {
defaultValue?: number;
min?: number;
max?: number;
integer?: boolean;
}

/**
* @desc The type class of numbers.
*/
class Number implements Type {

static defaults: NumberOptions;

constructor(options?: NumberOptions);

defaultValue: number;

/**
* @desc The minimum limit.
* @default -Infinity
*/
min: number;

/**
* @desc The maximum limit.
* @default Infinity
*/
max: number;

/**
* @desc Whether the number must be an integer.
* @default false
*/
integer: boolean;

validate(value: unknown): ValidatingResult;

}

/**
* @desc Create a number type instance.
*/
function number(options?: NumberOptions | undefined): Number;

/**
* @desc The type of nullable options. (See property details.)
*/
interface NullableOptions {
defaultValue?: T;
null?: boolean;
undefined?: boolean;
}

/**
* @desc The type class of nullable value.
*/
class Nullable implements Type {

static defaults: NullableOptions;

constructor(options?: NullableOptions);

defaultValue: T;

/**
* @desc Whether `null` is acceptable.
* @default true
*/
null: boolean;

/**
* @desc Whether `undefined` is acceptable.
* @default true
*/
undefined: boolean;

validate(value: unknown): ValidatingResult;

}

/**
* @desc Create a nullable type instance.
*/
function nullable:
(options?: NullableOptions): Nullable;

/**
* @desc The type class of dictionaries.
*/
class Dictionary implements Type {

/**
* @desc The property types. (`null` or `undefined` means no limit.)
* @example
* ```js
* dictionary.types = {
* foo: HS.string(),
* bar: HS.number(),
* };
* ```
*/
readonly types?: Types | null;

constructor(types?: Types | null);

/**
* @desc The default value. (If not provided, one will be created from `types`.)
*/
defaultValue: T;

validate(value: unknown): ValidatingResult;

}

/**
* @desc Create a dictionary type instance.
*/
function dictionary(types?: Types | null): Dictionary;

/**
* @desc The type of list options. (See property details.)
*/
interface ListOptions {
defaultValue?: T[];
type: Type;
}

/**
* @desc The type class of lists.
*/
class List implements Type {

static defaults: ListOptions;

constructor(options?: ListOptions);

defaultValue: T[];

/**
* @desc The type of list elements.
* @default Any
*/
type: Type;

validate(value: unknown): ValidatingResult;

}

/**
* @desc Create a list type instance.
*/
function list(options?: ListOptions): List;

/**
* @desc The type of union options. (See property details.)
*/
interface UnionOptions {
defaultValue?: T;
types: Type[];
}

/**
* @desc The type class of union.
*/
class Union implements Type {

constructor(options?: UnionOptions);

/**
* @desc The default value. (If not provided, one will be created from `types`.)
*/
defaultValue: T;

/**
* @desc The types included in the union.
*/
types: Type[];

validate(value: unknown): ValidatingResult;

}

/**
* @desc Create a union type instance.
*/
function union(options?: UnionOptions): Union;

/**
* @desc Get the type nested in the given type by giving the path to it.
* (Its ancestors must be dictionary types.)
*/
function getTypeByPath(type: Type, path: string[]): Type;

/**
* @desc Infer type from the given value.
*/
function inferType(value: unknown): Type;

```

## Links

- [Contributing Guide](./CONTRIBUTING.md)
- [Changelog](./CHANGELOG.md)
- [License (MIT)](./LICENSE)