nusm 0.1.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/dist/adapters/indexDbAdapter.d.ts +3 -0
  4. package/dist/adapters/indexDbAdapter.d.ts.map +1 -0
  5. package/dist/adapters/indexDbAdapter.js +53 -0
  6. package/dist/adapters/indexDbAdapter.js.map +1 -0
  7. package/dist/adapters/localStorageAdapter.d.ts +3 -0
  8. package/dist/adapters/localStorageAdapter.d.ts.map +1 -0
  9. package/dist/adapters/localStorageAdapter.js +6 -0
  10. package/dist/adapters/localStorageAdapter.js.map +1 -0
  11. package/dist/adapters/sessionStorageAdapter.d.ts +3 -0
  12. package/dist/adapters/sessionStorageAdapter.d.ts.map +1 -0
  13. package/dist/adapters/sessionStorageAdapter.js +6 -0
  14. package/dist/adapters/sessionStorageAdapter.js.map +1 -0
  15. package/dist/adapters/storageAdapter.d.ts +3 -0
  16. package/dist/adapters/storageAdapter.d.ts.map +1 -0
  17. package/dist/adapters/storageAdapter.js +62 -0
  18. package/dist/adapters/storageAdapter.js.map +1 -0
  19. package/dist/core/createNusmStore.d.ts +3 -0
  20. package/dist/core/createNusmStore.d.ts.map +1 -0
  21. package/dist/core/createNusmStore.js +491 -0
  22. package/dist/core/createNusmStore.js.map +1 -0
  23. package/dist/devtools/client.d.ts +15 -0
  24. package/dist/devtools/client.d.ts.map +1 -0
  25. package/dist/devtools/client.js +21 -0
  26. package/dist/devtools/client.js.map +1 -0
  27. package/dist/devtools/plugin.d.ts +3 -0
  28. package/dist/devtools/plugin.d.ts.map +1 -0
  29. package/dist/devtools/plugin.js +57 -0
  30. package/dist/devtools/plugin.js.map +1 -0
  31. package/dist/index.d.ts +7 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +6 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/react/index.d.ts +11 -0
  36. package/dist/react/index.d.ts.map +1 -0
  37. package/dist/react/index.js +32 -0
  38. package/dist/react/index.js.map +1 -0
  39. package/dist/types.d.ts +112 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +2 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/utils.d.ts +5 -0
  44. package/dist/utils.d.ts.map +1 -0
  45. package/dist/utils.js +30 -0
  46. package/dist/utils.js.map +1 -0
  47. package/package.json +96 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 nusm contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,240 @@
