@cosystem/storage 0.0.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/dist/index.d.ts
CHANGED
|
@@ -11,13 +11,19 @@ interface StoragePluginOptions<TState = unknown> {
|
|
|
11
11
|
readonly storage: StorageLike;
|
|
12
12
|
readonly serialize?: (state: TState) => string;
|
|
13
13
|
readonly deserialize?: (value: string) => TState;
|
|
14
|
+
readonly partialize?: (state: unknown) => TState;
|
|
15
|
+
readonly merge?: (persisted: TState, current: unknown) => unknown;
|
|
14
16
|
readonly shouldPersist?: (event: StateChangeEvent) => boolean;
|
|
17
|
+
readonly onError?: (error: unknown, phase: StoragePluginErrorPhase) => void;
|
|
15
18
|
}
|
|
19
|
+
type StoragePluginErrorPhase = "clear" | "hydrate" | "persist";
|
|
16
20
|
interface StoragePlugin extends Plugin {
|
|
17
21
|
clear(): Promise<void>;
|
|
22
|
+
flush(): Promise<void>;
|
|
18
23
|
persist(app: App): Promise<void>;
|
|
24
|
+
ready(): Promise<void>;
|
|
19
25
|
}
|
|
20
26
|
declare function createStoragePlugin<TState = unknown>(options: StoragePluginOptions<TState>): StoragePlugin;
|
|
21
27
|
//#endregion
|
|
22
|
-
export { StorageLike, StoragePlugin, StoragePluginOptions, createStoragePlugin };
|
|
28
|
+
export { StorageLike, StoragePlugin, StoragePluginErrorPhase, StoragePluginOptions, createStoragePlugin };
|
|
23
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;UAEiB,WAAA;EACf,OAAA,CAAQ,GAAA,2BAA8B,OAAA;EACtC,OAAA,CAAQ,GAAA,UAAa,KAAA,kBAAuB,OAAA;EAC5C,UAAA,EAAY,GAAA,kBAAqB,OAAA;AAAA;AAAA,UAGlB,oBAAA;EAAA,SACN,GAAA;EAAA,SACA,OAAA,EAAS,WAAA;EAAA,SACT,SAAA,IAAa,KAAA,EAAO,MAAA;EAAA,SACpB,WAAA,IAAe,KAAA,aAAkB,MAAA;EAAA,SACjC,aAAA,IAAiB,KAAA,EAAO,gBAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;UAEiB,WAAA;EACf,OAAA,CAAQ,GAAA,2BAA8B,OAAA;EACtC,OAAA,CAAQ,GAAA,UAAa,KAAA,kBAAuB,OAAA;EAC5C,UAAA,EAAY,GAAA,kBAAqB,OAAA;AAAA;AAAA,UAGlB,oBAAA;EAAA,SACN,GAAA;EAAA,SACA,OAAA,EAAS,WAAA;EAAA,SACT,SAAA,IAAa,KAAA,EAAO,MAAA;EAAA,SACpB,WAAA,IAAe,KAAA,aAAkB,MAAA;EAAA,SACjC,UAAA,IAAc,KAAA,cAAmB,MAAA;EAAA,SACjC,KAAA,IAAS,SAAA,EAAW,MAAA,EAAQ,OAAA;EAAA,SAC5B,aAAA,IAAiB,KAAA,EAAO,gBAAA;EAAA,SACxB,OAAA,IAAW,KAAA,WAAgB,KAAA,EAAO,uBAAA;AAAA;AAAA,KAGjC,uBAAA;AAAA,UAEK,aAAA,SAAsB,MAAA;EACrC,KAAA,IAAS,OAAA;EACT,KAAA,IAAS,OAAA;EACT,OAAA,CAAQ,GAAA,EAAK,GAAA,GAAM,OAAA;EACnB,KAAA,IAAS,OAAA;AAAA;AAAA,iBAGK,mBAAA,mBACd,OAAA,EAAS,oBAAA,CAAqB,MAAA,IAC7B,aAAA"}
|
package/dist/index.js
CHANGED
|
@@ -2,22 +2,56 @@
|
|
|
2
2
|
function createStoragePlugin(options) {
|
|
3
3
|
const serialize = options.serialize ?? JSON.stringify;
|
|
4
4
|
const deserialize = options.deserialize ?? JSON.parse;
|
|
5
|
+
const partialize = options.partialize ?? ((state) => state);
|
|
6
|
+
const merge = options.merge ?? ((persisted) => persisted);
|
|
7
|
+
let readyPromise = Promise.resolve();
|
|
8
|
+
let writeQueue = Promise.resolve();
|
|
9
|
+
const runQueued = (phase, task) => {
|
|
10
|
+
const operation = writeQueue.catch(() => void 0).then(task);
|
|
11
|
+
writeQueue = operation.catch((error) => {
|
|
12
|
+
options.onError?.(error, phase);
|
|
13
|
+
});
|
|
14
|
+
return operation;
|
|
15
|
+
};
|
|
5
16
|
return {
|
|
6
17
|
name: "cosystem:storage",
|
|
7
18
|
async clear() {
|
|
8
|
-
await
|
|
19
|
+
await readyPromise;
|
|
20
|
+
await runQueued("clear", async () => {
|
|
21
|
+
await options.storage.removeItem?.(options.key);
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
async flush() {
|
|
25
|
+
await readyPromise;
|
|
26
|
+
await writeQueue;
|
|
9
27
|
},
|
|
10
|
-
|
|
28
|
+
onStateChange(event) {
|
|
11
29
|
if (options.shouldPersist !== void 0 && !options.shouldPersist(event)) return;
|
|
12
|
-
|
|
30
|
+
runQueued("persist", async () => {
|
|
31
|
+
await options.storage.setItem(options.key, serialize(partialize(event.state)));
|
|
32
|
+
}).catch(() => void 0);
|
|
13
33
|
},
|
|
14
34
|
async persist(app) {
|
|
15
|
-
await
|
|
35
|
+
await readyPromise;
|
|
36
|
+
await runQueued("persist", async () => {
|
|
37
|
+
await options.storage.setItem(options.key, serialize(partialize(app.store.getPureState())));
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
ready() {
|
|
41
|
+
return readyPromise;
|
|
16
42
|
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
43
|
+
setup(app) {
|
|
44
|
+
readyPromise = (async () => {
|
|
45
|
+
try {
|
|
46
|
+
const stored = await options.storage.getItem(options.key);
|
|
47
|
+
if (stored === null) return;
|
|
48
|
+
app.store.setState(merge(deserialize(stored), app.store.getPureState()));
|
|
49
|
+
} catch (error) {
|
|
50
|
+
options.onError?.(error, "hydrate");
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
return readyPromise;
|
|
21
55
|
}
|
|
22
56
|
};
|
|
23
57
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { App, Plugin, StateChangeEvent } from \"@cosystem/core\";\n\nexport interface StorageLike {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem?(key: string): void | Promise<void>;\n}\n\nexport interface StoragePluginOptions<TState = unknown> {\n readonly key: string;\n readonly storage: StorageLike;\n readonly serialize?: (state: TState) => string;\n readonly deserialize?: (value: string) => TState;\n readonly shouldPersist?: (event: StateChangeEvent) => boolean;\n}\n\nexport interface StoragePlugin extends Plugin {\n clear(): Promise<void>;\n persist(app: App): Promise<void>;\n}\n\nexport function createStoragePlugin<TState = unknown>(\n options: StoragePluginOptions<TState>,\n): StoragePlugin {\n const serialize = options.serialize ?? JSON.stringify;\n const deserialize = options.deserialize ?? JSON.parse;\n\n return {\n name: \"cosystem:storage\",\n async clear() {\n await options.storage.removeItem?.(options.key);\n },\n async onStateChange(event) {\n if (options.shouldPersist !== undefined && !options.shouldPersist(event)) {\n return;\n }\n\n await options.storage.setItem(options.key, serialize(event.state
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { App, Plugin, StateChangeEvent } from \"@cosystem/core\";\n\nexport interface StorageLike {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem?(key: string): void | Promise<void>;\n}\n\nexport interface StoragePluginOptions<TState = unknown> {\n readonly key: string;\n readonly storage: StorageLike;\n readonly serialize?: (state: TState) => string;\n readonly deserialize?: (value: string) => TState;\n readonly partialize?: (state: unknown) => TState;\n readonly merge?: (persisted: TState, current: unknown) => unknown;\n readonly shouldPersist?: (event: StateChangeEvent) => boolean;\n readonly onError?: (error: unknown, phase: StoragePluginErrorPhase) => void;\n}\n\nexport type StoragePluginErrorPhase = \"clear\" | \"hydrate\" | \"persist\";\n\nexport interface StoragePlugin extends Plugin {\n clear(): Promise<void>;\n flush(): Promise<void>;\n persist(app: App): Promise<void>;\n ready(): Promise<void>;\n}\n\nexport function createStoragePlugin<TState = unknown>(\n options: StoragePluginOptions<TState>,\n): StoragePlugin {\n const serialize = options.serialize ?? JSON.stringify;\n const deserialize = options.deserialize ?? JSON.parse;\n const partialize = options.partialize ?? ((state: unknown) => state as TState);\n const merge = options.merge ?? ((persisted: TState) => persisted);\n let readyPromise: Promise<void> = Promise.resolve();\n let writeQueue: Promise<void> = Promise.resolve();\n\n const runQueued = (\n phase: StoragePluginErrorPhase,\n task: () => void | Promise<void>,\n ): Promise<void> => {\n const operation = writeQueue.catch(() => undefined).then(task);\n writeQueue = operation.catch((error: unknown) => {\n options.onError?.(error, phase);\n });\n\n return operation;\n };\n\n return {\n name: \"cosystem:storage\",\n async clear() {\n await readyPromise;\n await runQueued(\"clear\", async () => {\n await options.storage.removeItem?.(options.key);\n });\n },\n async flush() {\n await readyPromise;\n await writeQueue;\n },\n onStateChange(event) {\n if (options.shouldPersist !== undefined && !options.shouldPersist(event)) {\n return;\n }\n\n void runQueued(\"persist\", async () => {\n await options.storage.setItem(options.key, serialize(partialize(event.state)));\n }).catch(() => undefined);\n },\n async persist(app) {\n await readyPromise;\n await runQueued(\"persist\", async () => {\n await options.storage.setItem(options.key, serialize(partialize(app.store.getPureState())));\n });\n },\n ready() {\n return readyPromise;\n },\n setup(app) {\n readyPromise = (async () => {\n try {\n const stored = await options.storage.getItem(options.key);\n\n if (stored === null) {\n return;\n }\n\n app.store.setState(merge(deserialize(stored), app.store.getPureState()) as never);\n } catch (error) {\n options.onError?.(error, \"hydrate\");\n throw error;\n }\n })();\n\n return readyPromise;\n },\n };\n}\n"],"mappings":";AA4BA,SAAgB,oBACd,SACe;CACf,MAAM,YAAY,QAAQ,aAAa,KAAK;CAC5C,MAAM,cAAc,QAAQ,eAAe,KAAK;CAChD,MAAM,aAAa,QAAQ,gBAAgB,UAAmB;CAC9D,MAAM,QAAQ,QAAQ,WAAW,cAAsB;CACvD,IAAI,eAA8B,QAAQ,QAAQ;CAClD,IAAI,aAA4B,QAAQ,QAAQ;CAEhD,MAAM,aACJ,OACA,SACkB;EAClB,MAAM,YAAY,WAAW,YAAY,KAAA,CAAS,CAAC,CAAC,KAAK,IAAI;EAC7D,aAAa,UAAU,OAAO,UAAmB;GAC/C,QAAQ,UAAU,OAAO,KAAK;EAChC,CAAC;EAED,OAAO;CACT;CAEA,OAAO;EACL,MAAM;EACN,MAAM,QAAQ;GACZ,MAAM;GACN,MAAM,UAAU,SAAS,YAAY;IACnC,MAAM,QAAQ,QAAQ,aAAa,QAAQ,GAAG;GAChD,CAAC;EACH;EACA,MAAM,QAAQ;GACZ,MAAM;GACN,MAAM;EACR;EACA,cAAc,OAAO;GACnB,IAAI,QAAQ,kBAAkB,KAAA,KAAa,CAAC,QAAQ,cAAc,KAAK,GACrE;GAGF,UAAe,WAAW,YAAY;IACpC,MAAM,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,UAAU,WAAW,MAAM,KAAK,CAAC,CAAC;GAC/E,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAC1B;EACA,MAAM,QAAQ,KAAK;GACjB,MAAM;GACN,MAAM,UAAU,WAAW,YAAY;IACrC,MAAM,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,UAAU,WAAW,IAAI,MAAM,aAAa,CAAC,CAAC,CAAC;GAC5F,CAAC;EACH;EACA,QAAQ;GACN,OAAO;EACT;EACA,MAAM,KAAK;GACT,gBAAgB,YAAY;IAC1B,IAAI;KACF,MAAM,SAAS,MAAM,QAAQ,QAAQ,QAAQ,QAAQ,GAAG;KAExD,IAAI,WAAW,MACb;KAGF,IAAI,MAAM,SAAS,MAAM,YAAY,MAAM,GAAG,IAAI,MAAM,aAAa,CAAC,CAAU;IAClF,SAAS,OAAO;KACd,QAAQ,UAAU,OAAO,SAAS;KAClC,MAAM;IACR;GACF,EAAA,CAAG;GAEH,OAAO;EACT;CACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosystem/storage",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Persistence plugin for CoSystem.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/coactionjs/cosystem.git",
|
|
9
|
+
"directory": "packages/storage"
|
|
10
|
+
},
|
|
6
11
|
"files": [
|
|
7
12
|
"dist"
|
|
8
13
|
],
|
|
@@ -20,7 +25,7 @@
|
|
|
20
25
|
"access": "public"
|
|
21
26
|
},
|
|
22
27
|
"dependencies": {
|
|
23
|
-
"@cosystem/core": "0.0
|
|
28
|
+
"@cosystem/core": "1.0.0"
|
|
24
29
|
},
|
|
25
30
|
"devDependencies": {
|
|
26
31
|
"tsdown": "0.22.3",
|