@storesjs/stores 0.8.6 → 0.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 (40) hide show
  1. package/dist/config.d.ts +37 -7
  2. package/dist/createBaseStore.d.ts +2 -2
  3. package/dist/createQueryStore.d.ts +7 -23
  4. package/dist/createStoreWithEqualityFn.d.ts +5 -0
  5. package/dist/createVirtualStore.d.ts +4 -3
  6. package/dist/derivedStore/{globalDeriveScheduler.d.ts → cascadeScheduler.d.ts} +9 -1
  7. package/dist/derivedStore/deriveProxy.d.ts +6 -16
  8. package/dist/derivedStore/pathFinder.d.ts +27 -0
  9. package/dist/errors.d.ts +14 -0
  10. package/dist/hooks/useSyncExternalStoreWithSelector.d.ts +5 -0
  11. package/dist/index.d.ts +3 -1
  12. package/dist/logger.d.ts +0 -5
  13. package/dist/middleware/createHydrationGate.d.ts +1 -1
  14. package/dist/native/index.js +1 -1
  15. package/dist/native/index.mjs +1 -1
  16. package/dist/plugins/chrome/chromeExtensionSyncEngine.d.ts +3 -1
  17. package/dist/queryStore/queryStoreDefaults.d.ts +8 -0
  18. package/dist/queryStore/signalTypes.d.ts +13 -0
  19. package/dist/queryStore/types.d.ts +35 -30
  20. package/dist/signal.d.ts +2 -11
  21. package/dist/storage/storageCreators.d.ts +1 -1
  22. package/dist/sync/syncEnhancer.d.ts +4 -0
  23. package/dist/sync/types.d.ts +53 -128
  24. package/dist/types/functions.d.ts +19 -2
  25. package/dist/types/objects.d.ts +10 -3
  26. package/dist/types/utils.d.ts +1 -1
  27. package/dist/types.d.ts +35 -32
  28. package/dist/utils/core.d.ts +23 -4
  29. package/dist/utils/createStoreActions.d.ts +3 -3
  30. package/dist/utils/persistUtils.d.ts +2 -2
  31. package/dist/utils/storeUtils.d.ts +22 -15
  32. package/dist/utils/time.d.ts +0 -3
  33. package/dist/web/chrome.js +1 -1
  34. package/dist/web/chrome.mjs +1 -1
  35. package/dist/web/chunk-3U5A7HQV.mjs +1 -0
  36. package/dist/web/index.js +1 -1
  37. package/dist/web/index.mjs +1 -1
  38. package/package.json +17 -12
  39. package/dist/sync/transport.d.ts +0 -113
  40. package/dist/web/chunk-B3GRBY25.mjs +0 -1
@@ -1,4 +1,4 @@
1
- type UnknownFunction = (...args: unknown[]) => unknown;
1
+ import { UnknownFunction } from '../types/functions';
2
2
  /**
3
3
  * Metadata for a field's last write.
4
4
  */
