cross-state 1.8.5 → 1.9.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.
Files changed (43) hide show
  1. package/dist/{diff-BZm7wZ6G.d.cts → diff-Bcr0h7-x.d.cts} +2 -1
  2. package/dist/{diff-DxjoO6qz.d.ts → diff-CwiTYAVK.d.ts} +2 -1
  3. package/dist/extendedJson-DA3RQ_ly.js +138 -0
  4. package/dist/extendedJson-DA3RQ_ly.js.map +1 -0
  5. package/dist/extendedJson-DzXMFE1P.cjs +167 -0
  6. package/dist/extendedJson-DzXMFE1P.cjs.map +1 -0
  7. package/dist/index.cjs +4 -4
  8. package/dist/index.d.cts +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +3 -3
  11. package/dist/{patchMethods-CxI_x-zv.d.ts → patchMethods-C21iQqML.d.ts} +2 -2
  12. package/dist/{patchMethods-BfyJt9me.cjs → patchMethods-CZje49Dk.cjs} +4 -117
  13. package/dist/patchMethods-CZje49Dk.cjs.map +1 -0
  14. package/dist/{patchMethods-D-Vmx93m.js → patchMethods-Cui462lc.js} +4 -111
  15. package/dist/patchMethods-Cui462lc.js.map +1 -0
  16. package/dist/{patchMethods-DjHq-wbw.d.cts → patchMethods-Cyb6MEOG.d.cts} +2 -2
  17. package/dist/patches/index.cjs +1 -1
  18. package/dist/patches/index.d.cts +1 -1
  19. package/dist/patches/index.d.ts +1 -1
  20. package/dist/patches/index.js +1 -1
  21. package/dist/patches/register.cjs +1 -1
  22. package/dist/patches/register.d.cts +1 -1
  23. package/dist/patches/register.d.ts +1 -1
  24. package/dist/patches/register.js +1 -1
  25. package/dist/persist/register.cjs +1 -1
  26. package/dist/persist/register.js +1 -1
  27. package/dist/{persist-CwKzFRM7.cjs → persist-CG1WHP6D.cjs} +3 -3
  28. package/dist/{persist-CwKzFRM7.cjs.map → persist-CG1WHP6D.cjs.map} +1 -1
  29. package/dist/{persist-CZhDrupc.js → persist-CNA2sYtB.js} +3 -3
  30. package/dist/{persist-CZhDrupc.js.map → persist-CNA2sYtB.js.map} +1 -1
  31. package/dist/react/index.cjs +41 -3
  32. package/dist/react/index.cjs.map +1 -1
  33. package/dist/react/index.d.cts +9 -0
  34. package/dist/react/index.d.ts +9 -0
  35. package/dist/react/index.js +41 -3
  36. package/dist/react/index.js.map +1 -1
  37. package/package.json +1 -1
  38. package/dist/extendedJson-B1OEqZtF.js +0 -29
  39. package/dist/extendedJson-B1OEqZtF.js.map +0 -1
  40. package/dist/extendedJson-BwYSvpOA.cjs +0 -53
  41. package/dist/extendedJson-BwYSvpOA.cjs.map +0 -1
  42. package/dist/patchMethods-BfyJt9me.cjs.map +0 -1
  43. package/dist/patchMethods-D-Vmx93m.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { a as set, c as deepEqual, i as remove, o as isObject } from "./propAccess-BxCKNeOj.js";
2
- import { r as toExtendedJson, t as fromExtendedJson } from "./extendedJson-B1OEqZtF.js";
1
+ import { a as set, i as remove } from "./propAccess-BxCKNeOj.js";
2
+ import { a as diff, r as toExtendedJson, t as fromExtendedJson } from "./extendedJson-DA3RQ_ly.js";
3
3
 
4
4
  //#region src/lib/applyPatches.ts
