{"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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"}