@@ -9,147 +9,86 @@ export type SyncStateKey<T extends Record<string, unknown>> = Extract<{
9
9
  export type SyncValues<T extends Record<string, unknown>> = Partial<T> & {
10
10
  [K in SyncStateKey<T>]?: T[K];
11
11
  };
12
- export type RecordDeltaPayload<TValue = unknown> = {
13
- readonly clear?: true;
14
- readonly del?: readonly string[];
15
- readonly set?: Record<string, TValue>;
16
- readonly patch?: Record<string, RecordDeltaPayload>;
17
- };
18
- export type SyncDeltaPayload<TValue = unknown> = {
19
- readonly kind: 'record';
20
- } & RecordDeltaPayload<TValue>;
21
- export type SyncDeltaDescriptor = {
22
- /**
23
- * Minimum fraction of the full payload the delta must save (0–1).
24
- */
25
- readonly minSavingsRatio?: number;
26
- /**
27
- * Minimum number of bytes the delta must save compared to sending the full payload.
28
- */
29
- readonly minSavingsBytes?: number;
30
- };
31
- /**
32
- * Per-field delta configuration. Use `true` to enable with defaults, or provide thresholds.
33
- */
34
- export type SyncDeltaConfig<T extends Record<string, unknown>> = Partial<Record<SyncStateKey<T>, SyncDeltaDescriptor | true>>;
35
- export type SyncDeltaMap<T extends Record<string, unknown>> = Partial<Record<SyncStateKey<T>, SyncDeltaPayload<T[SyncStateKey<T>]>>>;
36
12
  export type SyncUpdate<T extends Record<string, unknown>> = {
37
- deltas?: SyncDeltaMap<T>;
38
13
  replace: boolean;
39
14
  sessionId: string;
40
15
  timestamp: number;
41
16
  values: SyncValues<T>;
42
17
  };
18
+ /**
19
+ * Passed to `SyncEngine.register()` to connect a store to the sync system.
20
+ */
43
21
  export type SyncRegistration<T extends Record<string, unknown>> = {
22
+ /** Callback invoked by the engine to apply incoming remote updates to the store. */
44
23
  apply: (update: SyncUpdate<T>) => void;
24
+ /** The state keys to sync. Non-function properties only. */
45
25
  fields: ReadonlyArray<SyncStateKey<T>>;
26
+ /** Returns the store's current state. Used by engines that need to read state (e.g., for diffing). */
46
27
  getState: () => T;
28
+ /** Unique identifier for this store. Must match across clients to sync the same data. */
47
29
  key: string;
48
- delta?: SyncDeltaConfig<T>;
49
30
  };
31
+ /**
32
+ * Returned by `SyncEngine.register()`. Controls the lifecycle of a synced store.
33
+ */
50
34
  export interface SyncHandle<T extends Record<string, unknown>> {
35
+ /**
36
+ * Permanently removes this store from the sync engine. After calling, the handle
37
+ * is invalid and the store will no longer send or receive updates. To temporarily
38
+ * pause sync, use `onFirstSubscribe`/`onLastUnsubscribe` lifecycle hooks instead.
39
+ */
51
40
  destroy: () => void;
41
+ /** Returns `true` once the store has received its initial state from the engine. */
52
42
  hydrated?: () => boolean;
43
+ /**
44
+ * Called when the store's subscriber count goes from 0 to 1. The registration
45
+ * remains active. Use for lazy resource acquisition (e.g., opening a WebSocket).
46
+ */
47
+ onFirstSubscribe?: () => void;
48
+ /** Registers a one-time callback to run when hydration completes. */
53
49
  onHydrated?: (callback: () => void) => void;
50
+ /**
51
+ * Called when the store's subscriber count drops to 0. The registration remains
52
+ * active and `onFirstSubscribe` will fire again on the next subscription.
53
+ * Use for resource cleanup (e.g., closing idle connections).
54
+ */
55
+ onLastUnsubscribe?: () => void;
56
+ /**
57
+ * Broadcasts a state update to other clients. Set to `null` for engines where
58
+ * publishing is implicit (e.g., `chrome.storage` where the write itself triggers sync).
59
+ */
54
60
  publish: ((update: SyncUpdate<T>) => void) | null;
55
61
  }
62
+ /**
63
+ * Interface for multi-client state synchronization. Stores register to send and receive updates.
64
+ */
56
65
  export interface SyncEngine {
57
- register<T extends Record<string, unknown>>(registration: SyncRegistration<T>): SyncHandle<T>;
58
- registerPresence?<Presence>(registration: SyncPresenceRegistration<Presence>): SyncPresenceChannel<Presence> | null;
59
66
  /**
60
- * When true, injects sync metadata (`{ origin, timestamp, fields }`) into the persisted
61
- * storage payload. Only takes effect when used with a persisted store.
62
- *
63
- * Useful for sync engines that use storage events as their transport (e.g., `chrome.storage`).
67
+ * When `true`, embeds sync metadata (`{ origin, timestamp, fields }`) into persisted
68
+ * storage values. Required for engines that use storage writes as their transport.
69
+ * Only effective when the store is also persisted.
64
70
  * @default false
65
71
  */
66
72
  readonly injectStorageMetadata?: boolean;
73
+ /** Registers a store for synchronization. Returns a handle to control the sync lifecycle. */
74
+ register: {
75
+ <T extends Record<string, unknown>>(registration: SyncRegistration<T>): SyncHandle<T>;
76
+ (registration: SyncRegistration<Record<string, unknown>>): SyncHandle<Record<string, unknown>>;
77
+ };
78
+ /** Unique identifier for this client session. Used for conflict resolution and filtering self-updates. */
67
79
  readonly sessionId: string;
68
80
  }
69
81
  export type SyncMergeFn<T, TState = unknown> = (incoming: T, current: T, currentState: TState, incomingValues: Partial<TState>) => T;
70
- export type SyncPresenceJoinHandler<Presence> = (userId: string, data: Presence) => void;
71
- export type SyncPresenceUpdateHandler<Presence> = (userId: string, data: Presence) => void;
72
- export type SyncPresenceLeaveHandler = (userId: string) => void;
73
- export type PresencePruneStrategy = 'updates' | 'activity';
74
- type PresenceActivityField<Presence> = Presence extends Record<string, unknown> ? Extract<keyof Presence, string> : string;
75
- export type SyncPresenceHeartbeatConfig<Presence> = {
76
- /** Interval in milliseconds between heartbeat broadcasts */
77
- interval: number;
78
- /** Reuse the last presence payload for each heartbeat (default). */
79
- behavior?: 'reuse' | undefined;
80
- } | {
81
- /** Interval in milliseconds between heartbeat broadcasts */
82
- interval: number;
83
- /** Clone the payload and refresh an activity field on every heartbeat. */
84
- behavior: 'refresh-activity';
85
- /**
86
- * Field from the presence payload to refresh. Defaults to the prune strategy's activity field or `timestamp`.
87
- */
88
- activityField?: PresenceActivityField<Presence>;
89
- } | {
90
- /** Interval in milliseconds between heartbeat broadcasts */
91
- interval: number;
92
- /** Derive a custom payload for each heartbeat. */
93
- behavior: 'transform';
94
- /**
95
- * Transform invoked before each heartbeat. Return a payload to broadcast, or void to reuse the current data.
96
- */
97
- onHeartbeat: (currentData: Presence) => Presence | void;
98
- };
99
- export type SyncPresenceRegistration<Presence> = {
100
- key: string;
101
- /**
102
- * Optional heartbeat configuration. When enabled, presence data is re-broadcast at the
103
- * specified interval. Use `'reuse'` (default) to emit the last payload unchanged, `'refresh-activity'`
104
- * to automatically update a timestamp-like field on object payloads, or `'transform'` to derive a custom payload.
105
- */
106
- heartbeat?: SyncPresenceHeartbeatConfig<Presence>;
107
- /**
108
- * Optional stale presence pruning. When enabled, remote presence entries that
109
- * haven't been updated within the specified threshold are automatically removed.
110
- */
111
- pruneStale?: {
112
- /**
113
- * Determines how staleness is evaluated.
114
- * - `updates` (default) considers the time since the last presence message arrived.
115
- * - `activity` considers a timestamp field within the presence payload (defaults to `timestamp`).
116
- */
117
- basedOn?: PresencePruneStrategy;
118
- /**
119
- * Field from the presence payload to inspect when `basedOn` is set to `activity`.
120
- * Defaults to `timestamp`.
121
- */
122
- activityField?: PresenceActivityField<Presence>;
123
- /** Time in milliseconds after which presence is considered stale */
124
- after: number;
125
- /** Optional callback invoked before removing stale presence */
126
- onPrune?: (userId: string, data: Presence) => void;
127
- };
128
- onJoin?: SyncPresenceJoinHandler<Presence>;
129
- onLeave?: SyncPresenceLeaveHandler;
130
- onUpdate?: SyncPresenceUpdateHandler<Presence>;
131
- };
132
- export interface SyncPresenceChannel<Presence> {
133
- join(userId: string, data: Presence): void;
134
- leave(): void;
135
- update(data: Presence): void;
136
- /**
137
- * Destroys the presence channel and cleans up all resources.
138
- * Automatically calls leave() and clears all timers.
139
- * Safe to call multiple times.
140
- */
141
- destroy(): void;
142
- }
143
82
  export type SyncConfig<T extends Record<string, unknown>> = {
144
- engine?: SyncEngine;
145
- fields?: ReadonlyArray<SyncStateKey<T>>;
146
83
  /**
147
- * The delta configuration for the sync engine.
84
+ * The sync engine implementation to use.
148
85
  *
149
- * Only takes effect when used with delta-enabled engines like `NetworkSyncEngine`.
150
- * @default undefined
86
+ * Defaults to cross-tab sync in browser environments. No-op in other environments unless a
87
+ * custom engine is provided.
151
88
  */
152
- delta?: SyncDeltaConfig<T>;
89
+ engine?: SyncEngine;
90
+ /** The state keys to sync. If unspecified, all non-function store properties are synced. */
91
+ fields?: ReadonlyArray<SyncStateKey<T>>;
153
92
  /**
154
93
  * When true, injects sync metadata (`{ origin, timestamp, fields }`) into the persisted
155
94
  * storage payload. Only takes effect when used with a persisted store.
@@ -160,7 +99,9 @@ export type SyncConfig<T extends Record<string, unknown>> = {
160
99
  * @default false
161
100
  */
162
101
  injectStorageMetadata?: boolean;
102
+ /** The key used to identify the store to the sync engine. Required if `storageKey` is absent. */
163
103
  key?: string;
104
+ /** Optional merge function to use for each synced state key. Use with caution. */
164
105
  merge?: {
165
106
  [K in SyncStateKey<T>]?: SyncMergeFn<T[K], T>;
166
107
  };
@@ -171,20 +112,4 @@ export type SyncConfig<T extends Record<string, unknown>> = {
171
112
  export type NormalizedSyncConfig<T extends Record<string, unknown>> = SyncConfig<T> & {
172
113
  key: string;
173
114
  };
174
- export type SyncAuthPhase = 'connect' | 'refresh' | 'challenge';
175
- export type SyncAuthPayload = {
176
- readonly headers?: Record<string, string>;
177
- readonly query?: Record<string, string>;
178
- readonly token?: string;
179
- };
180
- export type SyncAuthFailure = {
181
- readonly code: string;
182
- readonly message?: string;
183
- readonly retryable: boolean;
184
- };
185
- export type SyncAuthenticator = {
186
- readonly getPayload: (phase: SyncAuthPhase) => Promise<SyncAuthPayload | null> | SyncAuthPayload | null;
187
- readonly onFailure?: (failure: SyncAuthFailure) => void;
188
- };
189
- export {};
190
115
  //# sourceMappingURL=types.d.ts.map
@@ -1,7 +1,24 @@
1
- /** Extract the keys of T whose values are functions. */
1
+ /**
2
+ * Relaxes function parameter variance to allow subtype
3
+ * assignment otherwise blocked by strict contravariance.
4
+ */
5
+ export type BivariantMethod<T extends Record<string, UnknownFunction>> = T[keyof T];
6
+ /**
7
+ * Extract the keys of `T` whose values are functions.
8
+ */
2
9
  export type FunctionKeys<T> = {
3
10
  [K in keyof T]-?: T[K] extends UnknownFunction ? K : never;
4
11
  }[keyof T];
5
- export type OmitFunctionKeys<T> = Omit<T, FunctionKeys<T>>;
12
+ /**
13
+ * A record of string keys to unknown functions.
14
+ */
15
+ export type FunctionRecord = Record<string, UnknownFunction>;
16
+ /**
17
+ * Return `T` if it is **not** a function, otherwise `never`.
18
+ */
19
+ export type NonFunction<T> = T extends (...args: infer _) => unknown ? never : T;
20
+ /**
21
+ * Unknown generic function type.
22
+ */
6
23
  export type UnknownFunction = (...args: never[]) => unknown;
7
24
  //# sourceMappingURL=functions.d.ts.map
@@ -1,4 +1,11 @@
1
- import { FunctionKeys, UnknownFunction } from './functions';
2
- export type NoOverlap<State, Bundled extends ObjectMethods> = Extract<keyof Bundled, FunctionKeys<State>> extends never ? Bundled : never;
3
- export type ObjectMethods = Record<string, UnknownFunction>;
1
+ /**
2
+ * Forces TypeScript to expand a type for clearer IDE display.
3
+ */
4
+ export type Prettify<T> = T extends infer U ? {
5
+ [K in keyof U]: U[K];
6
+ } : never;
7
+ /**
8
+ * Enforce no overlapping keys between two objects.
9
+ */
10
+ export type NoOverlap<A, B> = B & Record<Extract<keyof A, keyof B>, never>;
4
11
  //# sourceMappingURL=objects.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Safe `hasOwnProperty` check. Use to guard `for..in` loops against inherited properties.
2
+ * Typed `hasOwnProperty` alias.
3
3
  */
4
4
  export declare function hasOwn<T extends Record<string, unknown>, K extends string>(value: T, key: K): value is T & Record<K, unknown>;
5
5
  /**
package/dist/types.d.ts CHANGED
@@ -1,16 +1,17 @@
1
- import { Mutate, StateCreator as ZustandStateCreator, StoreApi } from 'zustand';
2
- import { PersistOptions } from 'zustand/middleware';
3
- import { UseBoundStoreWithEqualityFn } from 'zustand/traditional';
4
- import { StorageValue } from './storage/storageTypes';
5
- import { SyncConfig } from './sync/types';
1
+ import type { Mutate, StateCreator as ZustandStateCreator, StoreApi, StoreMutatorIdentifier } from 'zustand';
2
+ import type { PersistOptions } from 'zustand/middleware';
3
+ import type { StorageValue } from './storage/storageTypes';
4
+ import type { SyncConfig } from './sync/types';
6
5
  type SubscribeWithSelector = ['zustand/subscribeWithSelector', never];
6
+ export type StoreMutators = [StoreMutatorIdentifier, unknown][];
7
+ export type StoreMutatorsWithSelector<Mutators extends StoreMutators = StoreMutators> = [SubscribeWithSelector, ...Mutators];
7
8
  type HydrationPromise<PersistReturn> = PersistReturn extends Promise<void> ? {
8
9
  /** Invoke to get a promise that resolves once hydration completes. */
9
10
  hydrationPromise: () => Promise<void>;
10
11
  } : {
11
12
  hydrationPromise?: undefined;
12
13
  };
13
- export type StorePersist<Store, PersistedState, PersistReturn> = Store extends {
14
+ type WithPersist<Store, PersistedState, PersistReturn> = Store extends {
14
15
  getState: () => infer S;
15
16
  setState: {
16
17
  (...args: infer SetPartialArgs): infer _;
@@ -30,18 +31,16 @@ export type StorePersist<Store, PersistedState, PersistReturn> = Store extends {
30
31
  } & HydrationPromise<PersistReturn>;
31
32
  } : never;
32
33
  export type StateCreator<S, U = S> = ZustandStateCreator<S, [SubscribeWithSelector], [SubscribeWithSelector], U>;
34
+ export type UseBoundStoreWithEqualityFn<Store extends StoreApi<unknown>, State = InferStoreState<Store>> = UseStoreCallSignatures<State> & Store;
33
35
  export type BaseStore<S, ExtraSubscribeOptions extends boolean = false> = UseBoundStoreWithEqualityFn<Mutate<StoreApi<S>, [SubscribeWithSelector]>> & {
34
36
  subscribe: SubscribeOverloads<S, ExtraSubscribeOptions>;
35
37
  };
36
- export type PersistedStore<S, PersistedState = Partial<S>, ExtraSubscribeOptions extends boolean = false, PersistReturn = unknown> = {
37
- (): S;
38
- <U>(selector: (state: S) => U, equalityFn?: (a: U, b: U) => boolean): U;
39
- } & Omit<BaseStore<S, ExtraSubscribeOptions>, 'setState' | 'persist'> & StorePersist<BaseStore<S, ExtraSubscribeOptions>, PersistedState, PersistReturn>;
40
- export type Store<S, PersistedState extends Partial<S> = never, ExtraSubscribeOptions extends boolean = false, PersistReturn = unknown> = [
38
+ export type PersistedStore<S, PersistedState = Partial<S>, PersistReturn = unknown, ExtraSubscribeOptions extends boolean = false> = UseStoreCallSignatures<S> & Omit<BaseStore<S, ExtraSubscribeOptions>, 'setState' | 'persist'> & WithPersist<BaseStore<S, ExtraSubscribeOptions>, PersistedState, PersistReturn>;
39
+ export type Store<S, PersistedState extends Partial<S> = never, PersistReturn = unknown, ExtraSubscribeOptions extends boolean = false> = [
41
40
  PersistedState
42
- ] extends [never] ? BaseStore<S, ExtraSubscribeOptions> : PersistedStore<S, PersistedState, ExtraSubscribeOptions, PersistReturn>;
41
+ ] extends [never] ? BaseStore<S, ExtraSubscribeOptions> : PersistedStore<S, PersistedState, PersistReturn, ExtraSubscribeOptions>;
43
42
  export type OptionallyPersistedStore<S, PersistedState, PersistReturn = void> = WithAsyncSet<Store<S>, S, PersistedState, PersistReturn> & UseStoreCallSignatures<S> & {
44
- persist?: PersistedStore<S, PersistedState, false, PersistReturn>['persist'];
43
+ persist?: PersistedStore<S, PersistedState, PersistReturn, false>['persist'];
45
44
  };
46
45
  export type NoInfer<T> = [T][T extends unknown ? 0 : never];
47
46
  export type Timeout = ReturnType<typeof setTimeout>;
@@ -56,24 +55,18 @@ export type InferStoreState<Store extends StoreApi<unknown>> = Store extends {
56
55
  getState: () => infer T;
57
56
  } ? T : never;
58
57
  /**
59
- * Extracts the return type of setState from a store.
60
- * Returns `void` for non-persisted or sync-persisted stores.
61
- * Returns `Promise<void>` for async-persisted stores.
58
+ * Extracts a store's `setState` return type.
59
+ * - `void` for non-persisted or synchronous persisted stores.
60
+ * - `Promise<void>` for async persisted stores.
62
61
  */
63
62
  export type InferSetStateReturn<Store> = Store extends {
64
63
  setState(...args: SetStateArgs<infer S>): infer R;
65
64
  } ? R : void;
66
65
  /**
67
- * Extracts the PersistedState type from a store's persist property.
68
- * Returns `Partial<State>` if the store doesn't have persistence.
66
+ * Extracts a store's `PersistedState` type.
67
+ * Returns `never` if the store doesn't use persistence.
69
68
  */
70
- export type InferPersistedState<Store, State> = Store extends {
71
- persist: {
72
- getOptions: () => infer Options;
73
- };
74
- } ? Options extends {
75
- name?: string;
76
- } ? Partial<State> : Partial<State> : Partial<State>;
69
+ export type InferPersistedState<PersistedStore> = PersistedStore extends Store<infer _, infer PersistedState> ? PersistedState : never;
77
70
  export type SetPartial<S> = Partial<S> | ((state: S) => Partial<S>);
78
71
  export type SetFull<S> = S | ((state: S) => S);
79
72
  export type SetStateReplaceArgs<S, ExtraArgs extends unknown[] = []> = [update: SetFull<S>, replace: true, ...extraArgs: ExtraArgs];
@@ -85,10 +78,16 @@ export type SetStateOverloads<S, PersistReturn extends Promise<void> | void = vo
85
78
  (update: SetFull<S>, replace: true): PersistReturn;
86
79
  };
87
80
  export type WithAsyncSet<Store extends StoreApi<unknown>, S, PersistedState, PersistReturn> = Omit<Store, 'persist' | 'setState'> & {
88
- persist?: PersistedStore<S, PersistedState, false, PersistReturn>['persist'];
81
+ persist?: PersistedStore<S, PersistedState, PersistReturn, false>['persist'];
89
82
  setState(update: SetPartial<InferStoreState<Store>>, replace?: false): PersistReturn;
90
83
  setState(update: SetFull<InferStoreState<Store>>, replace: true): PersistReturn;
91
84
  };
85
+ /**
86
+ * Minimum store API required for subscription.
87
+ */
88
+ export type SubscribableStore = {
89
+ subscribe(selector: Selector<unknown, unknown>, listener: () => void, options?: SubscribeOptions<unknown>): UnsubscribeFn;
90
+ };
92
91
  export type SubscribeOptions<Selected> = {
93
92
  equalityFn?: EqualityFn<Selected>;
94
93
  fireImmediately?: boolean;
@@ -111,6 +110,10 @@ export type DerivedStore<S> = WithFlushUpdates<ReadOnlyDerivedStore<BaseStore<S>
111
110
  export type WithFlushUpdates<Store extends StoreApi<unknown>> = Store & {
112
111
  /**
113
112
  * Destroy the derived store and its subscriptions.
113
+ *
114
+ * Derived stores automatically clean up internal resources and subscriptions
115
+ * when no subscribers exist. So calling `destroy()` is usually unnecessary,
116
+ * unless `keepAlive: true` is specified and explict teardown is desired.
114
117
  */
115
118
  destroy: () => void;
116
119
  /**
@@ -202,12 +205,12 @@ export interface SyncStorageInterface<SerializedState = unknown> {
202
205
  * Adapter-level deserializer used when a store does not supply its own.
203
206
  * Acts as the default before falling back to the framework implementation.
204
207
  */
205
- readonly deserializer?: <PersistedState>(serializedState: SerializedState) => StorageValue<PersistedState>;
208
+ deserializer?<PersistedState>(serializedState: SerializedState): StorageValue<PersistedState>;
206
209
  /**
207
210
  * Adapter-level serializer used when a store does not supply its own.
208
211
  * Acts as the default before falling back to the framework implementation.
209
212
  */
210
- readonly serializer?: <PersistedState>(storageValue: StorageValue<PersistedState>) => SerializedState;
213
+ serializer?<PersistedState>(storageValue: StorageValue<PersistedState>): SerializedState;
211
214
  clearAll(): void;
212
215
  contains(key: string): boolean;
213
216
  delete(key: string): void;
@@ -225,12 +228,12 @@ export type AsyncStorageInterface<SerializedState = unknown> = {
225
228
  * Adapter-level deserializer used when a store does not supply its own.
226
229
  * Acts as the default before falling back to the framework implementation.
227
230
  */
228
- readonly deserializer?: <PersistedState>(serializedState: SerializedState) => StorageValue<PersistedState>;
231
+ deserializer?<PersistedState>(serializedState: SerializedState): StorageValue<PersistedState>;
229
232
  /**
230
233
  * Adapter-level serializer used when a store does not supply its own.
231
234
  * Acts as the default before falling back to the framework implementation.
232
235
  */
233
- readonly serializer?: <PersistedState>(storageValue: StorageValue<PersistedState>) => SerializedState;
236
+ serializer?<PersistedState>(storageValue: StorageValue<PersistedState>): SerializedState;
234
237
  clearAll(): Promise<void>;
235
238
  contains(key: string): Promise<boolean>;
236
239
  delete(key: string): Promise<void>;
@@ -246,7 +249,7 @@ export type PersistConfig<S, PersistedState = Partial<S>, PersistReturn = void>
246
249
  * A function to convert the serialized value back into the state object.
247
250
  * If not provided, the storage adapter's `deserializer` is used before falling back to the default implementation.
248
251
  */
249
- deserializer?: <SerializedState>(serializedState: SerializedState) => StorageValue<PersistedState>;
252
+ deserializer?: (serializedState: unknown) => StorageValue<PersistedState>;
250
253
  /**
251
254
  * A function to merge persisted state with current state during hydration.
252
255
  * By default, zustand does a shallow merge, but this allows custom logic for deep merging nested objects.
@@ -277,7 +280,7 @@ export type PersistConfig<S, PersistedState = Partial<S>, PersistReturn = void>
277
280
  * A function to serialize the state and version for storage.
278
281
  * If not provided, the storage adapter's `serializer` is used before falling back to the default implementation.
279
282
  */
280
- serializer?: <SerializedState>(storageValue: StorageValue<PersistedState>) => SerializedState;
283
+ serializer?: (storageValue: StorageValue<PersistedState>) => string;
281
284
  /**
282
285
  * Custom storage implementation. If async, `setState` will return a Promise that resolves
283
286
  * when the state is persisted. If sync, `setState` will return void.
@@ -1,7 +1,26 @@
1
1
  /**
2
- * Returns the first argument provided to it.
3
- * @param value - Any value.
4
- * @returns `value`.
2
+ * Returns the argument provided.
5
3
  */
6
- export declare const identity: (value: any) => any;
4
+ export declare function identity<T>(value: T): T;
5
+ export declare function identity<T, _>(value: T): T;
6
+ /**
7
+ * Creates a null-prototype object using the runtime-optimal path:
8
+ * - React Native: direct literal `{ __proto__: null }`
9
+ * - Web/Node: `Object.create` with a shared, frozen null prototype
10
+ */
11
+ export declare function nullObject<T extends Record<string, unknown> | object = Record<string, unknown>>(): T;
12
+ /**
13
+ * Builds null-prototype objects. Provided arguments are
14
+ * shallow-merged into a newly created null-prototype object:
15
+ *
16
+ * ```ts
17
+ * Object.assign(nullObject(), a, b?)
18
+ * ```
19
+ */
20
+ export declare function buildNullObject<A extends Record<string, unknown>>(a: A): A;
21
+ export declare function buildNullObject<A extends object, B>(a: object, b?: object): [undefined] extends B ? A : A & B;
22
+ /**
23
+ * Does nothing.
24
+ */
25
+ export declare function noop(): void;
7
26
  //# sourceMappingURL=core.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { StoreApi } from 'zustand';
2
2
  import { InferStoreState } from '../types';
3
- import { NoOverlap, ObjectMethods } from '../types/objects';
4
- import { FunctionKeys } from '../types/functions';
3
+ import { NoOverlap } from '../types/objects';
4
+ import { FunctionKeys, FunctionRecord } from '../types/functions';
5
5
  export type StoreActions<Store extends StoreApi<unknown>> = Pick<InferStoreState<Store>, FunctionKeys<InferStoreState<Store>>>;
6
6
  /**
7
7
  * Given a store instance, produces a new object containing only its actions.
@@ -21,5 +21,5 @@ export type StoreActions<Store extends StoreApi<unknown>> = Pick<InferStoreState
21
21
  * exampleActions.increment();
22
22
  */
23
23
  export declare function createStoreActions<Store extends StoreApi<unknown>>(store: Store): StoreActions<Store>;
24
- export declare function createStoreActions<Store extends StoreApi<unknown>, Bundled extends ObjectMethods>(store: Store, bundledMethods: NoOverlap<InferStoreState<Store>, Bundled>): StoreActions<Store> & Bundled;
24
+ export declare function createStoreActions<Store extends StoreApi<unknown>, Bundled extends FunctionRecord>(store: Store, bundledMethods: NoOverlap<InferStoreState<Store>, Bundled>): StoreActions<Store> & Bundled;
25
25
  //# sourceMappingURL=createStoreActions.d.ts.map
@@ -1,9 +1,9 @@
1
- import { StorageValue } from '../storage/storageTypes';
1
+ import type { StorageValue } from '../storage/storageTypes';
2
2
  /**
3
3
  * Default partialize function if none is provided. It omits top-level store
4
4
  * methods and keeps all other state.
5
5
  */
6
- export declare function omitStoreMethods<S, PersistedState extends Partial<S>>(state: S): PersistedState;
6
+ export declare function omitStoreMethods<S, PersistedState extends Partial<S> = Partial<S>>(state: S): PersistedState;
7
7
  export declare function defaultSerializeState<PersistedState>(storageValue: StorageValue<PersistedState>, shouldUseReplacer: boolean): string;
8
8
  export declare function defaultDeserializeState<PersistedState>(serializedState: string, shouldUseReviver: boolean): StorageValue<PersistedState>;
9
9
  //# sourceMappingURL=persistUtils.d.ts.map
@@ -1,11 +1,12 @@
1
1
  import { StoreApi } from 'zustand';
2
- import { BaseStore, DerivedStore, PersistedStore, SetStateArgs, WithGetSnapshot } from '../types';
3
- import { QueryStore, QueryStoreState } from 'src/queryStore/types';
4
- export declare enum StoreTags {
5
- QueryStore = "_queryStore",
6
- VirtualStore = "_virtualStore"
7
- }
8
- export declare function assignStoreTag<S>(store: BaseStore<S>, tag: StoreTags): BaseStore<S>;
2
+ import { QueryStore, QueryStoreState } from '../queryStore/types';
3
+ import { BaseStore, InferStoreState, PersistedStore, SetStateArgs } from '../types';
4
+ export declare const StoreTags: Readonly<{
5
+ QueryStore: symbol;
6
+ VirtualStore: symbol;
7
+ }>;
8
+ type StoreTag = (typeof StoreTags)[keyof typeof StoreTags];
9
+ export declare function assignStoreTag<S>(store: BaseStore<S>, tag: StoreTag): BaseStore<S>;
9
10
  /**
10
11
  * Helper that applies a `setState` update to the provided state.
11
12
  * Handles the `setState` discriminated union types internally.
@@ -29,29 +30,35 @@ export declare function getStoreName(store: BaseStore<unknown>): string;
29
30
  /**
30
31
  * Checks if a store has a `destroy` method.
31
32
  */
32
- export declare function hasDestroy<S>(store: StoreApi<S>): store is StoreApi<S> & {
33
+ export declare function hasDestroy<T extends StoreApi<unknown>>(store: T): store is T & {
33
34
  destroy: () => void;
34
35
  };
35
36
  /**
36
37
  * Checks if a store is a `DerivedStore` and reveals its internal `getSnapshot` method.
37
38
  */
38
- export declare function hasGetSnapshot<S>(store: BaseStore<S> | StoreApi<S>): store is WithGetSnapshot<DerivedStore<S>>;
39
+ export declare function hasGetSnapshot<T extends BaseStore<unknown> | StoreApi<unknown>>(store: T): store is T & {
40
+ getSnapshot: () => InferStoreState<T>;
41
+ };
39
42
  /**
40
43
  * Checks if a store is a `QueryStore`.
41
44
  */
42
- export declare function isQueryStore<S>(store: StoreApi<S> | BaseStore<S> | QueryStore<S, Record<string, unknown>, S>): store is BaseStore<QueryStoreState<S, Record<string, unknown>, S>>;
45
+ export declare function isQueryStore<T extends object>(store: T): store is Extract<T, BaseStore<QueryStoreState<unknown, Record<string, unknown>, unknown>>>;
43
46
  /**
44
47
  * Checks if a store is a `DerivedStore`.
45
48
  */
46
- export declare function isDerivedStore<S>(store: BaseStore<S> | StoreApi<S>): store is DerivedStore<S>;
49
+ export declare function isDerivedStore<T extends BaseStore<unknown> | StoreApi<unknown>>(store: T): store is T & {
50
+ destroy: () => void;
51
+ flushUpdates: () => void;
52
+ };
47
53
  /**
48
54
  * Checks if a store is persisted.
49
55
  */
50
- export declare function isPersistedStore<S>(store: BaseStore<S>): store is PersistedStore<S>;
56
+ export declare function isPersistedStore<T extends BaseStore<unknown> | PersistedStore<unknown>>(store: T): store is T & {
57
+ persist: PersistedStore<InferStoreState<T>>['persist'];
58
+ };
51
59
  /**
52
60
  * Checks if a store is a virtual store.
53
61
  */
54
- export declare function isVirtualStore<S>(store: BaseStore<S> | StoreApi<S>): store is BaseStore<S> & {
55
- [StoreTags.VirtualStore]: true;
56
- };
62
+ export declare function isVirtualStore<T extends BaseStore<unknown> | StoreApi<unknown>>(store: T): store is T & BaseStore<InferStoreState<T>>;
63
+ export {};
57
64
  //# sourceMappingURL=storeUtils.d.ts.map
@@ -38,9 +38,6 @@ export declare const time: TimeUtils;
38
38
  * Uses setTimeout(0) to allow microtasks scheduled via queueMicrotask to execute.
39
39
  *
40
40
  * Useful in tests when waiting for async operations scheduled via microtasks.
41
- *
42
- * @example
43
- * await waitForMicrotask();
44
41
  */
45
42
  export declare function waitForMicrotask(): Promise<void>;
46
43
  export {};
@@ -1 +1 @@
1
- var e="stores:";function t(e){if("object"!=typeof e||null===e)return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function r(e,t){return t instanceof Map?{__type:"Map",entries:Array.from(t.entries())}:t instanceof Set?{__type:"Set",values:Array.from(t)}:t}function s(e,t){return function(e){return"object"==typeof e&&null!==e&&"__type"in e&&"Map"===e.__type}(t)?new Map(t.entries):function(e){return"object"==typeof e&&null!==e&&"__type"in e&&"Set"===e.__type}(t)?new Set(t.values):t}var n=class{constructor(t){this.async=!0,this.deserializer=i,this.serializer=o,this.area=t?.area??"local",this.storageKeyPrefix=t?.storageKeyPrefix??e}async clearAll(){const e=this.ensureStorage();if(!e)return;if(!this.storageKeyPrefix)throw new Error("Cannot clear all storage with empty storageKeyPrefix. This would delete all storage entries.");const t=await this.listPrefixedKeys(e,this.storageKeyPrefix);t.length&&await this.execute(e,r=>e.remove(t,r))}async contains(e){const t=this.ensureStorage();if(!t)return!1;const r=this.toStorageKey(e),s=await this.getFromStorage(t,r);return Object.prototype.hasOwnProperty.call(s,r)}async delete(e){const t=this.ensureStorage();if(!t)return;const r=this.toStorageKey(e);await this.execute(t,e=>t.remove(r,e))}async getAllKeys(){const e=this.ensureStorage();if(!e)return[];const t=await this.getFromStorage(e,null),r=this.storageKeyPrefix;return r?Object.keys(t).filter(e=>e.startsWith(r)).map(e=>e.slice(r.length)):Object.keys(t)}async get(e){const t=this.ensureStorage();if(!t)return;const r=this.toStorageKey(e);return a((await this.getFromStorage(t,r))[r])||void 0}async set(e,t){const r=this.ensureStorage();if(!r)return;const s=this.toStorageKey(e);await this.execute(r,e=>r.set({[s]:t},e))}ensureStorage(){return e=this.area,"undefined"!=typeof chrome&&chrome.storage?chrome.storage[e]??null:null;var e}toStorageKey(e){return this.storageKeyPrefix?`${this.storageKeyPrefix}${e}`:e}async listPrefixedKeys(e,t){const r=await this.getFromStorage(e,null);return Object.keys(r).filter(e=>e.startsWith(t))}async getFromStorage(e,t){return this.invokeWithCallbackSupport(r=>e.get(t,r))}async execute(e,t){await this.invokeWithCallbackSupport(t)}async invokeWithCallbackSupport(e){return new Promise((t,r)=>{let s=!1;const n=e=>{if(s)return;s=!0;const n="undefined"!=typeof chrome&&chrome.runtime&&chrome.runtime.lastError?new Error(chrome.runtime.lastError.message):null;n?r(n):t(e)};try{const t=e(n);(o=t)&&"object"==typeof o&&"then"in o&&"function"==typeof o.then&&t.then(n).catch(r)}catch(e){r(e)}var o})}};function o(e){return{state:h(e.state),syncMetadata:e.syncMetadata,version:e.version}}function i(e){const t=a(e);if(!t)throw new Error("[ChromeStorageAdapter] Invalid serialized state format");return{state:u(t.state),syncMetadata:t.syncMetadata,version:t.version}}function a(e){if(c(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);if(c(t))return t}catch{}return null}function c(e){return!(!e||"object"!=typeof e)&&Object.prototype.hasOwnProperty.call(e,"state")}function h(e,s=r){if(e instanceof Map||e instanceof Set)return s.call(void 0,"",e);if(!t(e))return e;const n={};for(const[t,r]of Object.entries(e))n[t]=s.call(e,t,r);return n}function u(e,r=s){const n=r.call(void 0,"",e);if(!t(n))return n;const o={};for(const e of Object.entries(n)){const t=e[0],s=e[1];o[t]=r.call(n,t,s)}return o}var l=class{constructor(t){this.injectStorageMetadata=!0,this.registrations=new Map,this.isListening=!1,this.onStorageChanged=async(e,t)=>{if(t===this.area)for(const t of this.registrations){const r=t[0],s=t[1];if(s.destroyed)continue;const n=e[this.toStorageKey(r)];if(n&&void 0!==n.newValue)try{const e=this.parsePersistValue(n.newValue);if(!e||e.syncMetadata?.origin===this.sessionId)continue;const t=e?.syncMetadata,r=this.extractChangedFields(s,e.state,t,n.oldValue);if(!Object.keys(r).length)continue;s.registration.apply({replace:!1,sessionId:t?.origin??"unknown",timestamp:t?.timestamp??Date.now(),values:r})}catch(e){continue}}},t&&"storage"in t?(this.area=t.storage.area,this.storageKeyPrefix=t.storage.storageKeyPrefix):(this.area=t?.area??"local",this.storageKeyPrefix=t?.storageKeyPrefix??e),this.sessionId=this.generateSessionId(),this.attachListener()}generateSessionId(){return"undefined"!=typeof crypto&&"randomUUID"in crypto?crypto.randomUUID():`${Math.random().toString(36).slice(2)}:${Date.now().toString(36)}`}register(e){this.attachListener();const t={destroyed:!1,hydrated:!0,listeners:new Set,registration:e};return this.registrations.set(e.key,t),{destroy:()=>{t.destroyed=!0,t.listeners.clear(),this.registrations.delete(e.key),this.registrations.size||this.detachListener()},publish:null}}attachListener(){"undefined"!=typeof chrome&&chrome.storage&&!this.isListening&&(this.isListening=!0,chrome.storage.onChanged.addListener(this.onStorageChanged))}detachListener(){"undefined"!=typeof chrome&&chrome.storage&&this.isListening&&(chrome.storage.onChanged.removeListener(this.onStorageChanged),this.isListening=!1)}extractChangedFields(e,t,r,s){const n=Object.create(null),o=r?.fields;if(o&&Object.keys(o).length>0){let r=!1;for(const s of e.registration.fields){const e=String(s);Object.prototype.hasOwnProperty.call(o,e)&&(n[s]=t[s],r=!0)}if(r)return n}const i=this.parsePersistValue(s);for(const r of e.registration.fields){const e=t[r],s=i?.state[r];Object.is(e,s)||(n[r]=e)}return n}toStorageKey(e){return this.storageKeyPrefix?`${this.storageKeyPrefix}${e}`:e}parsePersistValue(e){return i(e)}};exports.ChromeExtensionSyncEngine=l,exports.ChromeStorageAdapter=n,exports.createSyncedChromeStorage=function(e){const t=new n(e);return{storage:t,syncEngine:new l({storage:t})}};
1
+ process.env.NODE_ENV,process.env.NODE_ENV;var e=Object.prototype.hasOwnProperty;function t(t,r){return e.call(t,r)}function r(e){if("object"!=typeof e||null===e)return!1;const t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}var s=Object.freeze(Object.create(null)),n="stores:";function o(e,t){return t instanceof Map?{__type:"Map",entries:Array.from(t.entries())}:t instanceof Set?{__type:"Set",values:Array.from(t)}:t}function i(e,t){return function(e){return"object"==typeof e&&null!==e&&"__type"in e&&"Map"===e.__type}(t)?new Map(t.entries):function(e){return"object"==typeof e&&null!==e&&"__type"in e&&"Set"===e.__type}(t)?new Set(t.values):t}var a=class{constructor(e){this.async=!0,this.deserializer=h,this.serializer=c,this.area=e?.area??"local",this.storageKeyPrefix=e?.storageKeyPrefix??n}async clearAll(){const e=this.ensureStorage();if(!e)return;if(!this.storageKeyPrefix)throw new Error("Cannot clear all storage with empty storageKeyPrefix. This would delete all storage entries.");const t=await this.listPrefixedKeys(e,this.storageKeyPrefix);t.length&&await this.execute(e,r=>e.remove(t,r))}async contains(e){const t=this.ensureStorage();if(!t)return!1;const r=this.toStorageKey(e),s=await this.getFromStorage(t,r);return Object.prototype.hasOwnProperty.call(s,r)}async delete(e){const t=this.ensureStorage();if(!t)return;const r=this.toStorageKey(e);await this.execute(t,e=>t.remove(r,e))}async getAllKeys(){const e=this.ensureStorage();if(!e)return[];const t=await this.getFromStorage(e,null),r=this.storageKeyPrefix;return r?Object.keys(t).filter(e=>e.startsWith(r)).map(e=>e.slice(r.length)):Object.keys(t)}async get(e){const t=this.ensureStorage();if(!t)return;const r=this.toStorageKey(e);return u((await this.getFromStorage(t,r))[r])||void 0}async set(e,t){const r=this.ensureStorage();if(!r)return;const s=this.toStorageKey(e);await this.execute(r,e=>r.set({[s]:t},e))}ensureStorage(){return e=this.area,"undefined"!=typeof chrome&&chrome.storage?chrome.storage[e]??null:null;var e}toStorageKey(e){return this.storageKeyPrefix?`${this.storageKeyPrefix}${e}`:e}async listPrefixedKeys(e,t){const r=await this.getFromStorage(e,null);return Object.keys(r).filter(e=>e.startsWith(t))}async getFromStorage(e,t){return this.invokeWithCallbackSupport(r=>e.get(t,r))}async execute(e,t){await this.invokeWithCallbackSupport(t)}async invokeWithCallbackSupport(e){return new Promise((t,r)=>{let s=!1;function n(e){if(s)return;s=!0;const n="undefined"!=typeof chrome&&chrome.runtime&&chrome.runtime.lastError?new Error(chrome.runtime.lastError.message):null;n?r(n):t(e)}try{const t=e(n);(o=t)&&"object"==typeof o&&"then"in o&&"function"==typeof o.then&&t.then(n).catch(r)}catch(e){r(e)}var o})}};function c(e){return{state:g(e.state),syncMetadata:e.syncMetadata,version:e.version}}function h(e){const t=u(e);if(!t)throw new Error("[ChromeStorageAdapter] Invalid serialized state format");return{state:f(t.state),syncMetadata:t.syncMetadata,version:t.version}}function u(e){if(l(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);if(l(t))return t}catch{}return null}function l(e){return!(!e||"object"!=typeof e)&&Object.prototype.hasOwnProperty.call(e,"state")}function g(e,t=o){if(e instanceof Map||e instanceof Set)return t.call(void 0,"",e);if(!r(e))return e;const s={};for(const[r,n]of Object.entries(e))s[r]=t.call(e,r,n);return s}function f(e,t=i){const s=t.call(void 0,"",e);if(!r(s))return s;const n={};for(const e of Object.entries(s)){const r=e[0],o=e[1];n[r]=t.call(s,r,o)}return n}var y=class{constructor(e){this.injectStorageMetadata=!0,this.registrations=new Map,this.isListening=!1,this.onStorageChanged=async(e,t)=>{if(t===this.area)for(const t of this.registrations){const r=t[0],s=t[1];if(s.destroyed)continue;const n=e[this.toStorageKey(r)];if(n&&void 0!==n.newValue)try{const e=this.parsePersistValue(n.newValue);if(!e||e.syncMetadata?.origin===this.sessionId)continue;const t=e?.syncMetadata,r=this.extractChangedFields(s,e.state,t,n.oldValue);if(!Object.keys(r).length)continue;s.registration.apply({replace:!1,sessionId:t?.origin??"unknown",timestamp:t?.timestamp??Date.now(),values:r})}catch(e){continue}}},e&&"storage"in e?(this.area=e.storage.area,this.storageKeyPrefix=e.storage.storageKeyPrefix):(this.area=e?.area??"local",this.storageKeyPrefix=e?.storageKeyPrefix??n),this.sessionId=this.generateSessionId(),this.attachListener()}destroy(){for(const e of this.registrations.values())e.destroyed=!0,e.listeners.clear();this.detachListener()}register(e){this.attachListener();const t={destroyed:!1,hydrated:!0,listeners:new Set,registration:e};return this.setRegistration(e.key,t),{destroy:()=>{t.destroyed=!0,t.listeners.clear(),this.registrations.delete(e.key),this.registrations.size||this.detachListener()},publish:null}}generateSessionId(){return"undefined"!=typeof crypto&&"randomUUID"in crypto?crypto.randomUUID():`${Math.random().toString(36).slice(2)}:${Date.now().toString(36)}`}attachListener(){"undefined"!=typeof chrome&&chrome.storage&&!this.isListening&&(this.isListening=!0,chrome.storage.onChanged.addListener(this.onStorageChanged))}detachListener(){"undefined"!=typeof chrome&&chrome.storage&&this.isListening&&(chrome.storage.onChanged.removeListener(this.onStorageChanged),this.isListening=!1)}extractChangedFields(e,r,n,o){const i=Object.create(s),a=n?.fields;if(a&&Object.keys(a).length>0){let s=!1;for(const n of e.registration.fields)t(a,String(n))&&(i[n]=r[n],s=!0);if(s)return i}const c=this.parsePersistValue(o);for(const t of e.registration.fields){const e=r[t],s=c?.state[t];Object.is(e,s)||(i[t]=e)}return i}setRegistration(e,t){this.registrations.set(e,t)}toStorageKey(e){return this.storageKeyPrefix?`${this.storageKeyPrefix}${e}`:e}parsePersistValue(e){return h(e)}};exports.ChromeExtensionSyncEngine=y,exports.ChromeStorageAdapter=a,exports.createSyncedChromeStorage=function(e){const t=new a(e);return{storage:t,syncEngine:new y({storage:t})}};