dharma-core 0.6.0 → 0.6.1

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.
@@ -12,7 +12,7 @@ export type Store<TState extends object, TActions extends object> = {
12
12
  /** Subscribes to changes in the state of the store. Returns an unsubscribe function. */
13
13
  subscribe: (listener: Listener<TState>) => () => void;
14
14
  };
15
- export type EventHandlerContext<TState extends object> = {
15
+ export type StoreEventContext<TState extends object> = {
16
16
  /** The current state of the store. */
17
17
  state: TState;
18
18
  /** Sets the state of the store. */
@@ -20,9 +20,9 @@ export type EventHandlerContext<TState extends object> = {
20
20
  /** Resets the state of the store to its initial value. */
21
21
  reset: () => TState;
22
22
  };
23
- export type StoreEventHandler<TState extends object> = (context: EventHandlerContext<TState>) => void;
23
+ export type StoreEventHandler<TState extends object> = (context: StoreEventContext<TState>) => void;
24
24
  export type StateModifier<TState extends object> = Partial<TState> | ((state: TState) => Partial<TState>);
25
- export type StateFunctions<TState extends object> = {
25
+ export type StateHandler<TState extends object> = {
26
26
  /** Returns the current state of the store. */
27
27
  get: () => TState;
28
28
  /** Sets the state of the store. */
@@ -30,7 +30,7 @@ export type StateFunctions<TState extends object> = {
30
30
  /** Resets the state of the store to its initial value. */
31
31
  reset: () => TState;
32
32
  };
33
- export type DefineActions<TState extends object, TActions> = (stateFunctions: StateFunctions<TState>) => TActions;
33
+ export type DefineActions<TState extends object, TActions> = (stateHandler: StateHandler<TState>) => TActions;
34
34
  type BaseConfig<TState extends object, TActions extends object> = {
35
35
  /** The initial state of the store. */
36
36
  initialState: TState;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var getPersistenceHandlers = require('./getPersistenceHandlers.js');
3
+ var getPersistHandler = require('./getPersistHandler.js');
4
4
  var merge = require('./merge.js');
5
5
 
6
6
  /**
@@ -88,34 +88,34 @@ var merge = require('./merge.js');
88
88
  const createStore = (config) => {
89
89
  const { initialState, defineActions, onLoad, onAttach, onDetach, onChange } = config;
90
90
  let state = initialState;
91
- const listeners = new Set();
92
91
  const get = () => state;
93
92
  const setSilently = (stateModifier) => {
94
93
  state = merge.merge(state, stateModifier);
95
94
  return state;
96
95
  };
97
- const resetSilently = () => setSilently(initialState);
98
- const dispatch = () => {
99
- onChange?.({ state, set: setSilently, reset: resetSilently });
100
- persistenceHandlers?.updateSnapshot(state);
101
- listeners.forEach((listener) => listener(state));
102
- };
103
96
  const set = (stateModifier) => {
104
97
  setSilently(stateModifier);
105
98
  dispatch();
106
99
  return state;
107
100
  };
101
+ const resetSilently = () => setSilently(initialState);
108
102
  const reset = () => {
109
103
  resetSilently();
110
104
  dispatch();
111
105
  return state;
112
106
  };
107
+ const listeners = new Set();
108
+ const actions = defineActions
109
+ ? defineActions({ set, get, reset })
110
+ : {};
111
+ const IS_BROWSER = typeof window !== "undefined";
112
+ const persistHandler = getPersistHandler.getPersistHandler(config, IS_BROWSER, get, set);
113
113
  const subscribe = (listener) => {
114
114
  if (listeners.size === 0) {
115
115
  onAttach?.({ state, set, reset });
116
- persistenceHandlers?.updateState();
117
- if (IS_BROWSER && persistenceHandlers) {
118
- window.addEventListener("focus", persistenceHandlers.updateState);
116
+ persistHandler?.updateState();
117
+ if (IS_BROWSER && persistHandler) {
118
+ window.addEventListener("focus", persistHandler.updateState);
119
119
  }
120
120
  }
121
121
  listener(state);
@@ -124,19 +124,23 @@ const createStore = (config) => {
124
124
  listeners.delete(listener);
125
125
  if (listeners.size === 0) {
126
126
  onDetach?.({ state, set, reset });
127
- if (IS_BROWSER && persistenceHandlers) {
128
- window.removeEventListener("focus", persistenceHandlers.updateState);
127
+ if (IS_BROWSER && persistHandler) {
128
+ window.removeEventListener("focus", persistHandler.updateState);
129
129
  }
130
130
  }
131
131
  };
132
132
  };
133
- const actions = defineActions
134
- ? defineActions({ set, get, reset })
135
- : {};
136
- const IS_BROWSER = typeof window !== "undefined";
137
- const persistenceHandlers = getPersistenceHandlers.getPersistenceHandlers(config, IS_BROWSER, get, set);
133
+ const dispatch = () => {
134
+ onChange?.({
135
+ state,
136
+ set: setSilently,
137
+ reset: resetSilently,
138
+ });
139
+ persistHandler?.updateSnapshot(state);
140
+ listeners.forEach((listener) => listener(state));
141
+ };
138
142
  onLoad?.({ state, set, reset });
139
- persistenceHandlers?.initializeSnapshots();
143
+ persistHandler?.initializeSnapshots();
140
144
  return {
141
145
  get,
142
146
  set,
@@ -1 +1 @@
1
- {"version":3,"file":"createStore.js","sources":["../../../src/lib/createStore.ts"],"sourcesContent":["import { getPersistenceHandlers } from \"./getPersistenceHandlers\";\nimport { merge } from \"./merge\";\n\ntype Listener<TState extends object> = (state: TState) => void;\n\nexport type SetState<TState extends object> = (\n stateModifier: StateModifier<TState>,\n) => TState;\n\nexport type Store<TState extends object, TActions extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n /** Actions that can modify the state of the store. */\n actions: TActions;\n /** Subscribes to changes in the state of the store. Returns an unsubscribe function. */\n subscribe: (listener: Listener<TState>) => () => void;\n};\n\nexport type EventHandlerContext<TState extends object> = {\n /** The current state of the store. */\n state: TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type StoreEventHandler<TState extends object> = (\n context: EventHandlerContext<TState>,\n) => void;\n\nexport type StateModifier<TState extends object> =\n | Partial<TState>\n | ((state: TState) => Partial<TState>);\n\nexport type StateFunctions<TState extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type DefineActions<TState extends object, TActions> = (\n stateFunctions: StateFunctions<TState>,\n) => TActions;\n\ntype BaseConfig<TState extends object, TActions extends object> = {\n /** The initial state of the store. */\n initialState: TState;\n /** A function that defines actions that can modify the state. */\n defineActions?: DefineActions<TState, TActions>;\n /** Invoked when the store is created. */\n onLoad?: StoreEventHandler<TState>;\n /** Invoked when the store is subscribed to. */\n onAttach?: StoreEventHandler<TState>;\n /** Invoked when the store is unsubscribed from. */\n onDetach?: StoreEventHandler<TState>;\n /** Invoked whenever the state changes. */\n onChange?: StoreEventHandler<TState>;\n};\n\nexport type StorageAPI = {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Serializer<T = any> = {\n stringify: (value: T) => string;\n parse: (value: string) => T;\n};\n\ntype NonPersistentConfig = {\n /** Whether to persist the state of the store. */\n persist?: false;\n};\n\ntype PersistentConfig<TState extends object> = {\n /** Whether to persist the state of the store. */\n persist: true;\n /** The unique key used to identify this store in storage. */\n key: string;\n /** The storage to use for persisting the state. Defaults to local storage if available. */\n storage?: StorageAPI;\n /** The serializer to use for storing the state. Defaults to JSON. */\n serializer?: Serializer<TState>;\n};\n\nexport type StoreConfig<\n TState extends object,\n TActions extends object,\n> = BaseConfig<TState, TActions> &\n (NonPersistentConfig | PersistentConfig<TState>);\n\n/**\n * Creates a store with an initial state and actions that can modify the state.\n *\n * @param {StoreConfig<TState, TActions>} [config] - The configuration for the store.\n *\n * @returns {Store<TState, TActions>} The created store with state management methods.\n *\n * @example\n * Basic usage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * @example\n * With event handlers:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import { State } from \"./types\";\n *\n * const initialState: State = { data: null, loading: true, error: null };\n *\n * const store = createStore({\n * initialState,\n * onAttach: async ({ set }) => {\n * try {\n * const response = await fetch(\"https://api.example.com/data\");\n * const data = await response.json();\n * set({ data, loading: false });\n * } catch (error) {\n * set({ error, loading: false });\n * }\n * },\n * onDetach: ({ reset }) => reset(),\n * });\n * ```\n *\n * @example\n * Persistent store (uses local storage by default):\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * **Note:** The state needs to be serializable by whatever serializer you choose (JSON by default).\n * If you need something more versatile I would recommend using a library like [superjson](https://github.com/flightcontrolhq/superjson).\n *\n * @example\n * With superjson serialization and session storage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import superjson from \"superjson\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * serializer: superjson,\n * storage: sessionStorage,\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n */\nexport const createStore = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n): Store<TState, TActions> => {\n const { initialState, defineActions, onLoad, onAttach, onDetach, onChange } =\n config;\n\n let state = initialState;\n const listeners = new Set<Listener<TState>>();\n\n const get = () => state;\n\n const setSilently = (stateModifier: StateModifier<TState>) => {\n state = merge(state, stateModifier);\n return state;\n };\n\n const resetSilently = () => setSilently(initialState);\n\n const dispatch = () => {\n onChange?.({ state, set: setSilently, reset: resetSilently });\n persistenceHandlers?.updateSnapshot(state);\n listeners.forEach((listener) => listener(state));\n };\n\n const set = (stateModifier: StateModifier<TState>) => {\n setSilently(stateModifier);\n dispatch();\n return state;\n };\n\n const reset = () => {\n resetSilently();\n dispatch();\n return state;\n };\n\n const subscribe = (listener: Listener<TState>) => {\n if (listeners.size === 0) {\n onAttach?.({ state, set, reset });\n persistenceHandlers?.updateState();\n\n if (IS_BROWSER && persistenceHandlers) {\n window.addEventListener(\"focus\", persistenceHandlers.updateState);\n }\n }\n\n listener(state);\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n\n if (listeners.size === 0) {\n onDetach?.({ state, set, reset });\n\n if (IS_BROWSER && persistenceHandlers) {\n window.removeEventListener(\"focus\", persistenceHandlers.updateState);\n }\n }\n };\n };\n\n const actions = defineActions\n ? defineActions({ set, get, reset })\n : ({} as TActions);\n\n const IS_BROWSER = typeof window !== \"undefined\";\n const persistenceHandlers = getPersistenceHandlers<TState, TActions>(\n config,\n IS_BROWSER,\n get,\n set,\n );\n\n onLoad?.({ state, set, reset });\n persistenceHandlers?.initializeSnapshots();\n\n return {\n get,\n set,\n reset,\n subscribe,\n actions,\n };\n};\n"],"names":["merge","getPersistenceHandlers"],"mappings":";;;;;AAqGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFG;AACI,MAAM,WAAW,GAAG,CAIzB,MAAqC,KACV;AAC3B,IAAA,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GACzE,MAAM;IAER,IAAI,KAAK,GAAG,YAAY;AACxB,IAAA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB;AAE7C,IAAA,MAAM,GAAG,GAAG,MAAM,KAAK;AAEvB,IAAA,MAAM,WAAW,GAAG,CAAC,aAAoC,KAAI;AAC3D,QAAA,KAAK,GAAGA,WAAK,CAAC,KAAK,EAAE,aAAa,CAAC;AACnC,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAK;AACpB,QAAA,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAC7D,QAAA,mBAAmB,EAAE,cAAc,CAAC,KAAK,CAAC;AAC1C,QAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,IAAA,CAAC;AAED,IAAA,MAAM,GAAG,GAAG,CAAC,aAAoC,KAAI;QACnD,WAAW,CAAC,aAAa,CAAC;AAC1B,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;IAED,MAAM,KAAK,GAAG,MAAK;AACjB,QAAA,aAAa,EAAE;AACf,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,SAAS,GAAG,CAAC,QAA0B,KAAI;AAC/C,QAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;YACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;YACjC,mBAAmB,EAAE,WAAW,EAAE;AAElC,YAAA,IAAI,UAAU,IAAI,mBAAmB,EAAE;gBACrC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC;YACnE;QACF;QAEA,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEvB,QAAA,OAAO,MAAK;AACV,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAE1B,YAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;gBACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAEjC,gBAAA,IAAI,UAAU,IAAI,mBAAmB,EAAE;oBACrC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC;gBACtE;YACF;AACF,QAAA,CAAC;AACH,IAAA,CAAC;IAED,MAAM,OAAO,GAAG;UACZ,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;UAChC,EAAe;AAEpB,IAAA,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW;AAChD,IAAA,MAAM,mBAAmB,GAAGC,6CAAsB,CAChD,MAAM,EACN,UAAU,EACV,GAAG,EACH,GAAG,CACJ;IAED,MAAM,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC/B,mBAAmB,EAAE,mBAAmB,EAAE;IAE1C,OAAO;QACL,GAAG;QACH,GAAG;QACH,KAAK;QACL,SAAS;QACT,OAAO;KACR;AACH;;;;"}
1
+ {"version":3,"file":"createStore.js","sources":["../../../src/lib/createStore.ts"],"sourcesContent":["import { getPersistHandler } from \"./getPersistHandler\";\nimport { merge } from \"./merge\";\n\ntype Listener<TState extends object> = (state: TState) => void;\n\nexport type SetState<TState extends object> = (\n stateModifier: StateModifier<TState>,\n) => TState;\n\nexport type Store<TState extends object, TActions extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n /** Actions that can modify the state of the store. */\n actions: TActions;\n /** Subscribes to changes in the state of the store. Returns an unsubscribe function. */\n subscribe: (listener: Listener<TState>) => () => void;\n};\n\nexport type StoreEventContext<TState extends object> = {\n /** The current state of the store. */\n state: TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type StoreEventHandler<TState extends object> = (\n context: StoreEventContext<TState>,\n) => void;\n\nexport type StateModifier<TState extends object> =\n | Partial<TState>\n | ((state: TState) => Partial<TState>);\n\nexport type StateHandler<TState extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type DefineActions<TState extends object, TActions> = (\n stateHandler: StateHandler<TState>,\n) => TActions;\n\ntype BaseConfig<TState extends object, TActions extends object> = {\n /** The initial state of the store. */\n initialState: TState;\n /** A function that defines actions that can modify the state. */\n defineActions?: DefineActions<TState, TActions>;\n /** Invoked when the store is created. */\n onLoad?: StoreEventHandler<TState>;\n /** Invoked when the store is subscribed to. */\n onAttach?: StoreEventHandler<TState>;\n /** Invoked when the store is unsubscribed from. */\n onDetach?: StoreEventHandler<TState>;\n /** Invoked whenever the state changes. */\n onChange?: StoreEventHandler<TState>;\n};\n\nexport type StorageAPI = {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Serializer<T = any> = {\n stringify: (value: T) => string;\n parse: (value: string) => T;\n};\n\ntype NonPersistentConfig = {\n /** Whether to persist the state of the store. */\n persist?: false;\n};\n\ntype PersistentConfig<TState extends object> = {\n /** Whether to persist the state of the store. */\n persist: true;\n /** The unique key used to identify this store in storage. */\n key: string;\n /** The storage to use for persisting the state. Defaults to local storage if available. */\n storage?: StorageAPI;\n /** The serializer to use for storing the state. Defaults to JSON. */\n serializer?: Serializer<TState>;\n};\n\nexport type StoreConfig<\n TState extends object,\n TActions extends object,\n> = BaseConfig<TState, TActions> &\n (NonPersistentConfig | PersistentConfig<TState>);\n\n/**\n * Creates a store with an initial state and actions that can modify the state.\n *\n * @param {StoreConfig<TState, TActions>} [config] - The configuration for the store.\n *\n * @returns {Store<TState, TActions>} The created store with state management methods.\n *\n * @example\n * Basic usage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * @example\n * With event handlers:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import { State } from \"./types\";\n *\n * const initialState: State = { data: null, loading: true, error: null };\n *\n * const store = createStore({\n * initialState,\n * onAttach: async ({ set }) => {\n * try {\n * const response = await fetch(\"https://api.example.com/data\");\n * const data = await response.json();\n * set({ data, loading: false });\n * } catch (error) {\n * set({ error, loading: false });\n * }\n * },\n * onDetach: ({ reset }) => reset(),\n * });\n * ```\n *\n * @example\n * Persistent store (uses local storage by default):\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * **Note:** The state needs to be serializable by whatever serializer you choose (JSON by default).\n * If you need something more versatile I would recommend using a library like [superjson](https://github.com/flightcontrolhq/superjson).\n *\n * @example\n * With superjson serialization and session storage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import superjson from \"superjson\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * serializer: superjson,\n * storage: sessionStorage,\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n */\nexport const createStore = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n): Store<TState, TActions> => {\n const { initialState, defineActions, onLoad, onAttach, onDetach, onChange } =\n config;\n\n let state = initialState;\n\n const get = () => state;\n\n const setSilently = (stateModifier: StateModifier<TState>) => {\n state = merge(state, stateModifier);\n return state;\n };\n\n const set = (stateModifier: StateModifier<TState>) => {\n setSilently(stateModifier);\n dispatch();\n return state;\n };\n\n const resetSilently = () => setSilently(initialState);\n\n const reset = () => {\n resetSilently();\n dispatch();\n return state;\n };\n\n const listeners = new Set<Listener<TState>>();\n const actions = defineActions\n ? defineActions({ set, get, reset })\n : ({} as TActions);\n const IS_BROWSER = typeof window !== \"undefined\";\n const persistHandler = getPersistHandler(config, IS_BROWSER, get, set);\n\n const subscribe = (listener: Listener<TState>) => {\n if (listeners.size === 0) {\n onAttach?.({ state, set, reset });\n persistHandler?.updateState();\n\n if (IS_BROWSER && persistHandler) {\n window.addEventListener(\"focus\", persistHandler.updateState);\n }\n }\n\n listener(state);\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n\n if (listeners.size === 0) {\n onDetach?.({ state, set, reset });\n\n if (IS_BROWSER && persistHandler) {\n window.removeEventListener(\"focus\", persistHandler.updateState);\n }\n }\n };\n };\n\n const dispatch = () => {\n onChange?.({\n state,\n set: setSilently,\n reset: resetSilently,\n });\n persistHandler?.updateSnapshot(state);\n listeners.forEach((listener) => listener(state));\n };\n\n onLoad?.({ state, set, reset });\n persistHandler?.initializeSnapshots();\n\n return {\n get,\n set,\n reset,\n subscribe,\n actions,\n };\n};\n"],"names":["merge","getPersistHandler"],"mappings":";;;;;AAqGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFG;AACI,MAAM,WAAW,GAAG,CAIzB,MAAqC,KACV;AAC3B,IAAA,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GACzE,MAAM;IAER,IAAI,KAAK,GAAG,YAAY;AAExB,IAAA,MAAM,GAAG,GAAG,MAAM,KAAK;AAEvB,IAAA,MAAM,WAAW,GAAG,CAAC,aAAoC,KAAI;AAC3D,QAAA,KAAK,GAAGA,WAAK,CAAC,KAAK,EAAE,aAAa,CAAC;AACnC,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,GAAG,GAAG,CAAC,aAAoC,KAAI;QACnD,WAAW,CAAC,aAAa,CAAC;AAC1B,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC;IAErD,MAAM,KAAK,GAAG,MAAK;AACjB,QAAA,aAAa,EAAE;AACf,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB;IAC7C,MAAM,OAAO,GAAG;UACZ,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;UAChC,EAAe;AACpB,IAAA,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW;AAChD,IAAA,MAAM,cAAc,GAAGC,mCAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC;AAEtE,IAAA,MAAM,SAAS,GAAG,CAAC,QAA0B,KAAI;AAC/C,QAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;YACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;YACjC,cAAc,EAAE,WAAW,EAAE;AAE7B,YAAA,IAAI,UAAU,IAAI,cAAc,EAAE;gBAChC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,CAAC,WAAW,CAAC;YAC9D;QACF;QAEA,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEvB,QAAA,OAAO,MAAK;AACV,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAE1B,YAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;gBACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAEjC,gBAAA,IAAI,UAAU,IAAI,cAAc,EAAE;oBAChC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,cAAc,CAAC,WAAW,CAAC;gBACjE;YACF;AACF,QAAA,CAAC;AACH,IAAA,CAAC;IAED,MAAM,QAAQ,GAAG,MAAK;AACpB,QAAA,QAAQ,GAAG;YACT,KAAK;AACL,YAAA,GAAG,EAAE,WAAW;AAChB,YAAA,KAAK,EAAE,aAAa;AACrB,SAAA,CAAC;AACF,QAAA,cAAc,EAAE,cAAc,CAAC,KAAK,CAAC;AACrC,QAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,IAAA,CAAC;IAED,MAAM,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC/B,cAAc,EAAE,mBAAmB,EAAE;IAErC,OAAO;QACL,GAAG;QACH,GAAG;QACH,KAAK;QACL,SAAS;QACT,OAAO;KACR;AACH;;;;"}
@@ -0,0 +1,6 @@
1
+ import { SetState, StoreConfig } from "./createStore";
2
+ export declare const getPersistHandler: <TState extends object, TActions extends object = Record<never, never>>(config: StoreConfig<TState, TActions>, isBrowser: boolean, get: () => TState, set: SetState<TState>) => {
3
+ initializeSnapshots: () => void;
4
+ updateSnapshot: (newState: TState) => void;
5
+ updateState: () => void;
6
+ } | null;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const getPersistenceHandlers = (config, isBrowser, get, set) => {
3
+ const getPersistHandler = (config, isBrowser, get, set) => {
4
4
  if (!config.persist) {
5
5
  return null;
6
6
  }
@@ -38,5 +38,5 @@ const getPersistenceHandlers = (config, isBrowser, get, set) => {
38
38
  };
39
39
  };
40
40
 
41
- exports.getPersistenceHandlers = getPersistenceHandlers;
42
- //# sourceMappingURL=getPersistenceHandlers.js.map
41
+ exports.getPersistHandler = getPersistHandler;
42
+ //# sourceMappingURL=getPersistHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPersistHandler.js","sources":["../../../src/lib/getPersistHandler.ts"],"sourcesContent":["import { SetState, StoreConfig } from \"./createStore\";\n\nexport const getPersistHandler = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n isBrowser: boolean,\n get: () => TState,\n set: SetState<TState>,\n) => {\n if (!config.persist) {\n return null;\n }\n\n const storage = config.storage ?? (isBrowser ? localStorage : undefined);\n\n if (!storage) {\n return null;\n }\n\n const { key, serializer = JSON, initialState } = config;\n const initKey = `init_${key}`;\n\n const initializeSnapshots = () => {\n const initialStateSnapshot = storage.getItem(initKey);\n const initialStateString = serializer.stringify(initialState);\n\n if (initialStateSnapshot !== initialStateString) {\n storage.setItem(initKey, initialStateString);\n storage.removeItem(key);\n }\n };\n\n const updateSnapshot = (newState: TState) => {\n const currentSnapshot = storage.getItem(key);\n const newSnapshot = serializer.stringify(newState);\n\n if (newSnapshot !== currentSnapshot) {\n storage.setItem(key, newSnapshot);\n }\n };\n\n const updateState = () => {\n const currentSnapshot = storage.getItem(key);\n\n if (currentSnapshot && currentSnapshot !== serializer.stringify(get())) {\n set(serializer.parse(currentSnapshot));\n }\n };\n\n return {\n initializeSnapshots,\n updateSnapshot,\n updateState,\n };\n};\n"],"names":[],"mappings":";;AAEO,MAAM,iBAAiB,GAAG,CAI/B,MAAqC,EACrC,SAAkB,EAClB,GAAiB,EACjB,GAAqB,KACnB;AACF,IAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACnB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAExE,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,IAAI;IACb;IAEA,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM;AACvD,IAAA,MAAM,OAAO,GAAG,CAAA,KAAA,EAAQ,GAAG,EAAE;IAE7B,MAAM,mBAAmB,GAAG,MAAK;QAC/B,MAAM,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QACrD,MAAM,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;AAE7D,QAAA,IAAI,oBAAoB,KAAK,kBAAkB,EAAE;AAC/C,YAAA,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC;AAC5C,YAAA,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACzB;AACF,IAAA,CAAC;AAED,IAAA,MAAM,cAAc,GAAG,CAAC,QAAgB,KAAI;QAC1C,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QAC5C,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;AAElD,QAAA,IAAI,WAAW,KAAK,eAAe,EAAE;AACnC,YAAA,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC;QACnC;AACF,IAAA,CAAC;IAED,MAAM,WAAW,GAAG,MAAK;QACvB,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;AAE5C,QAAA,IAAI,eAAe,IAAI,eAAe,KAAK,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE;YACtE,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACxC;AACF,IAAA,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,cAAc;QACd,WAAW;KACZ;AACH;;;;"}
@@ -12,7 +12,7 @@ export type Store<TState extends object, TActions extends object> = {
12
12
  /** Subscribes to changes in the state of the store. Returns an unsubscribe function. */
13
13
  subscribe: (listener: Listener<TState>) => () => void;
14
14
  };
15
- export type EventHandlerContext<TState extends object> = {
15
+ export type StoreEventContext<TState extends object> = {
16
16
  /** The current state of the store. */
17
17
  state: TState;
18
18
  /** Sets the state of the store. */
@@ -20,9 +20,9 @@ export type EventHandlerContext<TState extends object> = {
20
20
  /** Resets the state of the store to its initial value. */
21
21
  reset: () => TState;
22
22
  };
23
- export type StoreEventHandler<TState extends object> = (context: EventHandlerContext<TState>) => void;
23
+ export type StoreEventHandler<TState extends object> = (context: StoreEventContext<TState>) => void;
24
24
  export type StateModifier<TState extends object> = Partial<TState> | ((state: TState) => Partial<TState>);
25
- export type StateFunctions<TState extends object> = {
25
+ export type StateHandler<TState extends object> = {
26
26
  /** Returns the current state of the store. */
27
27
  get: () => TState;
28
28
  /** Sets the state of the store. */
@@ -30,7 +30,7 @@ export type StateFunctions<TState extends object> = {
30
30
  /** Resets the state of the store to its initial value. */
31
31
  reset: () => TState;
32
32
  };
33
- export type DefineActions<TState extends object, TActions> = (stateFunctions: StateFunctions<TState>) => TActions;
33
+ export type DefineActions<TState extends object, TActions> = (stateHandler: StateHandler<TState>) => TActions;
34
34
  type BaseConfig<TState extends object, TActions extends object> = {
35
35
  /** The initial state of the store. */
36
36
  initialState: TState;
@@ -1,4 +1,4 @@
1
- import { getPersistenceHandlers } from './getPersistenceHandlers.js';
1
+ import { getPersistHandler } from './getPersistHandler.js';
2
2
  import { merge } from './merge.js';
3
3
 
4
4
  /**
@@ -86,34 +86,34 @@ import { merge } from './merge.js';
86
86
  const createStore = (config) => {
87
87
  const { initialState, defineActions, onLoad, onAttach, onDetach, onChange } = config;
88
88
  let state = initialState;
89
- const listeners = new Set();
90
89
  const get = () => state;
91
90
  const setSilently = (stateModifier) => {
92
91
  state = merge(state, stateModifier);
93
92
  return state;
94
93
  };
95
- const resetSilently = () => setSilently(initialState);
96
- const dispatch = () => {
97
- onChange?.({ state, set: setSilently, reset: resetSilently });
98
- persistenceHandlers?.updateSnapshot(state);
99
- listeners.forEach((listener) => listener(state));
100
- };
101
94
  const set = (stateModifier) => {
102
95
  setSilently(stateModifier);
103
96
  dispatch();
104
97
  return state;
105
98
  };
99
+ const resetSilently = () => setSilently(initialState);
106
100
  const reset = () => {
107
101
  resetSilently();
108
102
  dispatch();
109
103
  return state;
110
104
  };
105
+ const listeners = new Set();
106
+ const actions = defineActions
107
+ ? defineActions({ set, get, reset })
108
+ : {};
109
+ const IS_BROWSER = typeof window !== "undefined";
110
+ const persistHandler = getPersistHandler(config, IS_BROWSER, get, set);
111
111
  const subscribe = (listener) => {
112
112
  if (listeners.size === 0) {
113
113
  onAttach?.({ state, set, reset });
114
- persistenceHandlers?.updateState();
115
- if (IS_BROWSER && persistenceHandlers) {
116
- window.addEventListener("focus", persistenceHandlers.updateState);
114
+ persistHandler?.updateState();
115
+ if (IS_BROWSER && persistHandler) {
116
+ window.addEventListener("focus", persistHandler.updateState);
117
117
  }
118
118
  }
119
119
  listener(state);
@@ -122,19 +122,23 @@ const createStore = (config) => {
122
122
  listeners.delete(listener);
123
123
  if (listeners.size === 0) {
124
124
  onDetach?.({ state, set, reset });
125
- if (IS_BROWSER && persistenceHandlers) {
126
- window.removeEventListener("focus", persistenceHandlers.updateState);
125
+ if (IS_BROWSER && persistHandler) {
126
+ window.removeEventListener("focus", persistHandler.updateState);
127
127
  }
128
128
  }
129
129
  };
130
130
  };
131
- const actions = defineActions
132
- ? defineActions({ set, get, reset })
133
- : {};
134
- const IS_BROWSER = typeof window !== "undefined";
135
- const persistenceHandlers = getPersistenceHandlers(config, IS_BROWSER, get, set);
131
+ const dispatch = () => {
132
+ onChange?.({
133
+ state,
134
+ set: setSilently,
135
+ reset: resetSilently,
136
+ });
137
+ persistHandler?.updateSnapshot(state);
138
+ listeners.forEach((listener) => listener(state));
139
+ };
136
140
  onLoad?.({ state, set, reset });
137
- persistenceHandlers?.initializeSnapshots();
141
+ persistHandler?.initializeSnapshots();
138
142
  return {
139
143
  get,
140
144
  set,
@@ -1 +1 @@
1
- {"version":3,"file":"createStore.js","sources":["../../../src/lib/createStore.ts"],"sourcesContent":["import { getPersistenceHandlers } from \"./getPersistenceHandlers\";\nimport { merge } from \"./merge\";\n\ntype Listener<TState extends object> = (state: TState) => void;\n\nexport type SetState<TState extends object> = (\n stateModifier: StateModifier<TState>,\n) => TState;\n\nexport type Store<TState extends object, TActions extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n /** Actions that can modify the state of the store. */\n actions: TActions;\n /** Subscribes to changes in the state of the store. Returns an unsubscribe function. */\n subscribe: (listener: Listener<TState>) => () => void;\n};\n\nexport type EventHandlerContext<TState extends object> = {\n /** The current state of the store. */\n state: TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type StoreEventHandler<TState extends object> = (\n context: EventHandlerContext<TState>,\n) => void;\n\nexport type StateModifier<TState extends object> =\n | Partial<TState>\n | ((state: TState) => Partial<TState>);\n\nexport type StateFunctions<TState extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type DefineActions<TState extends object, TActions> = (\n stateFunctions: StateFunctions<TState>,\n) => TActions;\n\ntype BaseConfig<TState extends object, TActions extends object> = {\n /** The initial state of the store. */\n initialState: TState;\n /** A function that defines actions that can modify the state. */\n defineActions?: DefineActions<TState, TActions>;\n /** Invoked when the store is created. */\n onLoad?: StoreEventHandler<TState>;\n /** Invoked when the store is subscribed to. */\n onAttach?: StoreEventHandler<TState>;\n /** Invoked when the store is unsubscribed from. */\n onDetach?: StoreEventHandler<TState>;\n /** Invoked whenever the state changes. */\n onChange?: StoreEventHandler<TState>;\n};\n\nexport type StorageAPI = {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Serializer<T = any> = {\n stringify: (value: T) => string;\n parse: (value: string) => T;\n};\n\ntype NonPersistentConfig = {\n /** Whether to persist the state of the store. */\n persist?: false;\n};\n\ntype PersistentConfig<TState extends object> = {\n /** Whether to persist the state of the store. */\n persist: true;\n /** The unique key used to identify this store in storage. */\n key: string;\n /** The storage to use for persisting the state. Defaults to local storage if available. */\n storage?: StorageAPI;\n /** The serializer to use for storing the state. Defaults to JSON. */\n serializer?: Serializer<TState>;\n};\n\nexport type StoreConfig<\n TState extends object,\n TActions extends object,\n> = BaseConfig<TState, TActions> &\n (NonPersistentConfig | PersistentConfig<TState>);\n\n/**\n * Creates a store with an initial state and actions that can modify the state.\n *\n * @param {StoreConfig<TState, TActions>} [config] - The configuration for the store.\n *\n * @returns {Store<TState, TActions>} The created store with state management methods.\n *\n * @example\n * Basic usage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * @example\n * With event handlers:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import { State } from \"./types\";\n *\n * const initialState: State = { data: null, loading: true, error: null };\n *\n * const store = createStore({\n * initialState,\n * onAttach: async ({ set }) => {\n * try {\n * const response = await fetch(\"https://api.example.com/data\");\n * const data = await response.json();\n * set({ data, loading: false });\n * } catch (error) {\n * set({ error, loading: false });\n * }\n * },\n * onDetach: ({ reset }) => reset(),\n * });\n * ```\n *\n * @example\n * Persistent store (uses local storage by default):\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * **Note:** The state needs to be serializable by whatever serializer you choose (JSON by default).\n * If you need something more versatile I would recommend using a library like [superjson](https://github.com/flightcontrolhq/superjson).\n *\n * @example\n * With superjson serialization and session storage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import superjson from \"superjson\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * serializer: superjson,\n * storage: sessionStorage,\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n */\nexport const createStore = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n): Store<TState, TActions> => {\n const { initialState, defineActions, onLoad, onAttach, onDetach, onChange } =\n config;\n\n let state = initialState;\n const listeners = new Set<Listener<TState>>();\n\n const get = () => state;\n\n const setSilently = (stateModifier: StateModifier<TState>) => {\n state = merge(state, stateModifier);\n return state;\n };\n\n const resetSilently = () => setSilently(initialState);\n\n const dispatch = () => {\n onChange?.({ state, set: setSilently, reset: resetSilently });\n persistenceHandlers?.updateSnapshot(state);\n listeners.forEach((listener) => listener(state));\n };\n\n const set = (stateModifier: StateModifier<TState>) => {\n setSilently(stateModifier);\n dispatch();\n return state;\n };\n\n const reset = () => {\n resetSilently();\n dispatch();\n return state;\n };\n\n const subscribe = (listener: Listener<TState>) => {\n if (listeners.size === 0) {\n onAttach?.({ state, set, reset });\n persistenceHandlers?.updateState();\n\n if (IS_BROWSER && persistenceHandlers) {\n window.addEventListener(\"focus\", persistenceHandlers.updateState);\n }\n }\n\n listener(state);\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n\n if (listeners.size === 0) {\n onDetach?.({ state, set, reset });\n\n if (IS_BROWSER && persistenceHandlers) {\n window.removeEventListener(\"focus\", persistenceHandlers.updateState);\n }\n }\n };\n };\n\n const actions = defineActions\n ? defineActions({ set, get, reset })\n : ({} as TActions);\n\n const IS_BROWSER = typeof window !== \"undefined\";\n const persistenceHandlers = getPersistenceHandlers<TState, TActions>(\n config,\n IS_BROWSER,\n get,\n set,\n );\n\n onLoad?.({ state, set, reset });\n persistenceHandlers?.initializeSnapshots();\n\n return {\n get,\n set,\n reset,\n subscribe,\n actions,\n };\n};\n"],"names":[],"mappings":";;;AAqGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFG;AACI,MAAM,WAAW,GAAG,CAIzB,MAAqC,KACV;AAC3B,IAAA,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GACzE,MAAM;IAER,IAAI,KAAK,GAAG,YAAY;AACxB,IAAA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB;AAE7C,IAAA,MAAM,GAAG,GAAG,MAAM,KAAK;AAEvB,IAAA,MAAM,WAAW,GAAG,CAAC,aAAoC,KAAI;AAC3D,QAAA,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC;AACnC,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAK;AACpB,QAAA,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;AAC7D,QAAA,mBAAmB,EAAE,cAAc,CAAC,KAAK,CAAC;AAC1C,QAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,IAAA,CAAC;AAED,IAAA,MAAM,GAAG,GAAG,CAAC,aAAoC,KAAI;QACnD,WAAW,CAAC,aAAa,CAAC;AAC1B,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;IAED,MAAM,KAAK,GAAG,MAAK;AACjB,QAAA,aAAa,EAAE;AACf,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,SAAS,GAAG,CAAC,QAA0B,KAAI;AAC/C,QAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;YACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;YACjC,mBAAmB,EAAE,WAAW,EAAE;AAElC,YAAA,IAAI,UAAU,IAAI,mBAAmB,EAAE;gBACrC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC;YACnE;QACF;QAEA,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEvB,QAAA,OAAO,MAAK;AACV,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAE1B,YAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;gBACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAEjC,gBAAA,IAAI,UAAU,IAAI,mBAAmB,EAAE;oBACrC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC;gBACtE;YACF;AACF,QAAA,CAAC;AACH,IAAA,CAAC;IAED,MAAM,OAAO,GAAG;UACZ,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;UAChC,EAAe;AAEpB,IAAA,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW;AAChD,IAAA,MAAM,mBAAmB,GAAG,sBAAsB,CAChD,MAAM,EACN,UAAU,EACV,GAAG,EACH,GAAG,CACJ;IAED,MAAM,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC/B,mBAAmB,EAAE,mBAAmB,EAAE;IAE1C,OAAO;QACL,GAAG;QACH,GAAG;QACH,KAAK;QACL,SAAS;QACT,OAAO;KACR;AACH;;;;"}
1
+ {"version":3,"file":"createStore.js","sources":["../../../src/lib/createStore.ts"],"sourcesContent":["import { getPersistHandler } from \"./getPersistHandler\";\nimport { merge } from \"./merge\";\n\ntype Listener<TState extends object> = (state: TState) => void;\n\nexport type SetState<TState extends object> = (\n stateModifier: StateModifier<TState>,\n) => TState;\n\nexport type Store<TState extends object, TActions extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n /** Actions that can modify the state of the store. */\n actions: TActions;\n /** Subscribes to changes in the state of the store. Returns an unsubscribe function. */\n subscribe: (listener: Listener<TState>) => () => void;\n};\n\nexport type StoreEventContext<TState extends object> = {\n /** The current state of the store. */\n state: TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type StoreEventHandler<TState extends object> = (\n context: StoreEventContext<TState>,\n) => void;\n\nexport type StateModifier<TState extends object> =\n | Partial<TState>\n | ((state: TState) => Partial<TState>);\n\nexport type StateHandler<TState extends object> = {\n /** Returns the current state of the store. */\n get: () => TState;\n /** Sets the state of the store. */\n set: SetState<TState>;\n /** Resets the state of the store to its initial value. */\n reset: () => TState;\n};\n\nexport type DefineActions<TState extends object, TActions> = (\n stateHandler: StateHandler<TState>,\n) => TActions;\n\ntype BaseConfig<TState extends object, TActions extends object> = {\n /** The initial state of the store. */\n initialState: TState;\n /** A function that defines actions that can modify the state. */\n defineActions?: DefineActions<TState, TActions>;\n /** Invoked when the store is created. */\n onLoad?: StoreEventHandler<TState>;\n /** Invoked when the store is subscribed to. */\n onAttach?: StoreEventHandler<TState>;\n /** Invoked when the store is unsubscribed from. */\n onDetach?: StoreEventHandler<TState>;\n /** Invoked whenever the state changes. */\n onChange?: StoreEventHandler<TState>;\n};\n\nexport type StorageAPI = {\n getItem: (key: string) => string | null;\n setItem: (key: string, value: string) => void;\n removeItem: (key: string) => void;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type Serializer<T = any> = {\n stringify: (value: T) => string;\n parse: (value: string) => T;\n};\n\ntype NonPersistentConfig = {\n /** Whether to persist the state of the store. */\n persist?: false;\n};\n\ntype PersistentConfig<TState extends object> = {\n /** Whether to persist the state of the store. */\n persist: true;\n /** The unique key used to identify this store in storage. */\n key: string;\n /** The storage to use for persisting the state. Defaults to local storage if available. */\n storage?: StorageAPI;\n /** The serializer to use for storing the state. Defaults to JSON. */\n serializer?: Serializer<TState>;\n};\n\nexport type StoreConfig<\n TState extends object,\n TActions extends object,\n> = BaseConfig<TState, TActions> &\n (NonPersistentConfig | PersistentConfig<TState>);\n\n/**\n * Creates a store with an initial state and actions that can modify the state.\n *\n * @param {StoreConfig<TState, TActions>} [config] - The configuration for the store.\n *\n * @returns {Store<TState, TActions>} The created store with state management methods.\n *\n * @example\n * Basic usage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * @example\n * With event handlers:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import { State } from \"./types\";\n *\n * const initialState: State = { data: null, loading: true, error: null };\n *\n * const store = createStore({\n * initialState,\n * onAttach: async ({ set }) => {\n * try {\n * const response = await fetch(\"https://api.example.com/data\");\n * const data = await response.json();\n * set({ data, loading: false });\n * } catch (error) {\n * set({ error, loading: false });\n * }\n * },\n * onDetach: ({ reset }) => reset(),\n * });\n * ```\n *\n * @example\n * Persistent store (uses local storage by default):\n * ```ts\n * import { createStore } from \"dharma-core\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n *\n * **Note:** The state needs to be serializable by whatever serializer you choose (JSON by default).\n * If you need something more versatile I would recommend using a library like [superjson](https://github.com/flightcontrolhq/superjson).\n *\n * @example\n * With superjson serialization and session storage:\n * ```ts\n * import { createStore } from \"dharma-core\";\n * import superjson from \"superjson\";\n *\n * const store = createStore({\n * persist: true,\n * key: \"count\",\n * serializer: superjson,\n * storage: sessionStorage,\n * initialState: { count: 0 },\n * defineActions: ({ set }) => ({\n * increment: () => set((state) => ({ count: state.count + 1 })),\n * decrement: () => set((state) => ({ count: state.count - 1 })),\n * }),\n * });\n * ```\n */\nexport const createStore = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n): Store<TState, TActions> => {\n const { initialState, defineActions, onLoad, onAttach, onDetach, onChange } =\n config;\n\n let state = initialState;\n\n const get = () => state;\n\n const setSilently = (stateModifier: StateModifier<TState>) => {\n state = merge(state, stateModifier);\n return state;\n };\n\n const set = (stateModifier: StateModifier<TState>) => {\n setSilently(stateModifier);\n dispatch();\n return state;\n };\n\n const resetSilently = () => setSilently(initialState);\n\n const reset = () => {\n resetSilently();\n dispatch();\n return state;\n };\n\n const listeners = new Set<Listener<TState>>();\n const actions = defineActions\n ? defineActions({ set, get, reset })\n : ({} as TActions);\n const IS_BROWSER = typeof window !== \"undefined\";\n const persistHandler = getPersistHandler(config, IS_BROWSER, get, set);\n\n const subscribe = (listener: Listener<TState>) => {\n if (listeners.size === 0) {\n onAttach?.({ state, set, reset });\n persistHandler?.updateState();\n\n if (IS_BROWSER && persistHandler) {\n window.addEventListener(\"focus\", persistHandler.updateState);\n }\n }\n\n listener(state);\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n\n if (listeners.size === 0) {\n onDetach?.({ state, set, reset });\n\n if (IS_BROWSER && persistHandler) {\n window.removeEventListener(\"focus\", persistHandler.updateState);\n }\n }\n };\n };\n\n const dispatch = () => {\n onChange?.({\n state,\n set: setSilently,\n reset: resetSilently,\n });\n persistHandler?.updateSnapshot(state);\n listeners.forEach((listener) => listener(state));\n };\n\n onLoad?.({ state, set, reset });\n persistHandler?.initializeSnapshots();\n\n return {\n get,\n set,\n reset,\n subscribe,\n actions,\n };\n};\n"],"names":[],"mappings":";;;AAqGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFG;AACI,MAAM,WAAW,GAAG,CAIzB,MAAqC,KACV;AAC3B,IAAA,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GACzE,MAAM;IAER,IAAI,KAAK,GAAG,YAAY;AAExB,IAAA,MAAM,GAAG,GAAG,MAAM,KAAK;AAEvB,IAAA,MAAM,WAAW,GAAG,CAAC,aAAoC,KAAI;AAC3D,QAAA,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC;AACnC,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,GAAG,GAAG,CAAC,aAAoC,KAAI;QACnD,WAAW,CAAC,aAAa,CAAC;AAC1B,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC;IAErD,MAAM,KAAK,GAAG,MAAK;AACjB,QAAA,aAAa,EAAE;AACf,QAAA,QAAQ,EAAE;AACV,QAAA,OAAO,KAAK;AACd,IAAA,CAAC;AAED,IAAA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB;IAC7C,MAAM,OAAO,GAAG;UACZ,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE;UAChC,EAAe;AACpB,IAAA,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW;AAChD,IAAA,MAAM,cAAc,GAAG,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC;AAEtE,IAAA,MAAM,SAAS,GAAG,CAAC,QAA0B,KAAI;AAC/C,QAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;YACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;YACjC,cAAc,EAAE,WAAW,EAAE;AAE7B,YAAA,IAAI,UAAU,IAAI,cAAc,EAAE;gBAChC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,CAAC,WAAW,CAAC;YAC9D;QACF;QAEA,QAAQ,CAAC,KAAK,CAAC;AACf,QAAA,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEvB,QAAA,OAAO,MAAK;AACV,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAE1B,YAAA,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE;gBACxB,QAAQ,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAEjC,gBAAA,IAAI,UAAU,IAAI,cAAc,EAAE;oBAChC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,cAAc,CAAC,WAAW,CAAC;gBACjE;YACF;AACF,QAAA,CAAC;AACH,IAAA,CAAC;IAED,MAAM,QAAQ,GAAG,MAAK;AACpB,QAAA,QAAQ,GAAG;YACT,KAAK;AACL,YAAA,GAAG,EAAE,WAAW;AAChB,YAAA,KAAK,EAAE,aAAa;AACrB,SAAA,CAAC;AACF,QAAA,cAAc,EAAE,cAAc,CAAC,KAAK,CAAC;AACrC,QAAA,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;AAClD,IAAA,CAAC;IAED,MAAM,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC/B,cAAc,EAAE,mBAAmB,EAAE;IAErC,OAAO;QACL,GAAG;QACH,GAAG;QACH,KAAK;QACL,SAAS;QACT,OAAO;KACR;AACH;;;;"}
@@ -0,0 +1,6 @@
1
+ import { SetState, StoreConfig } from "./createStore";
2
+ export declare const getPersistHandler: <TState extends object, TActions extends object = Record<never, never>>(config: StoreConfig<TState, TActions>, isBrowser: boolean, get: () => TState, set: SetState<TState>) => {
3
+ initializeSnapshots: () => void;
4
+ updateSnapshot: (newState: TState) => void;
5
+ updateState: () => void;
6
+ } | null;
@@ -1,4 +1,4 @@
1
- const getPersistenceHandlers = (config, isBrowser, get, set) => {
1
+ const getPersistHandler = (config, isBrowser, get, set) => {
2
2
  if (!config.persist) {
3
3
  return null;
4
4
  }
@@ -36,5 +36,5 @@ const getPersistenceHandlers = (config, isBrowser, get, set) => {
36
36
  };
37
37
  };
38
38
 
39
- export { getPersistenceHandlers };
40
- //# sourceMappingURL=getPersistenceHandlers.js.map
39
+ export { getPersistHandler };
40
+ //# sourceMappingURL=getPersistHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPersistHandler.js","sources":["../../../src/lib/getPersistHandler.ts"],"sourcesContent":["import { SetState, StoreConfig } from \"./createStore\";\n\nexport const getPersistHandler = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n isBrowser: boolean,\n get: () => TState,\n set: SetState<TState>,\n) => {\n if (!config.persist) {\n return null;\n }\n\n const storage = config.storage ?? (isBrowser ? localStorage : undefined);\n\n if (!storage) {\n return null;\n }\n\n const { key, serializer = JSON, initialState } = config;\n const initKey = `init_${key}`;\n\n const initializeSnapshots = () => {\n const initialStateSnapshot = storage.getItem(initKey);\n const initialStateString = serializer.stringify(initialState);\n\n if (initialStateSnapshot !== initialStateString) {\n storage.setItem(initKey, initialStateString);\n storage.removeItem(key);\n }\n };\n\n const updateSnapshot = (newState: TState) => {\n const currentSnapshot = storage.getItem(key);\n const newSnapshot = serializer.stringify(newState);\n\n if (newSnapshot !== currentSnapshot) {\n storage.setItem(key, newSnapshot);\n }\n };\n\n const updateState = () => {\n const currentSnapshot = storage.getItem(key);\n\n if (currentSnapshot && currentSnapshot !== serializer.stringify(get())) {\n set(serializer.parse(currentSnapshot));\n }\n };\n\n return {\n initializeSnapshots,\n updateSnapshot,\n updateState,\n };\n};\n"],"names":[],"mappings":"AAEO,MAAM,iBAAiB,GAAG,CAI/B,MAAqC,EACrC,SAAkB,EAClB,GAAiB,EACjB,GAAqB,KACnB;AACF,IAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACnB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAExE,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,IAAI;IACb;IAEA,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM;AACvD,IAAA,MAAM,OAAO,GAAG,CAAA,KAAA,EAAQ,GAAG,EAAE;IAE7B,MAAM,mBAAmB,GAAG,MAAK;QAC/B,MAAM,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QACrD,MAAM,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;AAE7D,QAAA,IAAI,oBAAoB,KAAK,kBAAkB,EAAE;AAC/C,YAAA,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC;AAC5C,YAAA,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACzB;AACF,IAAA,CAAC;AAED,IAAA,MAAM,cAAc,GAAG,CAAC,QAAgB,KAAI;QAC1C,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QAC5C,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;AAElD,QAAA,IAAI,WAAW,KAAK,eAAe,EAAE;AACnC,YAAA,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC;QACnC;AACF,IAAA,CAAC;IAED,MAAM,WAAW,GAAG,MAAK;QACvB,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;AAE5C,QAAA,IAAI,eAAe,IAAI,eAAe,KAAK,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE;YACtE,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACxC;AACF,IAAA,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,cAAc;QACd,WAAW;KACZ;AACH;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dharma-core",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "author": "Frans Ekman <fransedvinekman@gmail.com>",
5
5
  "license": "MIT",
6
6
  "description": "My package description",
@@ -1,6 +0,0 @@
1
- import { SetState, StoreConfig } from "./createStore";
2
- export declare const getPersistenceHandlers: <TState extends object, TActions extends object = Record<never, never>>(config: StoreConfig<TState, TActions>, isBrowser: boolean, get: () => TState, set: SetState<TState>) => {
3
- initializeSnapshots: () => void;
4
- updateSnapshot: (newState: TState) => void;
5
- updateState: () => void;
6
- } | null;
@@ -1 +0,0 @@
1
- {"version":3,"file":"getPersistenceHandlers.js","sources":["../../../src/lib/getPersistenceHandlers.ts"],"sourcesContent":["import { SetState, StoreConfig } from \"./createStore\";\n\nexport const getPersistenceHandlers = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n isBrowser: boolean,\n get: () => TState,\n set: SetState<TState>,\n) => {\n if (!config.persist) {\n return null;\n }\n\n const storage = config.storage ?? (isBrowser ? localStorage : undefined);\n\n if (!storage) {\n return null;\n }\n\n const { key, serializer = JSON, initialState } = config;\n const initKey = `init_${key}`;\n\n const initializeSnapshots = () => {\n const initialStateSnapshot = storage.getItem(initKey);\n const initialStateString = serializer.stringify(initialState);\n\n if (initialStateSnapshot !== initialStateString) {\n storage.setItem(initKey, initialStateString);\n storage.removeItem(key);\n }\n };\n\n const updateSnapshot = (newState: TState) => {\n const currentSnapshot = storage.getItem(key);\n const newSnapshot = serializer.stringify(newState);\n\n if (newSnapshot !== currentSnapshot) {\n storage.setItem(key, newSnapshot);\n }\n };\n\n const updateState = () => {\n const currentSnapshot = storage.getItem(key);\n\n if (currentSnapshot && currentSnapshot !== serializer.stringify(get())) {\n set(serializer.parse(currentSnapshot));\n }\n };\n\n return {\n initializeSnapshots,\n updateSnapshot,\n updateState,\n };\n};\n"],"names":[],"mappings":";;AAEO,MAAM,sBAAsB,GAAG,CAIpC,MAAqC,EACrC,SAAkB,EAClB,GAAiB,EACjB,GAAqB,KACnB;AACF,IAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACnB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAExE,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,IAAI;IACb;IAEA,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM;AACvD,IAAA,MAAM,OAAO,GAAG,CAAA,KAAA,EAAQ,GAAG,EAAE;IAE7B,MAAM,mBAAmB,GAAG,MAAK;QAC/B,MAAM,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QACrD,MAAM,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;AAE7D,QAAA,IAAI,oBAAoB,KAAK,kBAAkB,EAAE;AAC/C,YAAA,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC;AAC5C,YAAA,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACzB;AACF,IAAA,CAAC;AAED,IAAA,MAAM,cAAc,GAAG,CAAC,QAAgB,KAAI;QAC1C,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QAC5C,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;AAElD,QAAA,IAAI,WAAW,KAAK,eAAe,EAAE;AACnC,YAAA,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC;QACnC;AACF,IAAA,CAAC;IAED,MAAM,WAAW,GAAG,MAAK;QACvB,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;AAE5C,QAAA,IAAI,eAAe,IAAI,eAAe,KAAK,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE;YACtE,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACxC;AACF,IAAA,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,cAAc;QACd,WAAW;KACZ;AACH;;;;"}
@@ -1,6 +0,0 @@
1
- import { SetState, StoreConfig } from "./createStore";
2
- export declare const getPersistenceHandlers: <TState extends object, TActions extends object = Record<never, never>>(config: StoreConfig<TState, TActions>, isBrowser: boolean, get: () => TState, set: SetState<TState>) => {
3
- initializeSnapshots: () => void;
4
- updateSnapshot: (newState: TState) => void;
5
- updateState: () => void;
6
- } | null;
@@ -1 +0,0 @@
1
- {"version":3,"file":"getPersistenceHandlers.js","sources":["../../../src/lib/getPersistenceHandlers.ts"],"sourcesContent":["import { SetState, StoreConfig } from \"./createStore\";\n\nexport const getPersistenceHandlers = <\n TState extends object,\n TActions extends object = Record<never, never>,\n>(\n config: StoreConfig<TState, TActions>,\n isBrowser: boolean,\n get: () => TState,\n set: SetState<TState>,\n) => {\n if (!config.persist) {\n return null;\n }\n\n const storage = config.storage ?? (isBrowser ? localStorage : undefined);\n\n if (!storage) {\n return null;\n }\n\n const { key, serializer = JSON, initialState } = config;\n const initKey = `init_${key}`;\n\n const initializeSnapshots = () => {\n const initialStateSnapshot = storage.getItem(initKey);\n const initialStateString = serializer.stringify(initialState);\n\n if (initialStateSnapshot !== initialStateString) {\n storage.setItem(initKey, initialStateString);\n storage.removeItem(key);\n }\n };\n\n const updateSnapshot = (newState: TState) => {\n const currentSnapshot = storage.getItem(key);\n const newSnapshot = serializer.stringify(newState);\n\n if (newSnapshot !== currentSnapshot) {\n storage.setItem(key, newSnapshot);\n }\n };\n\n const updateState = () => {\n const currentSnapshot = storage.getItem(key);\n\n if (currentSnapshot && currentSnapshot !== serializer.stringify(get())) {\n set(serializer.parse(currentSnapshot));\n }\n };\n\n return {\n initializeSnapshots,\n updateSnapshot,\n updateState,\n };\n};\n"],"names":[],"mappings":"AAEO,MAAM,sBAAsB,GAAG,CAIpC,MAAqC,EACrC,SAAkB,EAClB,GAAiB,EACjB,GAAqB,KACnB;AACF,IAAA,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE;AACnB,QAAA,OAAO,IAAI;IACb;AAEA,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;IAExE,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,OAAO,IAAI;IACb;IAEA,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM;AACvD,IAAA,MAAM,OAAO,GAAG,CAAA,KAAA,EAAQ,GAAG,EAAE;IAE7B,MAAM,mBAAmB,GAAG,MAAK;QAC/B,MAAM,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QACrD,MAAM,kBAAkB,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;AAE7D,QAAA,IAAI,oBAAoB,KAAK,kBAAkB,EAAE;AAC/C,YAAA,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,CAAC;AAC5C,YAAA,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QACzB;AACF,IAAA,CAAC;AAED,IAAA,MAAM,cAAc,GAAG,CAAC,QAAgB,KAAI;QAC1C,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;QAC5C,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;AAElD,QAAA,IAAI,WAAW,KAAK,eAAe,EAAE;AACnC,YAAA,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC;QACnC;AACF,IAAA,CAAC;IAED,MAAM,WAAW,GAAG,MAAK;QACvB,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;AAE5C,QAAA,IAAI,eAAe,IAAI,eAAe,KAAK,UAAU,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE;YACtE,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACxC;AACF,IAAA,CAAC;IAED,OAAO;QACL,mBAAmB;QACnB,cAAc;QACd,WAAW;KACZ;AACH;;;;"}