1
+ <p align="center">
2
+ <img src="./logo.svg" alt="nusm" height="100" />
3
+ </p>
4
+
5
+ # nusm
6
+ Non Uniform State Manager (nusm) > Pronounced **noose em** (/ˈnuːs əm/)
7
+ is a persistence-ready wrapper around
8
+ [@tanstack/store](https://github.com/TanStack/store) with adapter-based storage
9
+
10
+ ## Features
11
+
12
+ - Same store semantics as @tanstack/store
13
+ - Optional persistence via adapters
14
+ - Entire-store or slice-based persistence
15
+ - Async hydration with deep merge
16
+ - Debounced persistence via @tanstack/pacer
17
+ - Adapter events for cross-tab or external updates
18
+ - React hooks (via `nusm/react`)
19
+ - @tanstack/devtools event support (panel coming soon)
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ bun install `nusm`
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```ts
30
+ import { createNusmStore, createLocalStorageAdapter } from 'nusm'
31
+
32
+ const store = createNusmStore(
33
+ { count: 0 },
34
+ {
35
+ storeId: 'counter',
36
+ adapter: createLocalStorageAdapter(),
37
+ persist: { strategy: 'entire' },
38
+ },
39
+ )
40
+
41
+ await store.ready
42
+ store.setState((state) => ({ count: state.count + 1 }))
43
+ ```
44
+
45
+ ## API
46
+
47
+ ### `createNusmStore(initialState, options?)`
48
+
49
+ Creates a nusm-backed store.
50
+
51
+ ```ts
52
+ import { createNusmStore } from 'nusm'
53
+
54
+ const nusm = createNusmStore(initialState, {
55
+ storeId: 'settings',
56
+ adapter,
57
+ persist: {
58
+ strategy: 'entire',
59
+ },
60
+ })
61
+ ```
62
+
63
+ Return value:
64
+
65
+ - A @tanstack/store instance extended with `ready` (resolves when hydration completes).
66
+
67
+ ### Persistence strategies
68
+
69
+ **Entire store**
70
+
71
+ ```ts
72
+ persist: { strategy: 'entire' }
73
+ ```
74
+
75
+ **Slices**
76
+
77
+ ```ts
78
+ persist: {
79
+ strategy: 'slices',
80
+ slices: [
81
+ {
82
+ key: 'todos',
83
+ select: (state) => state.todos,
84
+ apply: (state, sliceValue) => ({ ...state, todos: sliceValue }),
85
+ },
86
+ ],
87
+ }
88
+ ```
89
+
90
+ ### Hydration configuration
91
+
92
+ ```ts
93
+ persist: {
94
+ strategy: 'entire',
95
+ hydrate: {
96
+ discardPersisted: false,
97
+ validate: (persisted) => ({ ok: true, value: persisted }),
98
+ merge: ({ initial, persisted }) => ({ ...initial, ...persisted }),
99
+ },
100
+ }
101
+ ```
102
+
103
+ ## Adapters
104
+
105
+ Adapters control persistence. They define how nusm reads/writes state and how
106
+ external changes (for example, another tab) are observed.
107
+
108
+ ### Adapter interface
109
+
110
+ ```ts
111
+ type NusmAdapter = {
112
+ name: string
113
+ getItem(key: string): unknown | null | Promise<unknown | null>
114
+ setItem(key: string, value: unknown): void | Promise<void>
115
+ removeItem(key: string): void | Promise<void>
116
+ getAllKeys?(): string[] | Promise<string[]>
117
+ clear?(): void | Promise<void>
118
+ subscribe?(listener: (event: { type: 'set' | 'remove' | 'clear'; key?: string }) => void): () => void
119
+ resolveKey?(params: { storeId: string; sliceKey?: string; kind: 'entire' | 'slice' }): string
120
+ pacer?: false | { wait?: number; maxWait?: number; leading?: boolean; trailing?: boolean }
121
+ }
122
+ ```
123
+
124
+ Notes:
125
+
126
+ - `getAllKeys` enables more complete persisted snapshots.
127
+ - `resolveKey` lets you control key layout. When omitted, nusm uses
128
+ `nusm:<storeId>:entire` and `nusm:<storeId>:slice:<sliceKey>`.
129
+ - `subscribe` should emit adapter events for cross-tab or external updates.
130
+ - `pacer` controls debouncing of writes. Use `false` to write immediately.
131
+
132
+ ### Creating a custom adapter
133
+
134
+ ```ts
135
+ const memoryAdapter: NusmAdapter = {
136
+ name: 'memory',
137
+ getItem: (key) => store.get(key) ?? null,
138
+ setItem: (key, value) => store.set(key, value),
139
+ removeItem: (key) => store.delete(key),
140
+ getAllKeys: () => Array.from(store.keys()),
141
+ resolveKey: ({ storeId, kind, sliceKey }) =>
142
+ kind === 'entire'
143
+ ? `nusm:${storeId}:entire`
144
+ : `nusm:${storeId}:slice:${sliceKey}`,
145
+ }
146
+ ```
147
+
148
+ ### Local Storage
149
+
150
+ ```ts
151
+ import { createLocalStorageAdapter } from 'nusm'
152
+
153
+ const adapter = createLocalStorageAdapter()
154
+ ```
155
+
156
+ Options:
157
+
158
+ - `storage`: a `Storage`-like implementation (defaults to `window.localStorage`).
159
+ - `prefix`: key prefix (default: `nusm`).
160
+ - `serialize`: custom serializer (default: `superjson.stringify`).
161
+ - `deserialize`: custom deserializer (default: `superjson.parse`).
162
+ - `pacer`: persistence debouncer configuration.
163
+
164
+ ### Session Storage
165
+
166
+ ```ts
167
+ import { createSessionStorageAdapter } from 'nusm'
168
+
169
+ const adapter = createSessionStorageAdapter()
170
+ ```
171
+
172
+ Options:
173
+
174
+ - `storage`: a `Storage`-like implementation (defaults to `window.sessionStorage`).
175
+ - `prefix`: key prefix (default: `nusm`).
176
+ - `serialize`: custom serializer (default: `superjson.stringify`).
177
+ - `deserialize`: custom deserializer (default: `superjson.parse`).
178
+ - `pacer`: persistence debouncer configuration.
179
+
180
+ ### IndexDB
181
+
182
+ ```ts
183
+ import { createIndexDbAdapter } from 'nusm'
184
+
185
+ const adapter = createIndexDbAdapter({ dbName: 'my-db' })
186
+ ```
187
+
188
+ Options:
189
+
190
+ - `dbName`: database name (default: `nusm`).
191
+ - `storeName`: object store name (default: `nusm`).
192
+ - `version`: database version (default: `1`).
193
+ - `serialize`: custom serializer (default: `superjson.stringify`).
194
+ - `deserialize`: custom deserializer (default: `superjson.parse`).
195
+ - `pacer`: persistence debouncer configuration (default: trailing, 100ms).
196
+
197
+ ## React Hooks
198
+
199
+ ```ts
200
+ import { useStore } from 'nusm/react'
201
+ ```
202
+
203
+ `useStore` uses React 19's `useSyncExternalStore` and supports selectors and
204
+ configurable equality checks.
205
+
206
+ ### `useStore(store, selector?, options?)`
207
+
208
+ Arguments:
209
+
210
+ - `store`: a Nusm store instance returned by `createNusmStore`.
211
+ - `selector` (optional): function that receives the full state and returns the
212
+ selected slice. Defaults to identity (returns full state).
213
+ - `options` (optional): configuration object with:
214
+ - `equal`: when `true`, uses deep equality (`fast-equals` `deepEqual`). When
215
+ `false` or omitted, uses shallow equality (`fast-equals` `shallowEqual`).
216
+
217
+ Example:
218
+
219
+ ```ts
220
+ const store = createNusmStore({ user: { name: 'Ada' } })
221
+
222
+ const name = useStore(store, (state) => state.user.name)
223
+ const user = useStore(store, (state) => state.user, { equal: true })
224
+ ```
225
+
226
+ ## Tests
227
+
228
+ ```bash
229
+ bun test
230
+ ```
231
+
232
+ ## Build
233
+
234
+ ```bash
235
+ bun run build
236
+ ```
237
+
238
+ ## License
239
+
240
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,3 @@
1
+ import type { IndexDbAdapterOptions, NusmAdapter } from "../types";
2
+ export declare const createIndexDbAdapter: (options?: IndexDbAdapterOptions) => NusmAdapter;
3
+ //# sourceMappingURL=indexDbAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexDbAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/indexDbAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AA+CnE,eAAO,MAAM,oBAAoB,GAC/B,UAAU,qBAAqB,KAC9B,WAsCF,CAAC"}
@@ -0,0 +1,53 @@
1
+ import superjson from "superjson";
2
+ const openIndexDb = (dbName, storeName, version) => {
3
+ return new Promise((resolve, reject) => {
4
+ const request = indexedDB.open(dbName, version);
5
+ request.onerror = () => reject(request.error);
6
+ request.onupgradeneeded = () => {
7
+ const db = request.result;
8
+ if (!db.objectStoreNames.contains(storeName)) {
9
+ db.createObjectStore(storeName);
10
+ }
11
+ };
12
+ request.onsuccess = () => resolve(request.result);
13
+ });
14
+ };
15
+ const withStore = async (dbName, storeName, mode, action) => {
16
+ const db = await openIndexDb(dbName, storeName, 1);
17
+ return new Promise((resolve, reject) => {
18
+ const tx = db.transaction(storeName, mode);
19
+ const store = tx.objectStore(storeName);
20
+ const request = action(store);
21
+ request.onerror = () => reject(request.error);
22
+ request.onsuccess = () => resolve(request.result);
23
+ });
24
+ };
25
+ const defaultResolveKey = (params) => {
26
+ if (params.kind === "entire") {
27
+ return `nusm:${params.storeId}:entire`;
28
+ }
29
+ return `nusm:${params.storeId}:slice:${params.sliceKey}`;
30
+ };
31
+ export const createIndexDbAdapter = (options) => {
32
+ if (typeof indexedDB === "undefined") {
33
+ throw new Error("IndexDB adapter requires a browser environment.");
34
+ }
35
+ const dbName = options?.dbName ?? "nusm";
36
+ const storeName = options?.storeName ?? "nusm";
37
+ const serialize = options?.serialize ?? ((value) => superjson.stringify(value));
38
+ const deserialize = options?.deserialize ?? ((raw) => superjson.parse(raw));
39
+ return {
40
+ clear: () => withStore(dbName, storeName, "readwrite", (store) => store.clear()).then(() => undefined),
41
+ getAllKeys: async () => {
42
+ const keys = await withStore(dbName, storeName, "readonly", (store) => store.getAllKeys());
43
+ return keys.map((key) => String(key));
44
+ },
45
+ getItem: (key) => withStore(dbName, storeName, "readonly", (store) => store.get(key)).then((raw) => (raw == null ? null : deserialize(String(raw)))),
46
+ name: "indexdb",
47
+ pacer: options?.pacer ?? { trailing: true, wait: 100 },
48
+ removeItem: (key) => withStore(dbName, storeName, "readwrite", (store) => store.delete(key)).then(() => undefined),
49
+ resolveKey: defaultResolveKey,
50
+ setItem: (key, value) => withStore(dbName, storeName, "readwrite", (store) => store.put(serialize(value), key)).then(() => undefined),
51
+ };
52
+ };
53
+ //# sourceMappingURL=indexDbAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexDbAdapter.js","sourceRoot":"","sources":["../../src/adapters/indexDbAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { NusmAdapter, StorageAdapterOptions } from "../types";
2
+ export declare const createLocalStorageAdapter: (options?: StorageAdapterOptions) => NusmAdapter;
3
+ //# sourceMappingURL=localStorageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localStorageAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/localStorageAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGnE,eAAO,MAAM,yBAAyB,GACpC,UAAU,qBAAqB,KAC9B,WAQA,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { createStorageAdapter } from "./storageAdapter";
2
+ export const createLocalStorageAdapter = (options) => createStorageAdapter("localStorage", typeof window === "undefined" ? undefined : window.localStorage, {
3
+ pacer: { trailing: true, wait: 50 },
4
+ ...options,
5
+ });
6
+ //# sourceMappingURL=localStorageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localStorageAdapter.js","sourceRoot":"","sources":["../../src/adapters/localStorageAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,OAA+B,EAClB,EAAE,CACf,oBAAoB,CAClB,cAAc,EACd,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,EAC/D;IACE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;IACnC,GAAG,OAAO;CACX,CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { NusmAdapter, StorageAdapterOptions } from "../types";
2
+ export declare const createSessionStorageAdapter: (options?: StorageAdapterOptions) => NusmAdapter;
3
+ //# sourceMappingURL=sessionStorageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStorageAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/sessionStorageAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGnE,eAAO,MAAM,2BAA2B,GACtC,UAAU,qBAAqB,KAC9B,WAQA,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { createStorageAdapter } from "./storageAdapter";
2
+ export const createSessionStorageAdapter = (options) => createStorageAdapter("sessionStorage", typeof window === "undefined" ? undefined : window.sessionStorage, {
3
+ pacer: { trailing: true, wait: 50 },
4
+ ...options,
5
+ });
6
+ //# sourceMappingURL=sessionStorageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionStorageAdapter.js","sourceRoot":"","sources":["../../src/adapters/sessionStorageAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,OAA+B,EAClB,EAAE,CACf,oBAAoB,CAClB,gBAAgB,EAChB,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,EACjE;IACE,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;IACnC,GAAG,OAAO;CACX,CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { NusmAdapter, StorageAdapterOptions, StorageLike } from "../types";
2
+ export declare const createStorageAdapter: (name: string, defaultStorage: StorageLike | undefined, options?: StorageAdapterOptions) => NusmAdapter;
3
+ //# sourceMappingURL=storageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storageAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/storageAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,WAAW,EACX,qBAAqB,EACrB,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,gBAAgB,WAAW,GAAG,SAAS,EACvC,UAAU,qBAAqB,KAC9B,WAmEF,CAAC"}
@@ -0,0 +1,62 @@
1
+ import superjson from "superjson";
2
+ export const createStorageAdapter = (name, defaultStorage, options) => {
3
+ const storage = options?.storage ?? defaultStorage;
4
+ if (!storage) {
5
+ throw new Error(`${name} adapter requires a storage implementation.`);
6
+ }
7
+ const prefix = options?.prefix ?? "nusm";
8
+ const serialize = options?.serialize ?? ((value) => superjson.stringify(value));
9
+ const deserialize = options?.deserialize ?? ((raw) => superjson.parse(raw));
10
+ const resolveKey = (params) => {
11
+ if (params.kind === "entire") {
12
+ return `${prefix}:${params.storeId}:entire`;
13
+ }
14
+ return `${prefix}:${params.storeId}:slice:${params.sliceKey}`;
15
+ };
16
+ const getAllKeys = () => {
17
+ if (typeof storage.length !== "number" || !storage.key)
18
+ return [];
19
+ const keys = [];
20
+ for (let i = 0; i < storage.length; i += 1) {
21
+ const key = storage.key(i);
22
+ if (key)
23
+ keys.push(key);
24
+ }
25
+ return keys;
26
+ };
27
+ const subscribe = (listener) => {
28
+ if (typeof window === "undefined" || !("addEventListener" in window)) {
29
+ return () => undefined;
30
+ }
31
+ const handler = (event) => {
32
+ if (!event.key)
33
+ return;
34
+ if (!event.key.startsWith(prefix))
35
+ return;
36
+ if (event.newValue === null) {
37
+ listener({ key: event.key, type: "remove" });
38
+ return;
39
+ }
40
+ listener({ key: event.key, type: "set" });
41
+ };
42
+ window.addEventListener("storage", handler);
43
+ return () => window.removeEventListener("storage", handler);
44
+ };
45
+ return {
46
+ clear: storage.clear ? () => storage.clear?.() : undefined,
47
+ getAllKeys,
48
+ getItem: (key) => {
49
+ const raw = storage.getItem(key);
50
+ return raw == null ? null : deserialize(raw);
51
+ },
52
+ name,
53
+ pacer: options?.pacer,
54
+ removeItem: (key) => storage.removeItem(key),
55
+ resolveKey,
56
+ setItem: (key, value) => {
57
+ storage.setItem(key, serialize(value));
58
+ },
59
+ subscribe,
60
+ };
61
+ };
62
+ //# sourceMappingURL=storageAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storageAdapter.js","sourceRoot":"","sources":["../../src/adapters/storageAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAC;AAQlC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAAY,EACZ,cAAuC,EACvC,OAA+B,EAClB,EAAE;IACf,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,CAAC;IACnD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,6CAA6C,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,MAAM,CAAC;IACzC,MAAM,SAAS,GACb,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5E,MAAM,UAAU,GAAG,CAAC,MAInB,EAAU,EAAE;QACX,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,SAAS,CAAC;QAC9C,CAAC;QACD,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,QAAQ,EAAE,CAAC;IAChE,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QAClE,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC3B,IAAI,GAAG;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,QAAuC,EAAE,EAAE;QAC5D,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,CAAC,CAAC,kBAAkB,IAAI,MAAM,CAAC,EAAE,CAAC;YACrE,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC;QACzB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,KAAmB,EAAE,EAAE;YACtC,IAAI,CAAC,KAAK,CAAC,GAAG;gBAAE,OAAO;YACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;gBAAE,OAAO;YAC1C,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC5B,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;YACD,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5C,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS;QAC1D,UAAU;QACV,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACf,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI;QACJ,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAC5C,UAAU;QACV,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACtB,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,SAAS;KACV,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CreateNusmStoreOptions, NusmStore } from "../types";
2
+ export declare function createNusmStore<TState>(initialState: TState, options?: CreateNusmStoreOptions<TState>): NusmStore<TState>;
3
+ //# sourceMappingURL=createNusmStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createNusmStore.d.ts","sourceRoot":"","sources":["../../src/core/createNusmStore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,sBAAsB,EAItB,SAAS,EACV,MAAM,UAAU,CAAC;AAwDlB,wBAAgB,eAAe,CAAC,MAAM,EACpC,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,sBAAsB,CAAC,MAAM,CAAC,GACvC,SAAS,CAAC,MAAM,CAAC,CAggBnB"}