5
5
  function applySinglePatch(target, patch) {
@@ -11,113 +11,6 @@ function applyPatches(target, ...patches) {
11
11
  return target;
12
12
  }
13
13
 
14
- //#endregion
15
- //#region src/lib/diff.ts
16
- function diff(a, b, options = {}) {
17
- const result = [..._diff(a, b, options)];
18
- return [result.map(([patch]) => patch), result.map(([, reversePatch]) => reversePatch)];
19
- }
20
- function* _diff(a, b, options, prefix = []) {
21
- if (a === b) return;
22
- if (typeof options.stopAt === "number" && prefix.length >= options.stopAt || typeof options.stopAt === "function" && options.stopAt(prefix)) {
23
- if (deepEqual(a, b)) return;
24
- return yield [{
25
- op: "replace",
26
- path: prefix,
27
- value: b
28
- }, {
29
- op: "replace",
30
- path: prefix,
31
- value: a
32
- }];
33
- }
34
- if (a instanceof Date && b instanceof Date) {
35
- if (a.getTime() === b.getTime()) return;
36
- return yield [{
37
- op: "replace",
38
- path: prefix,
39
- value: b
40
- }, {
41
- op: "replace",
42
- path: prefix,
43
- value: a
44
- }];
45
- }
46
- if (a instanceof Map && b instanceof Map) return yield* mapDiff(a, b, options, prefix);
47
- if (a instanceof Set && b instanceof Set) {
48
- if (deepEqual(a, b)) return;
49
- return yield [{
50
- op: "replace",
51
- path: prefix,
52
- value: b
53
- }, {
54
- op: "replace",
55
- path: prefix,
56
- value: a
57
- }];
58
- }
59
- if (Array.isArray(a) && Array.isArray(b)) {
60
- if (deepEqual(a, b)) return;
61
- return yield [{
62
- op: "replace",
63
- path: prefix,
64
- value: b
65
- }, {
66
- op: "replace",
67
- path: prefix,
68
- value: a
69
- }];
70
- }
71
- if (isObject(a) && isObject(b) && !Array.isArray(a) && !Array.isArray(b)) return yield* objectDiff(a, b, options, prefix);
72
- yield [{
73
- op: "replace",
74
- path: prefix,
75
- value: b
76
- }, {
77
- op: "replace",
78
- path: prefix,
79
- value: a
80
- }];
81
- }
82
- function* mapDiff(a, b, options, prefix) {
83
- for (const [key, value] of a) if (!b.has(key)) yield [{
84
- op: "remove",
85
- path: [...prefix, key]
86
- }, {
87
- op: "add",
88
- path: [...prefix, key],
89
- value
90
- }];
91
- else yield* _diff(value, b.get(key), options, [...prefix, key]);
92
- for (const [key, value] of b) if (!a.has(key)) yield [{
93
- op: "add",
94
- path: [...prefix, key],
95
- value
96
- }, {
97
- op: "remove",
98
- path: [...prefix, key]
99
- }];
100
- }
101
- function* objectDiff(a, b, options, prefix) {
102
- for (const [key, value] of Object.entries(a)) if (!(key in b)) yield [{
103
- op: "remove",
104
- path: [...prefix, key]
105
- }, {
106
- op: "add",
107
- path: [...prefix, key],
108
- value
109
- }];
110
- else yield* _diff(value, b[key], options, [...prefix, key]);
111
- for (const [key, value] of Object.entries(b)) if (!(key in a)) yield [{
112
- op: "add",
113
- path: [...prefix, key],
114
- value
115
- }, {
116
- op: "remove",
117
- path: [...prefix, key]
118
- }];
119
- }
120
-
121
14
  //#endregion
122
15
  //#region src/lib/trie.ts
123
16
  var TrieNode = class {
@@ -235,5 +128,5 @@ const patchMethods = {
235
128
  };
236
129
 
237
130
  //#endregion
238
- export { applyPatches as i, subscribePatches as n, diff as r, patchMethods as t };
239
- //# sourceMappingURL=patchMethods-D-Vmx93m.js.map
131
+ export { subscribePatches as n, applyPatches as r, patchMethods as t };
132
+ //# sourceMappingURL=patchMethods-Cui462lc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patchMethods-Cui462lc.js","names":["applyPatches","_applyPatches","patchMethods: {\n subscribePatches: typeof subscribePatches;\n applyPatches: typeof applyPatches;\n sync: typeof sync;\n acceptSync: typeof acceptSync;\n}"],"sources":["../src/lib/applyPatches.ts","../src/lib/trie.ts","../src/patches/patchMethods.ts"],"sourcesContent":["import type { Patch } from './diff';\nimport { remove, set } from './propAccess';\n\nfunction applySinglePatch<T>(target: T, patch: Patch): T {\n if (patch.op === 'remove') {\n return remove(target, patch.path as any);\n }\n\n return set(target, patch.path as any, patch.value);\n}\n\nexport function applyPatches<T>(target: T, ...patches: Patch[]): T {\n for (const patch of patches) {\n target = applySinglePatch(target, patch);\n }\n\n return target;\n}\n","import type { KeyType } from '@lib/path';\n\nclass TrieNode {\n children: Map<KeyType, TrieNode> = new Map();\n isLeaf = false;\n}\n\nexport class Trie {\n root: TrieNode = new TrieNode();\n\n add(path: KeyType[]): void {\n let node = this.root;\n for (const key of path) {\n let next = node.children.get(key);\n if (!next) node.children.set(key, (next = new TrieNode()));\n node = next;\n }\n node.isLeaf = true;\n }\n\n hasSubPath(path: KeyType[]): boolean {\n let node = this.root;\n for (const key of path) {\n const next = node.children.get(key);\n if (!next) return false;\n node = next;\n }\n return node.isLeaf;\n }\n}\n","import type { Cancel, DisposableCancel, SubscribeOptions } from '@core/commonTypes';\nimport type { Store } from '@core/store';\nimport { applyPatches as _applyPatches } from '@lib/applyPatches';\nimport { diff, type DiffOptions, type Patch } from '@lib/diff';\nimport { fromExtendedJson, toExtendedJson } from '@lib/extendedJson';\nimport { Trie } from '@lib/trie';\n\nexport interface SyncMessage {\n fromVersion?: string;\n toVersion: string;\n patches: Patch[];\n}\n\nexport interface HistoryEntry extends SyncMessage {\n reversePatches: Patch[];\n}\n\ndeclare module '..' {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n interface Store<T> {\n __patches?: {\n value: T;\n version: string;\n history: HistoryEntry[];\n };\n }\n}\n\nexport interface SubscribePatchOptions extends SubscribeOptions, DiffOptions {\n /** @default false */\n runNow?: boolean;\n /** try to start from a specific version and only receive patches after that.\n * If the id is not found, it will start from the beginning */\n startAt?: string;\n}\n\nexport type InteropPatch = Patch | { op: 'add' | 'replace' | 'remove'; value?: any };\n\nconst genId = () => Math.random().toString(36).slice(2);\n\nexport function subscribePatches<T>(\n this: Store<T>,\n listener: (\n this: { cancel: Cancel },\n patches: Patch[],\n reversePatches: Patch[],\n version: string,\n previousVersion: string | undefined,\n ) => void,\n options: SubscribePatchOptions = {},\n): DisposableCancel {\n const patches = (this.__patches ??= {\n value: this.get(),\n version: genId(),\n history: [],\n });\n\n options = { ...options };\n options.runNow ??= false;\n let cursor = options.startAt ?? (options.runNow ? undefined : this.__patches.version);\n\n return this.subscribe(function (value) {\n if (patches.value !== value) {\n const result = diff(patches.value, value, options);\n patches.value = value;\n\n if (result[0].length > 0) {\n const newVersion = genId();\n\n patches.history = patches.history\n .concat({\n fromVersion: patches.version,\n toVersion: newVersion,\n patches: result[0],\n reversePatches: result[1],\n })\n .slice(-1000);\n\n patches.version = newVersion;\n }\n }\n\n if (cursor === patches.version) return;\n const index = patches.history.findIndex((h) => h.fromVersion === cursor);\n let forward, backward, previousVersion;\n\n if (index === -1) {\n [forward, backward] = diff(undefined, value, options);\n previousVersion = undefined;\n } else {\n forward = patches.history.slice(index).flatMap((h) => h.patches);\n backward = patches.history.slice(index).flatMap((h) => h.reversePatches);\n previousVersion = cursor;\n }\n\n cursor = patches.version;\n listener.apply(this, [forward, backward, cursor, previousVersion]);\n }, options);\n}\n\nexport function applyPatches<T>(this: Store<T>, patches: InteropPatch[]): void;\nexport function applyPatches<T>(this: Store<T>, ...patches: InteropPatch[]): void;\nexport function applyPatches<T>(\n this: Store<T>,\n ...patches: (InteropPatch | InteropPatch[])[]\n): void {\n this.set((value) => _applyPatches(value, ...(patches.flat() as Patch[])));\n}\n\nexport function sync<T>(\n this: Store<T>,\n listener: (syncMessage: SyncMessage) => void,\n options?: Omit<SubscribePatchOptions, 'runNow'>,\n): DisposableCancel {\n const debounce =\n typeof options?.debounce === 'object' && 'wait' in options.debounce\n ? { ...options.debounce }\n : options?.debounce !== undefined\n ? { wait: options.debounce }\n : undefined;\n\n if (debounce) {\n debounce.waitOnRunNow ??= false;\n }\n\n return subscribePatches.apply<\n Store<T>,\n Parameters<typeof subscribePatches<T>>,\n ReturnType<typeof subscribePatches<T>>\n >(this, [\n (patches, _, version, previousVersion) => {\n const trie = new Trie();\n\n patches = [...patches]\n .reverse()\n .filter((patch) => {\n if (trie.hasSubPath(patch.path)) {\n return false;\n }\n\n trie.add(patch.path);\n return true;\n })\n .reverse();\n\n listener({\n fromVersion: previousVersion,\n toVersion: version,\n patches: toExtendedJson(patches) as Patch[],\n });\n },\n { ...options, debounce, runNow: true },\n ]);\n}\n\nexport function acceptSync<T>(this: Store<T>, message: SyncMessage): void {\n if (message.fromVersion && message.fromVersion !== this.version) {\n throw new Error(\n `version mismatch! version=${this.version}, fromVersion=${message.fromVersion}`,\n );\n }\n\n const patches = fromExtendedJson(message.patches) as Patch[];\n\n this.version = message.toVersion;\n applyPatches.apply<Store<T>, Patch[], void>(this, patches);\n}\n\nexport const patchMethods: {\n subscribePatches: typeof subscribePatches;\n applyPatches: typeof applyPatches;\n sync: typeof sync;\n acceptSync: typeof acceptSync;\n} = {\n subscribePatches,\n applyPatches,\n sync,\n acceptSync,\n};\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { g as Cancel, r as Store, w as SubscribeOptions, y as DisposableCancel } from "./store-21GsOOLS.cjs";
2
- import { n as Patch, t as DiffOptions } from "./diff-BZm7wZ6G.cjs";
2
+ import { n as Patch, t as DiffOptions } from "./diff-Bcr0h7-x.cjs";
3
3
 
4
4
  //#region src/patches/patchMethods.d.ts
5
5
  interface SyncMessage {
@@ -45,4 +45,4 @@ declare const patchMethods: {
45
45
  };
46
46
  //#endregion
47
47
  export { SyncMessage as n, patchMethods as r, SubscribePatchOptions as t };
48
- //# sourceMappingURL=patchMethods-DjHq-wbw.d.cts.map
48
+ //# sourceMappingURL=patchMethods-Cyb6MEOG.d.cts.map
@@ -1,3 +1,3 @@
1
- const require_patchMethods = require('../patchMethods-BfyJt9me.cjs');
1
+ const require_patchMethods = require('../patchMethods-CZje49Dk.cjs');
2
2
 
3
3
  exports.patchMethods = require_patchMethods.patchMethods;
@@ -1,2 +1,2 @@
1
- import { n as SyncMessage, r as patchMethods, t as SubscribePatchOptions } from "../patchMethods-DjHq-wbw.cjs";
1
+ import { n as SyncMessage, r as patchMethods, t as SubscribePatchOptions } from "../patchMethods-Cyb6MEOG.cjs";
2
2
  export { type SubscribePatchOptions, type SyncMessage, patchMethods };
@@ -1,2 +1,2 @@
1
- import { n as SyncMessage, r as patchMethods, t as SubscribePatchOptions } from "../patchMethods-CxI_x-zv.js";
1
+ import { n as SyncMessage, r as patchMethods, t as SubscribePatchOptions } from "../patchMethods-C21iQqML.js";
2
2
  export { type SubscribePatchOptions, type SyncMessage, patchMethods };
@@ -1,3 +1,3 @@
1
- import { t as patchMethods } from "../patchMethods-D-Vmx93m.js";
1
+ import { t as patchMethods } from "../patchMethods-Cui462lc.js";
2
2
 
3
3
  export { patchMethods };
@@ -1,5 +1,5 @@
1
1
  const require_store = require('../store-CPqOf4y5.cjs');
2
- const require_patchMethods = require('../patchMethods-BfyJt9me.cjs');
2
+ const require_patchMethods = require('../patchMethods-CZje49Dk.cjs');
3
3
 
4
4
  //#region src/patches/register.ts
5
5
  Object.assign(require_store.Store.prototype, require_patchMethods.patchMethods);
@@ -1,4 +1,4 @@
1
- import { r as patchMethods } from "../patchMethods-DjHq-wbw.cjs";
1
+ import { r as patchMethods } from "../patchMethods-Cyb6MEOG.cjs";
2
2
 
3
3
  //#region src/patches/register.d.ts
4
4
  type PatchMethods = typeof patchMethods;
@@ -1,4 +1,4 @@
1
- import { r as patchMethods } from "../patchMethods-CxI_x-zv.js";
1
+ import { r as patchMethods } from "../patchMethods-C21iQqML.js";
2
2
 
3
3
  //#region src/patches/register.d.ts
4
4
  type PatchMethods = typeof patchMethods;
@@ -1,5 +1,5 @@
1
1
  import { h as autobind, t as Store } from "../store-D4q5zD7q.js";
2
- import { t as patchMethods } from "../patchMethods-D-Vmx93m.js";
2
+ import { t as patchMethods } from "../patchMethods-Cui462lc.js";
3
3
 
4
4
  //#region src/patches/register.ts
5
5
  Object.assign(Store.prototype, patchMethods);
@@ -1,5 +1,5 @@
1
1
  const require_store = require('../store-CPqOf4y5.cjs');
2
- const require_persist = require('../persist-CwKzFRM7.cjs');
2
+ const require_persist = require('../persist-CG1WHP6D.cjs');
3
3
 
4
4
  //#region src/persist/register.ts
5
5
  require_store.Store.addHook((store) => {
@@ -1,5 +1,5 @@
1
1
  import { t as Store } from "../store-D4q5zD7q.js";
2
- import { t as persist } from "../persist-CZhDrupc.js";
2
+ import { t as persist } from "../persist-CNA2sYtB.js";
3
3
 
4
4
  //#region src/persist/register.ts
5
5
  Store.addHook((store) => {
@@ -1,7 +1,7 @@
1
1
  const require_store = require('./store-CPqOf4y5.cjs');
2
2
  const require_propAccess = require('./propAccess-udIdjqwY.cjs');
3
- const require_patchMethods = require('./patchMethods-BfyJt9me.cjs');
4
- const require_extendedJson = require('./extendedJson-BwYSvpOA.cjs');
3
+ const require_patchMethods = require('./patchMethods-CZje49Dk.cjs');
4
+ const require_extendedJson = require('./extendedJson-DzXMFE1P.cjs');
5
5
 
6
6
  //#region src/lib/promiseChain.ts
7
7
  function promiseChain(value) {
@@ -257,4 +257,4 @@ Object.defineProperty(exports, 'persist', {
257
257
  return persist;
258
258
  }
259
259
  });
260
- //# sourceMappingURL=persist-CwKzFRM7.cjs.map
260
+ //# sourceMappingURL=persist-CG1WHP6D.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"persist-CwKzFRM7.cjs","names":["isPromise","value","entries: Map<KeyType, unknown>","path","isPromise","store: Store<T>","options: PersistOptions<T>","queue","castArrayPath","calcDuration","subscribePatches","path","shallowEqual","isPromise","fromExtendedJsonString","remove","set","get","toExtendedJsonString"],"sources":["../src/lib/promiseChain.ts","../src/persist/persistPathHelpers.ts","../src/persist/persistStorage.ts","../src/persist/persist.ts"],"sourcesContent":["import isPromise from '@lib/isPromise';\n\nexport interface Chain<T> {\n value: T;\n next<S>(fn: (value: Awaited<T>) => S): T extends Promise<any> ? Chain<Promise<S>> : Chain<S>;\n}\n\nexport default function promiseChain<T>(value: T | (() => T)): Chain<T> {\n if (value instanceof Function) {\n value = value();\n }\n\n return {\n value,\n next(fn) {\n const next = isPromise(value)\n ? value.then((value) => fn(value as Awaited<T>))\n : fn(value as Awaited<T>);\n\n return promiseChain(next) as any;\n },\n };\n}\n","import type { KeyType } from '@lib/path';\n\nexport const isAncestor = (ancestor: KeyType[], path: KeyType[]): boolean => {\n return (\n ancestor.length <= path.length &&\n ancestor.every((v, i) => v === '*' || path[i] === '*' || v === path[i])\n );\n};\n\nexport const split = (value: any, path: KeyType[]): { path: KeyType[]; value: unknown }[] => {\n const [first, ...rest] = path;\n if (first === undefined) return [{ path: [], value }];\n\n let entries: Map<KeyType, unknown>;\n if (value instanceof Map) {\n entries = value;\n } else if (value instanceof Set) {\n entries = new Map([...value].map((v, i) => [i, v]));\n } else if (Array.isArray(value)) {\n entries = new Map(value.map((v, i) => [i, v]));\n } else if (typeof value === 'object' && value !== null) {\n entries = new Map(Object.entries(value));\n } else {\n return [{ path: [], value }];\n }\n\n if (first === '*') {\n return [...entries].flatMap(([k, v]) =>\n split(v, rest).map(({ path, value }) => ({ path: [k, ...path], value })),\n );\n }\n\n const subValue = entries.get(first);\n if (subValue === undefined) return [{ path: [], value }];\n\n return split(subValue, rest).map(({ path, value }) => ({ path: [first, ...path], value }));\n};\n","import isPromise from '@lib/isPromise';\nimport promiseChain from '@lib/promiseChain';\n\nexport interface PersistStorageBase {\n getItem: (key: string) => string | null | Promise<string | null>;\n setItem: (key: string, value: string) => void | Promise<unknown>;\n removeItem: (key: string) => void | Promise<unknown>;\n}\n\nexport interface PersistStorageWithKeys extends PersistStorageBase {\n keys: () => string[] | Promise<string[]>;\n}\n\nexport interface PersistStorageWithLength extends PersistStorageBase {\n length: number | (() => number | Promise<number>);\n key: (keyIndex: number) => string | null | Promise<string | null>;\n}\n\nexport interface PersistStorageWithListItems extends PersistStorageBase {\n listItems: () => Map<string, string> | Promise<Map<string, string>>;\n}\n\nexport type PersistStorage =\n | PersistStorageWithKeys\n | PersistStorageWithLength\n | PersistStorageWithListItems;\n\nexport function normalizeStorage(storage: PersistStorage): PersistStorageWithListItems {\n return {\n getItem: storage.getItem.bind(storage),\n setItem: storage.setItem.bind(storage),\n removeItem: storage.removeItem.bind(storage),\n\n listItems() {\n if ('listItems' in storage) {\n return storage.listItems();\n }\n\n return promiseChain(() => {\n if ('keys' in storage) {\n return storage.keys();\n } else {\n return promiseChain(\n storage.length instanceof Function ? storage.length() : storage.length,\n )\n .next((length) => {\n const keys = Array.from({ length }, (_, index) => storage.key(index));\n return keys.some(isPromise) ? Promise.all(keys) : (keys as (string | null)[]);\n })\n .next((keys) => {\n return keys.filter((key): key is string => typeof key === 'string');\n }).value;\n }\n })\n .next((keys) => {\n const results = keys.map(\n (key) =>\n promiseChain(storage.getItem(key)).next((value) => [key, value] as const).value,\n );\n\n return results.some(isPromise)\n ? Promise.all(results)\n : (results as [string, string | null][]);\n })\n .next((results) => {\n return new Map(results.filter(([, value]) => value !== null) as [string, string][]);\n }).value;\n },\n };\n}\n","import { type Cancel, type Duration, type Store } from '@core';\nimport { calcDuration } from '@lib/duration';\nimport { shallowEqual } from '@lib/equals';\nimport { fromExtendedJsonString, toExtendedJsonString } from '@lib/extendedJson';\nimport isPromise from '@lib/isPromise';\nimport type { KeyType, WildcardPath } from '@lib/path';\nimport promiseChain from '@lib/promiseChain';\nimport { castArrayPath, get, remove, set } from '@lib/propAccess';\nimport { queue } from '@lib/queue';\nimport { subscribePatches } from '@patches/patchMethods';\nimport { isAncestor, split } from '@persist/persistPathHelpers';\nimport {\n normalizeStorage,\n type PersistStorage,\n type PersistStorageWithListItems,\n} from './persistStorage';\n\ntype PathOption<T> =\n | WildcardPath<T>\n | {\n path: WildcardPath<T>;\n // throttle?: Duration;\n };\n\ntype Key = { type: 'internal'; path: string } | { type: 'data'; path: KeyType[] };\n\nexport interface PersistOptions<T> {\n id: string;\n storage: PersistStorage;\n paths?: PathOption<T>[];\n throttle?: Duration;\n persistInitialState?: boolean;\n}\n\nexport class Persist<T> {\n readonly storage: PersistStorageWithListItems;\n readonly [Symbol.dispose]!: Cancel;\n\n readonly paths: {\n path: KeyType[];\n throttle?: number;\n }[];\n\n readonly initialized: Promise<void>;\n\n private resolveInitialized?: () => void;\n\n private channel: BroadcastChannel;\n\n private queue = queue();\n\n private handles = new Set<Cancel>();\n\n private stopped = false;\n\n private updateInProgress = new Map<string, unknown>();\n\n private prefix;\n\n constructor(\n public readonly store: Store<T>,\n public readonly options: PersistOptions<T>,\n ) {\n this.storage = normalizeStorage(options.storage);\n this.channel = new BroadcastChannel(`cross-state-persist_${options.id}`);\n this.prefix = `${options.id}:`;\n\n if (Symbol.dispose) {\n this[Symbol.dispose] = () => this.stop();\n }\n\n this.paths = (options.paths ?? [])\n .map<{\n path: KeyType[];\n throttle?: number;\n }>((p) => {\n if (isPlainPath(p)) {\n return {\n path: castArrayPath(p),\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n };\n }\n\n const _p = p as { path: KeyType[]; throttle?: Duration };\n\n return {\n path: castArrayPath(_p.path),\n throttle:\n (_p.throttle ? calcDuration(_p.throttle) : undefined) ??\n (options.throttle ? calcDuration(options.throttle) : undefined),\n };\n })\n .sort((a, b) => b.path.length - a.path.length);\n\n if (this.paths.length === 0) {\n this.paths.push({\n path: ['*'],\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n });\n }\n\n this.initialized = new Promise((resolve) => {\n this.resolveInitialized = resolve;\n });\n\n this.watchStore();\n this.watchStorage();\n }\n\n private watchStore() {\n const throttle = Math.min(...this.paths.map((p) => p.throttle ?? 0)) || undefined;\n\n const cancel = subscribePatches.apply(this.store as Store<unknown>, [\n (patches, reversePatches) => {\n let i = 0;\n for (const patch of patches) {\n const reversePatch = reversePatches[i++];\n\n const stringPath = JSON.stringify(patch.path);\n if (\n this.updateInProgress.has(stringPath) &&\n this.updateInProgress.get(stringPath) ===\n (patch.op === 'remove' ? undefined : patch.value)\n ) {\n continue;\n }\n\n const matchingPaths = this.paths.filter(\n (p) => isAncestor(p.path, patch.path) || isAncestor(patch.path, p.path),\n );\n\n for (const { path } of matchingPaths) {\n if (path.length <= patch.path.length) {\n const pathToSave = patch.path.slice(0, path.length);\n this.queue(() => this.save(pathToSave), pathToSave);\n } else if (patch.op === 'remove') {\n const subValues = split(\n reversePatch?.op === 'add' ? reversePatch.value : {},\n path.slice(patch.path.length),\n );\n\n for (const { path } of subValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n } else {\n const updatedValues = split(patch.value, path.slice(patch.path.length));\n const removedValues = split(\n reversePatch?.op !== 'remove' ? (reversePatch?.value ?? {}) : {},\n path.slice(patch.path.length),\n ).filter((v) => !updatedValues.some((u) => shallowEqual(u.path, v.path)));\n\n for (const { path } of updatedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n for (const { path } of removedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n }\n }\n }\n },\n { runNow: this.options.persistInitialState ?? false, passive: true, throttle },\n ]);\n\n this.handles.add(cancel);\n }\n\n private async watchStorage() {\n if (!this.options.persistInitialState) {\n let items = this.storage.listItems();\n if (isPromise(items)) {\n items = await items;\n }\n\n if (this.stopped) {\n return;\n }\n\n const toLoad = new Map(\n [...items.entries()]\n .sort((a, b) => b[1].length - a[1].length)\n .map(([key, value]) => [this.parseKey(key), value])\n .filter(([key]) => key) as [Key, string][],\n );\n\n this.queue(() => this.load(toLoad));\n }\n\n this.queue(() => this.resolveInitialized?.());\n\n const listener = (event: MessageEvent) => {\n this.queue(() => this.load([{ type: 'data', path: event.data }]));\n };\n\n this.channel.addEventListener('message', listener);\n this.handles.add(() => this.channel.removeEventListener('message', listener));\n }\n\n private buildKey({ type, path }: Key) {\n return `${this.prefix}${type === 'internal' ? path : JSON.stringify(path)}`;\n }\n\n private parseKey(key: string): Key | undefined {\n if (!key.startsWith(this.prefix)) {\n return;\n }\n\n key = key.slice(this.prefix.length);\n\n if (!key.startsWith('[')) {\n return { type: 'internal', path: key };\n }\n\n return { type: 'data', path: JSON.parse(key) as KeyType[] };\n }\n\n private load(items: Key[] | Map<Key, string>): void | Promise<void> {\n return promiseChain(() => {\n if (Array.isArray(items)) {\n return promiseChain(() => {\n const entries = items.map(\n (key) =>\n promiseChain(() => {\n return this.storage.getItem(this.buildKey(key));\n }).next((value) => [key, value] as const).value,\n );\n\n return entries.some(isPromise)\n ? Promise.all(entries)\n : (entries as [Key, string | null][]);\n }).next((entries) => {\n return entries.filter((entry) => entry !== null) as [Key, string][];\n }).value;\n } else {\n return [...items.entries()];\n }\n }).next((entries) => {\n if (this.stopped) {\n return;\n }\n\n const toWrite = entries\n .filter(([key, value]) => {\n if (key.type !== 'data' || !value) {\n return;\n }\n\n if (\n !this.paths.find(\n (p) =>\n (p.path.length === 1 && p.path[0] === '*' && key.path.length === 0) ||\n (p.path.length === key.path.length && isAncestor(p.path, key.path)),\n )\n ) {\n return null;\n }\n\n const inSaveQueue = this.queue\n .getRefs()\n .find((ref) => isAncestor(ref, key.path) || isAncestor(key.path, ref));\n return !inSaveQueue;\n })\n .map(([key, value]) => {\n try {\n return {\n path: key.path,\n value: !value || value === 'undefined' ? undefined : fromExtendedJsonString(value),\n };\n } catch {\n return undefined;\n }\n })\n .filter(Boolean) as { path: KeyType[]; value: unknown }[];\n\n if (toWrite.length > 0) {\n for (const { path, value } of toWrite) {\n this.updateInProgress.set(JSON.stringify(path), value);\n }\n\n this.store.set((state) => {\n for (const { path, value } of toWrite) {\n if (value === undefined) {\n state = remove(state, path as any);\n } else {\n state = set(state, path as any, value);\n }\n }\n\n return state;\n });\n\n this.updateInProgress.clear();\n }\n\n const versionEntry = entries.find(\n ([key]) => key.type === 'internal' && key.path === 'version',\n );\n if (versionEntry) {\n this.store.version = versionEntry[1];\n }\n }).value;\n }\n\n private save(path: KeyType[]): void | Promise<unknown> {\n const key = this.buildKey({ type: 'data', path });\n const value = get(this.store.get() as any, path);\n\n return promiseChain(value)\n .next((value) => {\n if (value === undefined) {\n return this.storage.removeItem(key);\n } else {\n return this.storage.setItem(key, toExtendedJsonString(value));\n }\n })\n .next(() => {\n this.channel.postMessage(path);\n\n if (this.store.version) {\n return this.storage.setItem(\n this.buildKey({ type: 'internal', path: 'version' }),\n this.store.version,\n );\n } else {\n return this.storage.removeItem(this.buildKey({ type: 'internal', path: 'version' }));\n }\n }).value;\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n\n for (const handle of this.handles) {\n handle();\n }\n\n await this.queue.whenDone();\n this.channel.close();\n }\n}\n\nexport function persist<T>(store: Store<T>, options: PersistOptions<T>): Persist<T> {\n return new Persist<T>(store, options);\n}\n\nfunction isPlainPath<T>(p: PathOption<T>): p is WildcardPath<T> & (KeyType[] | string) {\n return typeof p === 'string' || Array.isArray(p);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"persist-CG1WHP6D.cjs","names":["isPromise","value","entries: Map<KeyType, unknown>","path","isPromise","store: Store<T>","options: PersistOptions<T>","queue","castArrayPath","calcDuration","subscribePatches","path","shallowEqual","isPromise","fromExtendedJsonString","remove","set","get","toExtendedJsonString"],"sources":["../src/lib/promiseChain.ts","../src/persist/persistPathHelpers.ts","../src/persist/persistStorage.ts","../src/persist/persist.ts"],"sourcesContent":["import isPromise from '@lib/isPromise';\n\nexport interface Chain<T> {\n value: T;\n next<S>(fn: (value: Awaited<T>) => S): T extends Promise<any> ? Chain<Promise<S>> : Chain<S>;\n}\n\nexport default function promiseChain<T>(value: T | (() => T)): Chain<T> {\n if (value instanceof Function) {\n value = value();\n }\n\n return {\n value,\n next(fn) {\n const next = isPromise(value)\n ? value.then((value) => fn(value as Awaited<T>))\n : fn(value as Awaited<T>);\n\n return promiseChain(next) as any;\n },\n };\n}\n","import type { KeyType } from '@lib/path';\n\nexport const isAncestor = (ancestor: KeyType[], path: KeyType[]): boolean => {\n return (\n ancestor.length <= path.length &&\n ancestor.every((v, i) => v === '*' || path[i] === '*' || v === path[i])\n );\n};\n\nexport const split = (value: any, path: KeyType[]): { path: KeyType[]; value: unknown }[] => {\n const [first, ...rest] = path;\n if (first === undefined) return [{ path: [], value }];\n\n let entries: Map<KeyType, unknown>;\n if (value instanceof Map) {\n entries = value;\n } else if (value instanceof Set) {\n entries = new Map([...value].map((v, i) => [i, v]));\n } else if (Array.isArray(value)) {\n entries = new Map(value.map((v, i) => [i, v]));\n } else if (typeof value === 'object' && value !== null) {\n entries = new Map(Object.entries(value));\n } else {\n return [{ path: [], value }];\n }\n\n if (first === '*') {\n return [...entries].flatMap(([k, v]) =>\n split(v, rest).map(({ path, value }) => ({ path: [k, ...path], value })),\n );\n }\n\n const subValue = entries.get(first);\n if (subValue === undefined) return [{ path: [], value }];\n\n return split(subValue, rest).map(({ path, value }) => ({ path: [first, ...path], value }));\n};\n","import isPromise from '@lib/isPromise';\nimport promiseChain from '@lib/promiseChain';\n\nexport interface PersistStorageBase {\n getItem: (key: string) => string | null | Promise<string | null>;\n setItem: (key: string, value: string) => void | Promise<unknown>;\n removeItem: (key: string) => void | Promise<unknown>;\n}\n\nexport interface PersistStorageWithKeys extends PersistStorageBase {\n keys: () => string[] | Promise<string[]>;\n}\n\nexport interface PersistStorageWithLength extends PersistStorageBase {\n length: number | (() => number | Promise<number>);\n key: (keyIndex: number) => string | null | Promise<string | null>;\n}\n\nexport interface PersistStorageWithListItems extends PersistStorageBase {\n listItems: () => Map<string, string> | Promise<Map<string, string>>;\n}\n\nexport type PersistStorage =\n | PersistStorageWithKeys\n | PersistStorageWithLength\n | PersistStorageWithListItems;\n\nexport function normalizeStorage(storage: PersistStorage): PersistStorageWithListItems {\n return {\n getItem: storage.getItem.bind(storage),\n setItem: storage.setItem.bind(storage),\n removeItem: storage.removeItem.bind(storage),\n\n listItems() {\n if ('listItems' in storage) {\n return storage.listItems();\n }\n\n return promiseChain(() => {\n if ('keys' in storage) {\n return storage.keys();\n } else {\n return promiseChain(\n storage.length instanceof Function ? storage.length() : storage.length,\n )\n .next((length) => {\n const keys = Array.from({ length }, (_, index) => storage.key(index));\n return keys.some(isPromise) ? Promise.all(keys) : (keys as (string | null)[]);\n })\n .next((keys) => {\n return keys.filter((key): key is string => typeof key === 'string');\n }).value;\n }\n })\n .next((keys) => {\n const results = keys.map(\n (key) =>\n promiseChain(storage.getItem(key)).next((value) => [key, value] as const).value,\n );\n\n return results.some(isPromise)\n ? Promise.all(results)\n : (results as [string, string | null][]);\n })\n .next((results) => {\n return new Map(results.filter(([, value]) => value !== null) as [string, string][]);\n }).value;\n },\n };\n}\n","import { type Cancel, type Duration, type Store } from '@core';\nimport { calcDuration } from '@lib/duration';\nimport { shallowEqual } from '@lib/equals';\nimport { fromExtendedJsonString, toExtendedJsonString } from '@lib/extendedJson';\nimport isPromise from '@lib/isPromise';\nimport type { KeyType, WildcardPath } from '@lib/path';\nimport promiseChain from '@lib/promiseChain';\nimport { castArrayPath, get, remove, set } from '@lib/propAccess';\nimport { queue } from '@lib/queue';\nimport { subscribePatches } from '@patches/patchMethods';\nimport { isAncestor, split } from '@persist/persistPathHelpers';\nimport {\n normalizeStorage,\n type PersistStorage,\n type PersistStorageWithListItems,\n} from './persistStorage';\n\ntype PathOption<T> =\n | WildcardPath<T>\n | {\n path: WildcardPath<T>;\n // throttle?: Duration;\n };\n\ntype Key = { type: 'internal'; path: string } | { type: 'data'; path: KeyType[] };\n\nexport interface PersistOptions<T> {\n id: string;\n storage: PersistStorage;\n paths?: PathOption<T>[];\n throttle?: Duration;\n persistInitialState?: boolean;\n}\n\nexport class Persist<T> {\n readonly storage: PersistStorageWithListItems;\n readonly [Symbol.dispose]!: Cancel;\n\n readonly paths: {\n path: KeyType[];\n throttle?: number;\n }[];\n\n readonly initialized: Promise<void>;\n\n private resolveInitialized?: () => void;\n\n private channel: BroadcastChannel;\n\n private queue = queue();\n\n private handles = new Set<Cancel>();\n\n private stopped = false;\n\n private updateInProgress = new Map<string, unknown>();\n\n private prefix;\n\n constructor(\n public readonly store: Store<T>,\n public readonly options: PersistOptions<T>,\n ) {\n this.storage = normalizeStorage(options.storage);\n this.channel = new BroadcastChannel(`cross-state-persist_${options.id}`);\n this.prefix = `${options.id}:`;\n\n if (Symbol.dispose) {\n this[Symbol.dispose] = () => this.stop();\n }\n\n this.paths = (options.paths ?? [])\n .map<{\n path: KeyType[];\n throttle?: number;\n }>((p) => {\n if (isPlainPath(p)) {\n return {\n path: castArrayPath(p),\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n };\n }\n\n const _p = p as { path: KeyType[]; throttle?: Duration };\n\n return {\n path: castArrayPath(_p.path),\n throttle:\n (_p.throttle ? calcDuration(_p.throttle) : undefined) ??\n (options.throttle ? calcDuration(options.throttle) : undefined),\n };\n })\n .sort((a, b) => b.path.length - a.path.length);\n\n if (this.paths.length === 0) {\n this.paths.push({\n path: ['*'],\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n });\n }\n\n this.initialized = new Promise((resolve) => {\n this.resolveInitialized = resolve;\n });\n\n this.watchStore();\n this.watchStorage();\n }\n\n private watchStore() {\n const throttle = Math.min(...this.paths.map((p) => p.throttle ?? 0)) || undefined;\n\n const cancel = subscribePatches.apply(this.store as Store<unknown>, [\n (patches, reversePatches) => {\n let i = 0;\n for (const patch of patches) {\n const reversePatch = reversePatches[i++];\n\n const stringPath = JSON.stringify(patch.path);\n if (\n this.updateInProgress.has(stringPath) &&\n this.updateInProgress.get(stringPath) ===\n (patch.op === 'remove' ? undefined : patch.value)\n ) {\n continue;\n }\n\n const matchingPaths = this.paths.filter(\n (p) => isAncestor(p.path, patch.path) || isAncestor(patch.path, p.path),\n );\n\n for (const { path } of matchingPaths) {\n if (path.length <= patch.path.length) {\n const pathToSave = patch.path.slice(0, path.length);\n this.queue(() => this.save(pathToSave), pathToSave);\n } else if (patch.op === 'remove') {\n const subValues = split(\n reversePatch?.op === 'add' ? reversePatch.value : {},\n path.slice(patch.path.length),\n );\n\n for (const { path } of subValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n } else {\n const updatedValues = split(patch.value, path.slice(patch.path.length));\n const removedValues = split(\n reversePatch?.op !== 'remove' ? (reversePatch?.value ?? {}) : {},\n path.slice(patch.path.length),\n ).filter((v) => !updatedValues.some((u) => shallowEqual(u.path, v.path)));\n\n for (const { path } of updatedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n for (const { path } of removedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n }\n }\n }\n },\n { runNow: this.options.persistInitialState ?? false, passive: true, throttle },\n ]);\n\n this.handles.add(cancel);\n }\n\n private async watchStorage() {\n if (!this.options.persistInitialState) {\n let items = this.storage.listItems();\n if (isPromise(items)) {\n items = await items;\n }\n\n if (this.stopped) {\n return;\n }\n\n const toLoad = new Map(\n [...items.entries()]\n .sort((a, b) => b[1].length - a[1].length)\n .map(([key, value]) => [this.parseKey(key), value])\n .filter(([key]) => key) as [Key, string][],\n );\n\n this.queue(() => this.load(toLoad));\n }\n\n this.queue(() => this.resolveInitialized?.());\n\n const listener = (event: MessageEvent) => {\n this.queue(() => this.load([{ type: 'data', path: event.data }]));\n };\n\n this.channel.addEventListener('message', listener);\n this.handles.add(() => this.channel.removeEventListener('message', listener));\n }\n\n private buildKey({ type, path }: Key) {\n return `${this.prefix}${type === 'internal' ? path : JSON.stringify(path)}`;\n }\n\n private parseKey(key: string): Key | undefined {\n if (!key.startsWith(this.prefix)) {\n return;\n }\n\n key = key.slice(this.prefix.length);\n\n if (!key.startsWith('[')) {\n return { type: 'internal', path: key };\n }\n\n return { type: 'data', path: JSON.parse(key) as KeyType[] };\n }\n\n private load(items: Key[] | Map<Key, string>): void | Promise<void> {\n return promiseChain(() => {\n if (Array.isArray(items)) {\n return promiseChain(() => {\n const entries = items.map(\n (key) =>\n promiseChain(() => {\n return this.storage.getItem(this.buildKey(key));\n }).next((value) => [key, value] as const).value,\n );\n\n return entries.some(isPromise)\n ? Promise.all(entries)\n : (entries as [Key, string | null][]);\n }).next((entries) => {\n return entries.filter((entry) => entry !== null) as [Key, string][];\n }).value;\n } else {\n return [...items.entries()];\n }\n }).next((entries) => {\n if (this.stopped) {\n return;\n }\n\n const toWrite = entries\n .filter(([key, value]) => {\n if (key.type !== 'data' || !value) {\n return;\n }\n\n if (\n !this.paths.find(\n (p) =>\n (p.path.length === 1 && p.path[0] === '*' && key.path.length === 0) ||\n (p.path.length === key.path.length && isAncestor(p.path, key.path)),\n )\n ) {\n return null;\n }\n\n const inSaveQueue = this.queue\n .getRefs()\n .find((ref) => isAncestor(ref, key.path) || isAncestor(key.path, ref));\n return !inSaveQueue;\n })\n .map(([key, value]) => {\n try {\n return {\n path: key.path,\n value: !value || value === 'undefined' ? undefined : fromExtendedJsonString(value),\n };\n } catch {\n return undefined;\n }\n })\n .filter(Boolean) as { path: KeyType[]; value: unknown }[];\n\n if (toWrite.length > 0) {\n for (const { path, value } of toWrite) {\n this.updateInProgress.set(JSON.stringify(path), value);\n }\n\n this.store.set((state) => {\n for (const { path, value } of toWrite) {\n if (value === undefined) {\n state = remove(state, path as any);\n } else {\n state = set(state, path as any, value);\n }\n }\n\n return state;\n });\n\n this.updateInProgress.clear();\n }\n\n const versionEntry = entries.find(\n ([key]) => key.type === 'internal' && key.path === 'version',\n );\n if (versionEntry) {\n this.store.version = versionEntry[1];\n }\n }).value;\n }\n\n private save(path: KeyType[]): void | Promise<unknown> {\n const key = this.buildKey({ type: 'data', path });\n const value = get(this.store.get() as any, path);\n\n return promiseChain(value)\n .next((value) => {\n if (value === undefined) {\n return this.storage.removeItem(key);\n } else {\n return this.storage.setItem(key, toExtendedJsonString(value));\n }\n })\n .next(() => {\n this.channel.postMessage(path);\n\n if (this.store.version) {\n return this.storage.setItem(\n this.buildKey({ type: 'internal', path: 'version' }),\n this.store.version,\n );\n } else {\n return this.storage.removeItem(this.buildKey({ type: 'internal', path: 'version' }));\n }\n }).value;\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n\n for (const handle of this.handles) {\n handle();\n }\n\n await this.queue.whenDone();\n this.channel.close();\n }\n}\n\nexport function persist<T>(store: Store<T>, options: PersistOptions<T>): Persist<T> {\n return new Persist<T>(store, options);\n}\n\nfunction isPlainPath<T>(p: PathOption<T>): p is WildcardPath<T> & (KeyType[] | string) {\n return typeof p === 'string' || Array.isArray(p);\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { d as queue, m as calcDuration, p as isPromise } from "./store-D4q5zD7q.js";
2
2
  import { a as set, i as remove, l as shallowEqual, n as get, t as castArrayPath } from "./propAccess-BxCKNeOj.js";
3
- import { n as subscribePatches } from "./patchMethods-D-Vmx93m.js";
4
- import { i as toExtendedJsonString, n as fromExtendedJsonString } from "./extendedJson-B1OEqZtF.js";
3
+ import { n as subscribePatches } from "./patchMethods-Cui462lc.js";
4
+ import { i as toExtendedJsonString, n as fromExtendedJsonString } from "./extendedJson-DA3RQ_ly.js";
5
5
 
6
6
  //#region src/lib/promiseChain.ts
7
7
  function promiseChain(value) {
@@ -252,4 +252,4 @@ function isPlainPath(p) {
252
252
 
253
253
  //#endregion
254
254
  export { persist as t };
255
- //# sourceMappingURL=persist-CZhDrupc.js.map
255
+ //# sourceMappingURL=persist-CNA2sYtB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"persist-CZhDrupc.js","names":["value","entries: Map<KeyType, unknown>","path","store: Store<T>","options: PersistOptions<T>","path"],"sources":["../src/lib/promiseChain.ts","../src/persist/persistPathHelpers.ts","../src/persist/persistStorage.ts","../src/persist/persist.ts"],"sourcesContent":["import isPromise from '@lib/isPromise';\n\nexport interface Chain<T> {\n value: T;\n next<S>(fn: (value: Awaited<T>) => S): T extends Promise<any> ? Chain<Promise<S>> : Chain<S>;\n}\n\nexport default function promiseChain<T>(value: T | (() => T)): Chain<T> {\n if (value instanceof Function) {\n value = value();\n }\n\n return {\n value,\n next(fn) {\n const next = isPromise(value)\n ? value.then((value) => fn(value as Awaited<T>))\n : fn(value as Awaited<T>);\n\n return promiseChain(next) as any;\n },\n };\n}\n","import type { KeyType } from '@lib/path';\n\nexport const isAncestor = (ancestor: KeyType[], path: KeyType[]): boolean => {\n return (\n ancestor.length <= path.length &&\n ancestor.every((v, i) => v === '*' || path[i] === '*' || v === path[i])\n );\n};\n\nexport const split = (value: any, path: KeyType[]): { path: KeyType[]; value: unknown }[] => {\n const [first, ...rest] = path;\n if (first === undefined) return [{ path: [], value }];\n\n let entries: Map<KeyType, unknown>;\n if (value instanceof Map) {\n entries = value;\n } else if (value instanceof Set) {\n entries = new Map([...value].map((v, i) => [i, v]));\n } else if (Array.isArray(value)) {\n entries = new Map(value.map((v, i) => [i, v]));\n } else if (typeof value === 'object' && value !== null) {\n entries = new Map(Object.entries(value));\n } else {\n return [{ path: [], value }];\n }\n\n if (first === '*') {\n return [...entries].flatMap(([k, v]) =>\n split(v, rest).map(({ path, value }) => ({ path: [k, ...path], value })),\n );\n }\n\n const subValue = entries.get(first);\n if (subValue === undefined) return [{ path: [], value }];\n\n return split(subValue, rest).map(({ path, value }) => ({ path: [first, ...path], value }));\n};\n","import isPromise from '@lib/isPromise';\nimport promiseChain from '@lib/promiseChain';\n\nexport interface PersistStorageBase {\n getItem: (key: string) => string | null | Promise<string | null>;\n setItem: (key: string, value: string) => void | Promise<unknown>;\n removeItem: (key: string) => void | Promise<unknown>;\n}\n\nexport interface PersistStorageWithKeys extends PersistStorageBase {\n keys: () => string[] | Promise<string[]>;\n}\n\nexport interface PersistStorageWithLength extends PersistStorageBase {\n length: number | (() => number | Promise<number>);\n key: (keyIndex: number) => string | null | Promise<string | null>;\n}\n\nexport interface PersistStorageWithListItems extends PersistStorageBase {\n listItems: () => Map<string, string> | Promise<Map<string, string>>;\n}\n\nexport type PersistStorage =\n | PersistStorageWithKeys\n | PersistStorageWithLength\n | PersistStorageWithListItems;\n\nexport function normalizeStorage(storage: PersistStorage): PersistStorageWithListItems {\n return {\n getItem: storage.getItem.bind(storage),\n setItem: storage.setItem.bind(storage),\n removeItem: storage.removeItem.bind(storage),\n\n listItems() {\n if ('listItems' in storage) {\n return storage.listItems();\n }\n\n return promiseChain(() => {\n if ('keys' in storage) {\n return storage.keys();\n } else {\n return promiseChain(\n storage.length instanceof Function ? storage.length() : storage.length,\n )\n .next((length) => {\n const keys = Array.from({ length }, (_, index) => storage.key(index));\n return keys.some(isPromise) ? Promise.all(keys) : (keys as (string | null)[]);\n })\n .next((keys) => {\n return keys.filter((key): key is string => typeof key === 'string');\n }).value;\n }\n })\n .next((keys) => {\n const results = keys.map(\n (key) =>\n promiseChain(storage.getItem(key)).next((value) => [key, value] as const).value,\n );\n\n return results.some(isPromise)\n ? Promise.all(results)\n : (results as [string, string | null][]);\n })\n .next((results) => {\n return new Map(results.filter(([, value]) => value !== null) as [string, string][]);\n }).value;\n },\n };\n}\n","import { type Cancel, type Duration, type Store } from '@core';\nimport { calcDuration } from '@lib/duration';\nimport { shallowEqual } from '@lib/equals';\nimport { fromExtendedJsonString, toExtendedJsonString } from '@lib/extendedJson';\nimport isPromise from '@lib/isPromise';\nimport type { KeyType, WildcardPath } from '@lib/path';\nimport promiseChain from '@lib/promiseChain';\nimport { castArrayPath, get, remove, set } from '@lib/propAccess';\nimport { queue } from '@lib/queue';\nimport { subscribePatches } from '@patches/patchMethods';\nimport { isAncestor, split } from '@persist/persistPathHelpers';\nimport {\n normalizeStorage,\n type PersistStorage,\n type PersistStorageWithListItems,\n} from './persistStorage';\n\ntype PathOption<T> =\n | WildcardPath<T>\n | {\n path: WildcardPath<T>;\n // throttle?: Duration;\n };\n\ntype Key = { type: 'internal'; path: string } | { type: 'data'; path: KeyType[] };\n\nexport interface PersistOptions<T> {\n id: string;\n storage: PersistStorage;\n paths?: PathOption<T>[];\n throttle?: Duration;\n persistInitialState?: boolean;\n}\n\nexport class Persist<T> {\n readonly storage: PersistStorageWithListItems;\n readonly [Symbol.dispose]!: Cancel;\n\n readonly paths: {\n path: KeyType[];\n throttle?: number;\n }[];\n\n readonly initialized: Promise<void>;\n\n private resolveInitialized?: () => void;\n\n private channel: BroadcastChannel;\n\n private queue = queue();\n\n private handles = new Set<Cancel>();\n\n private stopped = false;\n\n private updateInProgress = new Map<string, unknown>();\n\n private prefix;\n\n constructor(\n public readonly store: Store<T>,\n public readonly options: PersistOptions<T>,\n ) {\n this.storage = normalizeStorage(options.storage);\n this.channel = new BroadcastChannel(`cross-state-persist_${options.id}`);\n this.prefix = `${options.id}:`;\n\n if (Symbol.dispose) {\n this[Symbol.dispose] = () => this.stop();\n }\n\n this.paths = (options.paths ?? [])\n .map<{\n path: KeyType[];\n throttle?: number;\n }>((p) => {\n if (isPlainPath(p)) {\n return {\n path: castArrayPath(p),\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n };\n }\n\n const _p = p as { path: KeyType[]; throttle?: Duration };\n\n return {\n path: castArrayPath(_p.path),\n throttle:\n (_p.throttle ? calcDuration(_p.throttle) : undefined) ??\n (options.throttle ? calcDuration(options.throttle) : undefined),\n };\n })\n .sort((a, b) => b.path.length - a.path.length);\n\n if (this.paths.length === 0) {\n this.paths.push({\n path: ['*'],\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n });\n }\n\n this.initialized = new Promise((resolve) => {\n this.resolveInitialized = resolve;\n });\n\n this.watchStore();\n this.watchStorage();\n }\n\n private watchStore() {\n const throttle = Math.min(...this.paths.map((p) => p.throttle ?? 0)) || undefined;\n\n const cancel = subscribePatches.apply(this.store as Store<unknown>, [\n (patches, reversePatches) => {\n let i = 0;\n for (const patch of patches) {\n const reversePatch = reversePatches[i++];\n\n const stringPath = JSON.stringify(patch.path);\n if (\n this.updateInProgress.has(stringPath) &&\n this.updateInProgress.get(stringPath) ===\n (patch.op === 'remove' ? undefined : patch.value)\n ) {\n continue;\n }\n\n const matchingPaths = this.paths.filter(\n (p) => isAncestor(p.path, patch.path) || isAncestor(patch.path, p.path),\n );\n\n for (const { path } of matchingPaths) {\n if (path.length <= patch.path.length) {\n const pathToSave = patch.path.slice(0, path.length);\n this.queue(() => this.save(pathToSave), pathToSave);\n } else if (patch.op === 'remove') {\n const subValues = split(\n reversePatch?.op === 'add' ? reversePatch.value : {},\n path.slice(patch.path.length),\n );\n\n for (const { path } of subValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n } else {\n const updatedValues = split(patch.value, path.slice(patch.path.length));\n const removedValues = split(\n reversePatch?.op !== 'remove' ? (reversePatch?.value ?? {}) : {},\n path.slice(patch.path.length),\n ).filter((v) => !updatedValues.some((u) => shallowEqual(u.path, v.path)));\n\n for (const { path } of updatedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n for (const { path } of removedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n }\n }\n }\n },\n { runNow: this.options.persistInitialState ?? false, passive: true, throttle },\n ]);\n\n this.handles.add(cancel);\n }\n\n private async watchStorage() {\n if (!this.options.persistInitialState) {\n let items = this.storage.listItems();\n if (isPromise(items)) {\n items = await items;\n }\n\n if (this.stopped) {\n return;\n }\n\n const toLoad = new Map(\n [...items.entries()]\n .sort((a, b) => b[1].length - a[1].length)\n .map(([key, value]) => [this.parseKey(key), value])\n .filter(([key]) => key) as [Key, string][],\n );\n\n this.queue(() => this.load(toLoad));\n }\n\n this.queue(() => this.resolveInitialized?.());\n\n const listener = (event: MessageEvent) => {\n this.queue(() => this.load([{ type: 'data', path: event.data }]));\n };\n\n this.channel.addEventListener('message', listener);\n this.handles.add(() => this.channel.removeEventListener('message', listener));\n }\n\n private buildKey({ type, path }: Key) {\n return `${this.prefix}${type === 'internal' ? path : JSON.stringify(path)}`;\n }\n\n private parseKey(key: string): Key | undefined {\n if (!key.startsWith(this.prefix)) {\n return;\n }\n\n key = key.slice(this.prefix.length);\n\n if (!key.startsWith('[')) {\n return { type: 'internal', path: key };\n }\n\n return { type: 'data', path: JSON.parse(key) as KeyType[] };\n }\n\n private load(items: Key[] | Map<Key, string>): void | Promise<void> {\n return promiseChain(() => {\n if (Array.isArray(items)) {\n return promiseChain(() => {\n const entries = items.map(\n (key) =>\n promiseChain(() => {\n return this.storage.getItem(this.buildKey(key));\n }).next((value) => [key, value] as const).value,\n );\n\n return entries.some(isPromise)\n ? Promise.all(entries)\n : (entries as [Key, string | null][]);\n }).next((entries) => {\n return entries.filter((entry) => entry !== null) as [Key, string][];\n }).value;\n } else {\n return [...items.entries()];\n }\n }).next((entries) => {\n if (this.stopped) {\n return;\n }\n\n const toWrite = entries\n .filter(([key, value]) => {\n if (key.type !== 'data' || !value) {\n return;\n }\n\n if (\n !this.paths.find(\n (p) =>\n (p.path.length === 1 && p.path[0] === '*' && key.path.length === 0) ||\n (p.path.length === key.path.length && isAncestor(p.path, key.path)),\n )\n ) {\n return null;\n }\n\n const inSaveQueue = this.queue\n .getRefs()\n .find((ref) => isAncestor(ref, key.path) || isAncestor(key.path, ref));\n return !inSaveQueue;\n })\n .map(([key, value]) => {\n try {\n return {\n path: key.path,\n value: !value || value === 'undefined' ? undefined : fromExtendedJsonString(value),\n };\n } catch {\n return undefined;\n }\n })\n .filter(Boolean) as { path: KeyType[]; value: unknown }[];\n\n if (toWrite.length > 0) {\n for (const { path, value } of toWrite) {\n this.updateInProgress.set(JSON.stringify(path), value);\n }\n\n this.store.set((state) => {\n for (const { path, value } of toWrite) {\n if (value === undefined) {\n state = remove(state, path as any);\n } else {\n state = set(state, path as any, value);\n }\n }\n\n return state;\n });\n\n this.updateInProgress.clear();\n }\n\n const versionEntry = entries.find(\n ([key]) => key.type === 'internal' && key.path === 'version',\n );\n if (versionEntry) {\n this.store.version = versionEntry[1];\n }\n }).value;\n }\n\n private save(path: KeyType[]): void | Promise<unknown> {\n const key = this.buildKey({ type: 'data', path });\n const value = get(this.store.get() as any, path);\n\n return promiseChain(value)\n .next((value) => {\n if (value === undefined) {\n return this.storage.removeItem(key);\n } else {\n return this.storage.setItem(key, toExtendedJsonString(value));\n }\n })\n .next(() => {\n this.channel.postMessage(path);\n\n if (this.store.version) {\n return this.storage.setItem(\n this.buildKey({ type: 'internal', path: 'version' }),\n this.store.version,\n );\n } else {\n return this.storage.removeItem(this.buildKey({ type: 'internal', path: 'version' }));\n }\n }).value;\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n\n for (const handle of this.handles) {\n handle();\n }\n\n await this.queue.whenDone();\n this.channel.close();\n }\n}\n\nexport function persist<T>(store: Store<T>, options: PersistOptions<T>): Persist<T> {\n return new Persist<T>(store, options);\n}\n\nfunction isPlainPath<T>(p: PathOption<T>): p is WildcardPath<T> & (KeyType[] | string) {\n return typeof p === 'string' || Array.isArray(p);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"persist-CNA2sYtB.js","names":["value","entries: Map<KeyType, unknown>","path","store: Store<T>","options: PersistOptions<T>","path"],"sources":["../src/lib/promiseChain.ts","../src/persist/persistPathHelpers.ts","../src/persist/persistStorage.ts","../src/persist/persist.ts"],"sourcesContent":["import isPromise from '@lib/isPromise';\n\nexport interface Chain<T> {\n value: T;\n next<S>(fn: (value: Awaited<T>) => S): T extends Promise<any> ? Chain<Promise<S>> : Chain<S>;\n}\n\nexport default function promiseChain<T>(value: T | (() => T)): Chain<T> {\n if (value instanceof Function) {\n value = value();\n }\n\n return {\n value,\n next(fn) {\n const next = isPromise(value)\n ? value.then((value) => fn(value as Awaited<T>))\n : fn(value as Awaited<T>);\n\n return promiseChain(next) as any;\n },\n };\n}\n","import type { KeyType } from '@lib/path';\n\nexport const isAncestor = (ancestor: KeyType[], path: KeyType[]): boolean => {\n return (\n ancestor.length <= path.length &&\n ancestor.every((v, i) => v === '*' || path[i] === '*' || v === path[i])\n );\n};\n\nexport const split = (value: any, path: KeyType[]): { path: KeyType[]; value: unknown }[] => {\n const [first, ...rest] = path;\n if (first === undefined) return [{ path: [], value }];\n\n let entries: Map<KeyType, unknown>;\n if (value instanceof Map) {\n entries = value;\n } else if (value instanceof Set) {\n entries = new Map([...value].map((v, i) => [i, v]));\n } else if (Array.isArray(value)) {\n entries = new Map(value.map((v, i) => [i, v]));\n } else if (typeof value === 'object' && value !== null) {\n entries = new Map(Object.entries(value));\n } else {\n return [{ path: [], value }];\n }\n\n if (first === '*') {\n return [...entries].flatMap(([k, v]) =>\n split(v, rest).map(({ path, value }) => ({ path: [k, ...path], value })),\n );\n }\n\n const subValue = entries.get(first);\n if (subValue === undefined) return [{ path: [], value }];\n\n return split(subValue, rest).map(({ path, value }) => ({ path: [first, ...path], value }));\n};\n","import isPromise from '@lib/isPromise';\nimport promiseChain from '@lib/promiseChain';\n\nexport interface PersistStorageBase {\n getItem: (key: string) => string | null | Promise<string | null>;\n setItem: (key: string, value: string) => void | Promise<unknown>;\n removeItem: (key: string) => void | Promise<unknown>;\n}\n\nexport interface PersistStorageWithKeys extends PersistStorageBase {\n keys: () => string[] | Promise<string[]>;\n}\n\nexport interface PersistStorageWithLength extends PersistStorageBase {\n length: number | (() => number | Promise<number>);\n key: (keyIndex: number) => string | null | Promise<string | null>;\n}\n\nexport interface PersistStorageWithListItems extends PersistStorageBase {\n listItems: () => Map<string, string> | Promise<Map<string, string>>;\n}\n\nexport type PersistStorage =\n | PersistStorageWithKeys\n | PersistStorageWithLength\n | PersistStorageWithListItems;\n\nexport function normalizeStorage(storage: PersistStorage): PersistStorageWithListItems {\n return {\n getItem: storage.getItem.bind(storage),\n setItem: storage.setItem.bind(storage),\n removeItem: storage.removeItem.bind(storage),\n\n listItems() {\n if ('listItems' in storage) {\n return storage.listItems();\n }\n\n return promiseChain(() => {\n if ('keys' in storage) {\n return storage.keys();\n } else {\n return promiseChain(\n storage.length instanceof Function ? storage.length() : storage.length,\n )\n .next((length) => {\n const keys = Array.from({ length }, (_, index) => storage.key(index));\n return keys.some(isPromise) ? Promise.all(keys) : (keys as (string | null)[]);\n })\n .next((keys) => {\n return keys.filter((key): key is string => typeof key === 'string');\n }).value;\n }\n })\n .next((keys) => {\n const results = keys.map(\n (key) =>\n promiseChain(storage.getItem(key)).next((value) => [key, value] as const).value,\n );\n\n return results.some(isPromise)\n ? Promise.all(results)\n : (results as [string, string | null][]);\n })\n .next((results) => {\n return new Map(results.filter(([, value]) => value !== null) as [string, string][]);\n }).value;\n },\n };\n}\n","import { type Cancel, type Duration, type Store } from '@core';\nimport { calcDuration } from '@lib/duration';\nimport { shallowEqual } from '@lib/equals';\nimport { fromExtendedJsonString, toExtendedJsonString } from '@lib/extendedJson';\nimport isPromise from '@lib/isPromise';\nimport type { KeyType, WildcardPath } from '@lib/path';\nimport promiseChain from '@lib/promiseChain';\nimport { castArrayPath, get, remove, set } from '@lib/propAccess';\nimport { queue } from '@lib/queue';\nimport { subscribePatches } from '@patches/patchMethods';\nimport { isAncestor, split } from '@persist/persistPathHelpers';\nimport {\n normalizeStorage,\n type PersistStorage,\n type PersistStorageWithListItems,\n} from './persistStorage';\n\ntype PathOption<T> =\n | WildcardPath<T>\n | {\n path: WildcardPath<T>;\n // throttle?: Duration;\n };\n\ntype Key = { type: 'internal'; path: string } | { type: 'data'; path: KeyType[] };\n\nexport interface PersistOptions<T> {\n id: string;\n storage: PersistStorage;\n paths?: PathOption<T>[];\n throttle?: Duration;\n persistInitialState?: boolean;\n}\n\nexport class Persist<T> {\n readonly storage: PersistStorageWithListItems;\n readonly [Symbol.dispose]!: Cancel;\n\n readonly paths: {\n path: KeyType[];\n throttle?: number;\n }[];\n\n readonly initialized: Promise<void>;\n\n private resolveInitialized?: () => void;\n\n private channel: BroadcastChannel;\n\n private queue = queue();\n\n private handles = new Set<Cancel>();\n\n private stopped = false;\n\n private updateInProgress = new Map<string, unknown>();\n\n private prefix;\n\n constructor(\n public readonly store: Store<T>,\n public readonly options: PersistOptions<T>,\n ) {\n this.storage = normalizeStorage(options.storage);\n this.channel = new BroadcastChannel(`cross-state-persist_${options.id}`);\n this.prefix = `${options.id}:`;\n\n if (Symbol.dispose) {\n this[Symbol.dispose] = () => this.stop();\n }\n\n this.paths = (options.paths ?? [])\n .map<{\n path: KeyType[];\n throttle?: number;\n }>((p) => {\n if (isPlainPath(p)) {\n return {\n path: castArrayPath(p),\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n };\n }\n\n const _p = p as { path: KeyType[]; throttle?: Duration };\n\n return {\n path: castArrayPath(_p.path),\n throttle:\n (_p.throttle ? calcDuration(_p.throttle) : undefined) ??\n (options.throttle ? calcDuration(options.throttle) : undefined),\n };\n })\n .sort((a, b) => b.path.length - a.path.length);\n\n if (this.paths.length === 0) {\n this.paths.push({\n path: ['*'],\n throttle: options.throttle ? calcDuration(options.throttle) : undefined,\n });\n }\n\n this.initialized = new Promise((resolve) => {\n this.resolveInitialized = resolve;\n });\n\n this.watchStore();\n this.watchStorage();\n }\n\n private watchStore() {\n const throttle = Math.min(...this.paths.map((p) => p.throttle ?? 0)) || undefined;\n\n const cancel = subscribePatches.apply(this.store as Store<unknown>, [\n (patches, reversePatches) => {\n let i = 0;\n for (const patch of patches) {\n const reversePatch = reversePatches[i++];\n\n const stringPath = JSON.stringify(patch.path);\n if (\n this.updateInProgress.has(stringPath) &&\n this.updateInProgress.get(stringPath) ===\n (patch.op === 'remove' ? undefined : patch.value)\n ) {\n continue;\n }\n\n const matchingPaths = this.paths.filter(\n (p) => isAncestor(p.path, patch.path) || isAncestor(patch.path, p.path),\n );\n\n for (const { path } of matchingPaths) {\n if (path.length <= patch.path.length) {\n const pathToSave = patch.path.slice(0, path.length);\n this.queue(() => this.save(pathToSave), pathToSave);\n } else if (patch.op === 'remove') {\n const subValues = split(\n reversePatch?.op === 'add' ? reversePatch.value : {},\n path.slice(patch.path.length),\n );\n\n for (const { path } of subValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n } else {\n const updatedValues = split(patch.value, path.slice(patch.path.length));\n const removedValues = split(\n reversePatch?.op !== 'remove' ? (reversePatch?.value ?? {}) : {},\n path.slice(patch.path.length),\n ).filter((v) => !updatedValues.some((u) => shallowEqual(u.path, v.path)));\n\n for (const { path } of updatedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n for (const { path } of removedValues) {\n this.queue(() => this.save([...patch.path, ...path]), [...patch.path, ...path]);\n }\n }\n }\n }\n },\n { runNow: this.options.persistInitialState ?? false, passive: true, throttle },\n ]);\n\n this.handles.add(cancel);\n }\n\n private async watchStorage() {\n if (!this.options.persistInitialState) {\n let items = this.storage.listItems();\n if (isPromise(items)) {\n items = await items;\n }\n\n if (this.stopped) {\n return;\n }\n\n const toLoad = new Map(\n [...items.entries()]\n .sort((a, b) => b[1].length - a[1].length)\n .map(([key, value]) => [this.parseKey(key), value])\n .filter(([key]) => key) as [Key, string][],\n );\n\n this.queue(() => this.load(toLoad));\n }\n\n this.queue(() => this.resolveInitialized?.());\n\n const listener = (event: MessageEvent) => {\n this.queue(() => this.load([{ type: 'data', path: event.data }]));\n };\n\n this.channel.addEventListener('message', listener);\n this.handles.add(() => this.channel.removeEventListener('message', listener));\n }\n\n private buildKey({ type, path }: Key) {\n return `${this.prefix}${type === 'internal' ? path : JSON.stringify(path)}`;\n }\n\n private parseKey(key: string): Key | undefined {\n if (!key.startsWith(this.prefix)) {\n return;\n }\n\n key = key.slice(this.prefix.length);\n\n if (!key.startsWith('[')) {\n return { type: 'internal', path: key };\n }\n\n return { type: 'data', path: JSON.parse(key) as KeyType[] };\n }\n\n private load(items: Key[] | Map<Key, string>): void | Promise<void> {\n return promiseChain(() => {\n if (Array.isArray(items)) {\n return promiseChain(() => {\n const entries = items.map(\n (key) =>\n promiseChain(() => {\n return this.storage.getItem(this.buildKey(key));\n }).next((value) => [key, value] as const).value,\n );\n\n return entries.some(isPromise)\n ? Promise.all(entries)\n : (entries as [Key, string | null][]);\n }).next((entries) => {\n return entries.filter((entry) => entry !== null) as [Key, string][];\n }).value;\n } else {\n return [...items.entries()];\n }\n }).next((entries) => {\n if (this.stopped) {\n return;\n }\n\n const toWrite = entries\n .filter(([key, value]) => {\n if (key.type !== 'data' || !value) {\n return;\n }\n\n if (\n !this.paths.find(\n (p) =>\n (p.path.length === 1 && p.path[0] === '*' && key.path.length === 0) ||\n (p.path.length === key.path.length && isAncestor(p.path, key.path)),\n )\n ) {\n return null;\n }\n\n const inSaveQueue = this.queue\n .getRefs()\n .find((ref) => isAncestor(ref, key.path) || isAncestor(key.path, ref));\n return !inSaveQueue;\n })\n .map(([key, value]) => {\n try {\n return {\n path: key.path,\n value: !value || value === 'undefined' ? undefined : fromExtendedJsonString(value),\n };\n } catch {\n return undefined;\n }\n })\n .filter(Boolean) as { path: KeyType[]; value: unknown }[];\n\n if (toWrite.length > 0) {\n for (const { path, value } of toWrite) {\n this.updateInProgress.set(JSON.stringify(path), value);\n }\n\n this.store.set((state) => {\n for (const { path, value } of toWrite) {\n if (value === undefined) {\n state = remove(state, path as any);\n } else {\n state = set(state, path as any, value);\n }\n }\n\n return state;\n });\n\n this.updateInProgress.clear();\n }\n\n const versionEntry = entries.find(\n ([key]) => key.type === 'internal' && key.path === 'version',\n );\n if (versionEntry) {\n this.store.version = versionEntry[1];\n }\n }).value;\n }\n\n private save(path: KeyType[]): void | Promise<unknown> {\n const key = this.buildKey({ type: 'data', path });\n const value = get(this.store.get() as any, path);\n\n return promiseChain(value)\n .next((value) => {\n if (value === undefined) {\n return this.storage.removeItem(key);\n } else {\n return this.storage.setItem(key, toExtendedJsonString(value));\n }\n })\n .next(() => {\n this.channel.postMessage(path);\n\n if (this.store.version) {\n return this.storage.setItem(\n this.buildKey({ type: 'internal', path: 'version' }),\n this.store.version,\n );\n } else {\n return this.storage.removeItem(this.buildKey({ type: 'internal', path: 'version' }));\n }\n }).value;\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n\n for (const handle of this.handles) {\n handle();\n }\n\n await this.queue.whenDone();\n this.channel.close();\n }\n}\n\nexport function persist<T>(store: Store<T>, options: PersistOptions<T>): Persist<T> {\n return new Persist<T>(store, options);\n}\n\nfunction isPlainPath<T>(p: PathOption<T>): p is WildcardPath<T> & (KeyType[] | string) {\n return typeof p === 'string' || Array.isArray(p);\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  const require_store = require('../store-CPqOf4y5.cjs');
2
2
  const require_propAccess = require('../propAccess-udIdjqwY.cjs');
3
- const require_extendedJson = require('../extendedJson-BwYSvpOA.cjs');
3
+ const require_extendedJson = require('../extendedJson-DzXMFE1P.cjs');
4
4
  const require_storeMethods = require('../storeMethods-BZb4k7Ma.cjs');
5
5
  let react = require("react");
6
6
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -213,6 +213,33 @@ function FormForEach({ name, renderElement, renderAdditionalElement, filter, chi
213
213
  })] });
214
214
  }
215
215
 
216
+ //#endregion
217
+ //#region src/react/form/formOnOriginalChange.tsx
218
+ function onOriginalChangeDefault(_oldOriginal, _newOriginal, draft, _form) {
219
+ return draft;
220
+ }
221
+ function onOriginalChangeMerge(oldOriginal, newOriginal, draft, _form) {
222
+ const [patches] = require_extendedJson.diff(oldOriginal, newOriginal, { diffArrays: true });
223
+ for (const p of patches) if (require_propAccess.deepEqual(require_propAccess.get(draft, p.path), require_propAccess.get(oldOriginal, p.path))) {
224
+ const newValue = p.op === "remove" ? void 0 : p.value;
225
+ draft = require_propAccess.set(draft, p.path, newValue);
226
+ }
227
+ return draft;
228
+ }
229
+ function onOriginalChangeOverwrite(_oldOriginal, newOriginal, _draft, _form) {
230
+ return newOriginal;
231
+ }
232
+ const builtinHandlers = {
233
+ default: onOriginalChangeDefault,
234
+ merge: onOriginalChangeMerge,
235
+ overwrite: onOriginalChangeOverwrite
236
+ };
237
+ function resolveOnOriginalChange(onOriginalChange) {
238
+ if (typeof onOriginalChange === "function") return onOriginalChange;
239
+ if (typeof onOriginalChange === "string" && onOriginalChange in builtinHandlers) return builtinHandlers[onOriginalChange];
240
+ return onOriginalChangeDefault;
241
+ }
242
+
216
243
  //#endregion
217
244
  //#region src/react/form/useFormAutosave.ts
218
245
  function useFormAutosave(form) {
@@ -433,7 +460,7 @@ var Form = class Form {
433
460
  ...options
434
461
  });
435
462
  }
436
- Form({ defaultValue, validations, initiallyTriggerValidations, localizeError, autoSave, transform, validatedClass, original, onSubmit, reportValidity, transformFieldProps, ...formProps }) {
463
+ Form({ defaultValue, validations, initiallyTriggerValidations, localizeError, autoSave, transform, validatedClass, original, onSubmit, reportValidity, transformFieldProps, onOriginalChange, ...formProps }) {
437
464
  const options = {
438
465
  defaultValue: {
439
466
  ...this.options.defaultValue,
@@ -453,7 +480,8 @@ var Form = class Form {
453
480
  original: original ?? this.options.original,
454
481
  onSubmit: onSubmit ?? this.options.onSubmit,
455
482
  reportValidity: reportValidity ?? this.options.reportValidity ?? "browser",
456
- transformFieldProps: transformFieldProps ?? this.options.transformFieldProps
483
+ transformFieldProps: transformFieldProps ?? this.options.transformFieldProps,
484
+ onOriginalChange: onOriginalChange ?? this.options.onOriginalChange ?? "default"
457
485
  };
458
486
  const formState = (0, react.useMemo)(() => {
459
487
  return require_store.createStore({
@@ -546,6 +574,15 @@ var Form = class Form {
546
574
  if (!require_propAccess.deepEqual(result, value)) context.formState.set("draft", result);
547
575
  });
548
576
  });
577
+ const lastOriginal = (0, react.useRef)(options.original);
578
+ (0, react.useEffect)(() => {
579
+ const draft = formState.get().draft;
580
+ if (draft !== void 0 && !require_propAccess.deepEqual(options.original, lastOriginal.current)) {
581
+ const result = resolveOnOriginalChange(options.onOriginalChange)(lastOriginal.current, options.original, draft, context);
582
+ if (result !== void 0 && !require_propAccess.deepEqual(result, draft)) formState.set("draft", result);
583
+ }
584
+ lastOriginal.current = options.original;
585
+ }, [options.original]);
549
586
  function updateValidity(errors, buttonElement) {
550
587
  const formElement = formRef.current;
551
588
  if (!formElement) return;
@@ -565,6 +602,7 @@ var Form = class Form {
565
602
  value: context,
566
603
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormContainer, {
567
604
  ...formProps,
605
+ ref: formRef,
568
606
  form: this,
569
607
  onSubmit: options.onSubmit
570
608
  })