@vladstudio/kstate 0.1.0 → 0.1.2

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 (37) hide show
  1. package/README.md +55 -41
  2. package/dist/adapters/local.d.ts +2 -2
  3. package/dist/adapters/local.d.ts.map +1 -1
  4. package/dist/adapters/local.js +15 -19
  5. package/dist/adapters/local.js.map +1 -1
  6. package/dist/adapters/queuedApi.d.ts.map +1 -1
  7. package/dist/adapters/queuedApi.js +22 -25
  8. package/dist/adapters/queuedApi.js.map +1 -1
  9. package/dist/core/cache.d.ts.map +1 -1
  10. package/dist/core/cache.js +7 -4
  11. package/dist/core/cache.js.map +1 -1
  12. package/dist/core/proxy.d.ts.map +1 -1
  13. package/dist/core/proxy.js +80 -109
  14. package/dist/core/proxy.js.map +1 -1
  15. package/dist/core/subscribers.d.ts.map +1 -1
  16. package/dist/core/subscribers.js +39 -27
  17. package/dist/core/subscribers.js.map +1 -1
  18. package/dist/hooks/useStore.d.ts.map +1 -1
  19. package/dist/hooks/useStore.js +14 -49
  20. package/dist/hooks/useStore.js.map +1 -1
  21. package/dist/hooks/useStoreStatus.d.ts +1 -1
  22. package/dist/hooks/useStoreStatus.d.ts.map +1 -1
  23. package/dist/hooks/useStoreStatus.js +3 -2
  24. package/dist/hooks/useStoreStatus.js.map +1 -1
  25. package/dist/stores/computed.d.ts +6 -10
  26. package/dist/stores/computed.d.ts.map +1 -1
  27. package/dist/stores/computed.js +8 -5
  28. package/dist/stores/computed.js.map +1 -1
  29. package/dist/stores/createSetStore.d.ts.map +1 -1
  30. package/dist/stores/createSetStore.js +73 -45
  31. package/dist/stores/createSetStore.js.map +1 -1
  32. package/dist/sync/api.d.ts.map +1 -1
  33. package/dist/sync/api.js +28 -69
  34. package/dist/sync/api.js.map +1 -1
  35. package/dist/types.d.ts +3 -1
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +1 -1
package/README.md CHANGED
@@ -25,9 +25,6 @@ configureKState({
25
25
  const token = localStorage.getItem('token')
26
26
  return token ? { Authorization: `Bearer ${token}` } : {}
27
27
  },
28
- onError: (error, operation, meta) => {
29
- console.error(`[KState] ${operation} failed:`, error.message)
30
- }
31
28
  })
32
29
  ```
33
30
 
@@ -35,9 +32,9 @@ configureKState({
35
32
 
36
33
  ## Stores
37
34
 
38
- ### `createSetStore` — Array of items
35
+ ### `createSetStore` — Collection of items
39
36
 
40
- For managing arrays of objects with `id`:
37
+ For managing collections of objects with unique `id`. Uses `Map<id, T>` internally for O(1) lookups:
41
38
 
42
39
  ```tsx
43
40
  import { createSetStore, api } from 'kstate'
@@ -71,14 +68,17 @@ users.dispose() // Cleanup listeners
71
68
  For managing a single object:
72
69
 
73
70
  ```tsx
74
- import { createStore, local } from 'kstate'
71
+ import { createStore, api } from 'kstate'
75
72
 
76
- interface Settings {
77
- theme: 'light' | 'dark'
78
- language: string
73
+ interface Profile {
74
+ id: string
75
+ name: string
76
+ email: string
79
77
  }
80
78
 
81
- const settings = createStore<Settings>(local('settings', { theme: 'light', language: 'en' }))
79
+ const profile = createStore<Profile>({
80
+ ...api({ list: '/profile' }),
81
+ })
82
82
  ```
83
83
 
84
84
  **Operations:**
@@ -175,9 +175,12 @@ import { sse } from 'kstate'
175
175
  const jobs = createSetStore<Job>({
176
176
  ...api({ list: '/jobs' }),
177
177
  subscribe: sse('/jobs/stream', {
178
- mode: 'upsert', // 'replace' | 'append' | 'upsert'
179
- dataKey: 'items',
180
- maxItems: 100, // For 'append' mode
178
+ mode: 'upsert', // 'replace' | 'append' | 'upsert' (default: 'replace')
179
+ eventName: 'message', // SSE event name (default: 'message')
180
+ dataKey: 'items', // Extract from response wrapper
181
+ maxItems: 100, // Limit items for 'append' mode
182
+ dedupe: (item) => item.id, // Custom deduplication key
183
+ withCredentials: true, // Send cookies (default: true)
181
184
  }),
182
185
  })
183
186
  ```
@@ -235,8 +238,13 @@ Subscribe to store data:
235
238
  import { useStore } from 'kstate'
236
239
 
237
240
  function UserList() {
238
- const items = useStore(users)
239
- return items.map(u => <div key={u.id}>{u.name}</div>)
241
+ const ids = users.ids // string[] - ordered IDs
242
+ return ids.map(id => <UserRow key={id} id={id} />)
243
+ }
244
+
245
+ function UserRow({ id }: { id: string }) {
246
+ const user = useStore(users[id]) // subscribe to specific item
247
+ return <div>{user.name}</div>
240
248
  }
241
249
  ```
242
250
 
@@ -270,13 +278,13 @@ function UserList() {
270
278
  Subscribe to specific paths — components only re-render when that exact value changes:
271
279
 
272
280
  ```tsx
273
- function UserName({ index }: { index: number }) {
274
- const name = useStore(users[index].name) // Only re-renders on name change
281
+ function UserName({ id }: { id: string }) {
282
+ const name = useStore(users[id].name) // Only re-renders on name change
275
283
  return <span>{name}</span>
276
284
  }
277
285
 
278
- function UserEmail({ index }: { index: number }) {
279
- const email = useStore(users[index].email) // Only re-renders on email change
286
+ function UserEmail({ id }: { id: string }) {
287
+ const email = useStore(users[id].email) // Only re-renders on email change
280
288
  return <span>{email}</span>
281
289
  }
282
290
  ```
@@ -284,16 +292,17 @@ function UserEmail({ index }: { index: number }) {
284
292
  **How paths work:**
285
293
 
286
294
  ```tsx
287
- useStore(users) // Path: [] - All changes
288
- useStore(users[0]) // Path: [0] - First item changes
289
- useStore(users[0].name) // Path: [0, 'name'] - First item's name only
295
+ useStore(users) // Path: [] - All changes
296
+ useStore(users['abc']) // Path: ['abc'] - Item 'abc' changes
297
+ useStore(users['abc'].name) // Path: ['abc', 'name'] - Item's name only
290
298
  ```
291
299
 
292
- When `users.patch({ id: '1', name: 'New' })` is called:
300
+ When `users.patch({ id: 'abc', name: 'New' })` is called:
293
301
  - `useStore(users)` — re-renders (ancestor)
294
- - `useStore(users[0])` — re-renders (ancestor)
295
- - `useStore(users[0].name)` — re-renders (exact match)
296
- - `useStore(users[0].email)` — **does NOT** re-render (sibling)
302
+ - `useStore(users['abc'])` — re-renders (ancestor)
303
+ - `useStore(users['abc'].name)` — re-renders (exact match)
304
+ - `useStore(users['abc'].email)` — **does NOT** re-render (sibling)
305
+ - `useStore(users['xyz'])` — **does NOT** re-render (different ID)
297
306
 
298
307
  ---
299
308
 
@@ -385,7 +394,7 @@ import { useStore, useStoreStatus } from 'kstate'
385
394
  import { users, activeUsers } from '../stores/users'
386
395
 
387
396
  export function UserList() {
388
- const items = useStore(activeUsers)
397
+ const active = useStore(activeUsers) // computed returns array
389
398
  const { isLoading, error } = useStoreStatus(users)
390
399
 
391
400
  useEffect(() => { users.get() }, [])
@@ -395,15 +404,20 @@ export function UserList() {
395
404
 
396
405
  return (
397
406
  <ul>
398
- {items.map(user => (
399
- <li key={user.id}>
400
- {user.name}
401
- <button onClick={() => users.delete({ id: user.id })}>Delete</button>
402
- </li>
403
- ))}
407
+ {active.map(u => <UserRow key={u.id} id={u.id} />)}
404
408
  </ul>
405
409
  )
406
410
  }
411
+
412
+ function UserRow({ id }: { id: string }) {
413
+ const name = useStore(users[id].name) // fine-grained subscription
414
+ return (
415
+ <li>
416
+ {name}
417
+ <button onClick={() => users.delete({ id })}>Delete</button>
418
+ </li>
419
+ )
420
+ }
407
421
  ```
408
422
 
409
423
  ### Shopping Cart (localStorage)
@@ -436,7 +450,7 @@ function CartSummary() {
436
450
 
437
451
  function AddToCart({ product }: { product: Product }) {
438
452
  const handleAdd = () => {
439
- const existing = cart.value.find(i => i.productId === product.id)
453
+ const existing = [...cart.value.values()].find(i => i.productId === product.id)
440
454
  if (existing) {
441
455
  cart.patch({ id: existing.id, quantity: existing.quantity + 1 })
442
456
  } else {
@@ -475,14 +489,14 @@ export const jobs = createSetStore<Job>({
475
489
  ```tsx
476
490
  // components/Jobs.tsx
477
491
  function JobList() {
478
- const items = useStore(jobs)
479
-
480
492
  useEffect(() => { jobs.get() }, [])
481
493
 
482
- return items.map(job => (
483
- <div key={job.id}>
484
- {job.status}: {job.url}
485
- </div>
486
- ))
494
+ return jobs.ids.map(id => <JobRow key={id} id={id} />)
495
+ }
496
+
497
+ function JobRow({ id }: { id: string }) {
498
+ const status = useStore(jobs[id].status)
499
+ const url = useStore(jobs[id].url)
500
+ return <div>{status}: {url}</div>
487
501
  }
488
502
  ```
@@ -11,10 +11,10 @@ export declare function local<T extends {
11
11
  }) => T;
12
12
  delete: (params: {
13
13
  id: string;
14
- }) => void;
14
+ }) => void | undefined;
15
15
  persist: {
16
16
  load: () => T[];
17
- save: (data: T[]) => void;
17
+ save: (data: T[]) => void | undefined;
18
18
  };
19
19
  };
20
20
  //# sourceMappingURL=local.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/adapters/local.ts"],"names":[],"mappings":"AAEA,wBAAgB,KAAK,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE;;qBAkB1D;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;mBAChB,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;kBAOlB,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;qBAOxB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;;oBAhChB,CAAC,EAAE;qBAUA,CAAC,EAAE;;EA2BxB"}
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/adapters/local.ts"],"names":[],"mappings":"AAEA,wBAAgB,KAAK,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE;;qBAU1D;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;mBAKhB,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;kBAOlB,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;qBAQxB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;;oBAzBhB,CAAC,EAAE;qBACA,CAAC,EAAE;;EA2BxB"}
@@ -1,28 +1,26 @@
1
- const getStorage = () => typeof localStorage !== 'undefined' ? localStorage : globalThis.localStorage;
1
+ const getStorage = () => typeof localStorage !== 'undefined' ? localStorage : null;
2
2
  export function local(key, defaultValue) {
3
- const load = () => {
3
+ const parse = (raw) => {
4
+ if (!raw)
5
+ return defaultValue ?? [];
4
6
  try {
5
- const storage = getStorage();
6
- if (!storage)
7
- return defaultValue ?? [];
8
- const raw = storage.getItem(key);
9
- if (!raw)
10
- return defaultValue ?? [];
11
- const parsed = JSON.parse(raw);
12
- return Array.isArray(parsed) ? parsed : (defaultValue ?? []);
7
+ const p = JSON.parse(raw);
8
+ return Array.isArray(p) ? p : (defaultValue ?? []);
13
9
  }
14
10
  catch {
15
11
  return defaultValue ?? [];
16
12
  }
17
13
  };
18
- const save = (data) => {
19
- const storage = getStorage();
20
- if (storage)
21
- storage.setItem(key, JSON.stringify(data));
22
- };
14
+ const load = () => parse(getStorage()?.getItem(key) ?? null);
15
+ const save = (data) => getStorage()?.setItem(key, JSON.stringify(data));
23
16
  return {
24
17
  get: () => load(),
25
- getOne: (params) => load().find(i => i.id === params.id) ?? (() => { throw new Error(`Item ${params.id} not found`); })(),
18
+ getOne: (params) => {
19
+ const item = load().find(i => i.id === params.id);
20
+ if (!item)
21
+ throw new Error(`Item ${params.id} not found`);
22
+ return item;
23
+ },
26
24
  create: (data) => {
27
25
  const items = load();
28
26
  const item = { ...data, id: data.id ?? crypto.randomUUID() };
@@ -39,9 +37,7 @@ export function local(key, defaultValue) {
39
37
  save(items);
40
38
  return items[idx];
41
39
  },
42
- delete: (params) => {
43
- save(load().filter(i => i.id !== params.id));
44
- },
40
+ delete: (params) => save(load().filter(i => i.id !== params.id)),
45
41
  persist: { load, save },
46
42
  };
47
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/adapters/local.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../src/adapters/local.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,OAAO,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA;AAElF,MAAM,UAAU,KAAK,CAA2B,GAAW,EAAE,YAAkB;IAC7E,MAAM,KAAK,GAAG,CAAC,GAAkB,EAAO,EAAE;QACxC,IAAI,CAAC,GAAG;YAAE,OAAO,YAAY,IAAI,EAAE,CAAA;QACnC,IAAI,CAAC;YAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAAC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,YAAY,IAAI,EAAE,CAAA;QAAC,CAAC;IAC3H,CAAC,CAAA;IACD,MAAM,IAAI,GAAG,GAAQ,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,CAAA;IACjE,MAAM,IAAI,GAAG,CAAC,IAAS,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IAE5E,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE;QACjB,MAAM,EAAE,CAAC,MAAsB,EAAE,EAAE;YACjC,MAAM,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAA;YACjD,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,MAAM,CAAC,EAAE,YAAY,CAAC,CAAA;YACzD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,EAAE,CAAC,IAAuB,EAAE,EAAE;YAClC,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;YACpB,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,EAAE,EAAG,IAAU,CAAC,EAAE,IAAI,MAAM,CAAC,UAAU,EAAE,EAAO,CAAA;YACxE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAChB,IAAI,CAAC,KAAK,CAAC,CAAA;YACX,OAAO,IAAI,CAAA;QACb,CAAC;QACD,KAAK,EAAE,CAAC,IAAiC,EAAE,EAAE;YAC3C,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;YACpB,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAA;YAClD,IAAI,GAAG,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,EAAE,YAAY,CAAC,CAAA;YACzD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,EAAE,CAAA;YACvC,IAAI,CAAC,KAAK,CAAC,CAAA;YACX,OAAO,KAAK,CAAC,GAAG,CAAC,CAAA;QACnB,CAAC;QACD,MAAM,EAAE,CAAC,MAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;QAChF,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;KACxB,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"queuedApi.d.ts","sourceRoot":"","sources":["../../src/adapters/queuedApi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AA0BhD,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,gBAAgB;mBAGzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBACrB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;mBAC1C,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;gBACpB,CAAC;kBACC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;qBACxB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;EAElC"}
1
+ {"version":3,"file":"queuedApi.d.ts","sourceRoot":"","sources":["../../src/adapters/queuedApi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAiBhD,wBAAgB,SAAS,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,gBAAgB;mBAGzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;qBACrB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;mBAC1C,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;gBACpB,CAAC;kBACC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;qBACxB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE;EAElC"}
@@ -1,34 +1,31 @@
1
1
  import { api } from './api';
2
- const queue = [];
3
- let running = false;
4
- async function processQueue() {
5
- if (running)
6
- return;
7
- running = true;
8
- while (queue.length > 0) {
9
- const task = queue.shift();
10
- try {
11
- await task();
12
- }
13
- catch { /* continue on error */ }
14
- }
15
- running = false;
16
- }
17
- function enqueue(task) {
18
- return new Promise((resolve, reject) => {
19
- queue.push(async () => {
2
+ function createQueue() {
3
+ const queue = [];
4
+ let running = false;
5
+ async function process() {
6
+ if (running)
7
+ return;
8
+ running = true;
9
+ while (queue.length > 0) {
20
10
  try {
21
- resolve(await task());
22
- }
23
- catch (e) {
24
- reject(e);
11
+ await queue.shift()();
25
12
  }
26
- });
27
- processQueue();
13
+ catch { /* continue */ }
14
+ }
15
+ running = false;
16
+ }
17
+ return (task) => new Promise((resolve, reject) => {
18
+ queue.push(async () => { try {
19
+ resolve(await task());
20
+ }
21
+ catch (e) {
22
+ reject(e);
23
+ } });
24
+ process();
28
25
  });
29
26
  }
30
27
  export function queuedApi(config) {
31
- const base = api(config);
28
+ const base = api(config), enqueue = createQueue();
32
29
  return {
33
30
  get: (params) => enqueue(() => base.get(params)),
34
31
  getOne: (params) => enqueue(() => base.getOne(params)),
@@ -1 +1 @@
1
- {"version":3,"file":"queuedApi.js","sourceRoot":"","sources":["../../src/adapters/queuedApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAK3B,MAAM,KAAK,GAAiB,EAAE,CAAA;AAC9B,IAAI,OAAO,GAAG,KAAK,CAAA;AAEnB,KAAK,UAAU,YAAY;IACzB,IAAI,OAAO;QAAE,OAAM;IACnB,OAAO,GAAG,IAAI,CAAA;IACd,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAG,CAAA;QAC3B,IAAI,CAAC;YAAC,MAAM,IAAI,EAAE,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,GAAG,KAAK,CAAA;AACjB,CAAC;AAED,SAAS,OAAO,CAAI,IAAsB;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YACpB,IAAI,CAAC;gBAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;YAAC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YAAC,CAAC;QACvD,CAAC,CAAC,CAAA;QACF,YAAY,EAAE,CAAA;IAChB,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAA2B,MAAwB;IAC1E,MAAM,IAAI,GAAG,GAAG,CAAI,MAAM,CAAC,CAAA;IAC3B,OAAO;QACL,GAAG,EAAE,CAAC,MAAgC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,EAAE,CAAC,MAAgD,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChG,MAAM,EAAE,CAAC,IAAuB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrE,GAAG,EAAE,CAAC,IAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/C,KAAK,EAAE,CAAC,IAAiC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,EAAE,CAAC,MAAsB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACvE,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"queuedApi.js","sourceRoot":"","sources":["../../src/adapters/queuedApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAG3B,SAAS,WAAW;IAClB,MAAM,KAAK,GAA+B,EAAE,CAAA;IAC5C,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,KAAK,UAAU,OAAO;QACpB,IAAI,OAAO;YAAE,OAAM;QACnB,OAAO,GAAG,IAAI,CAAA;QACd,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,MAAM,KAAK,CAAC,KAAK,EAAG,EAAE,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;QAAC,CAAC;QACpF,OAAO,GAAG,KAAK,CAAA;IACjB,CAAC;IACD,OAAO,CAAI,IAAsB,EAAc,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAChF,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC;YAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;QAAC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QACjF,OAAO,EAAE,CAAA;IACX,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAA2B,MAAwB;IAC1E,MAAM,IAAI,GAAG,GAAG,CAAI,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,CAAA;IACpD,OAAO;QACL,GAAG,EAAE,CAAC,MAAgC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,EAAE,CAAC,MAAgD,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChG,MAAM,EAAE,CAAC,IAAuB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrE,GAAG,EAAE,CAAC,IAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/C,KAAK,EAAE,CAAC,IAAiC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,EAAE,CAAC,MAAsB,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;KACvE,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAMzF;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAGtD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAOzF;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAItD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAsB;AAEnE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGrD"}
@@ -5,18 +5,21 @@ export function getCached(key, ttl) {
5
5
  if (!entry)
6
6
  return null;
7
7
  const age = Date.now() - entry.timestamp;
8
- if (age >= ttl)
8
+ if (age >= ttl) {
9
+ cache.delete(key);
9
10
  return null;
11
+ }
12
+ cache.delete(key);
13
+ cache.set(key, entry); // Move to end (LRU)
10
14
  return { data: entry.data, stale: age > ttl / 2 };
11
15
  }
12
16
  export function setCache(key, data) {
17
+ cache.delete(key); // Remove if exists to update position
13
18
  if (cache.size >= MAX_SIZE)
14
19
  cache.delete(cache.keys().next().value);
15
20
  cache.set(key, { data, timestamp: Date.now() });
16
21
  }
17
- export function clearCache(key) {
18
- cache.delete(key);
19
- }
22
+ export function clearCache(key) { cache.delete(key); }
20
23
  export function clearCachePrefix(prefix) {
21
24
  if (!prefix)
22
25
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AACA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAA;AACpD,MAAM,QAAQ,GAAG,GAAG,CAAA;AAEpB,MAAM,UAAU,SAAS,CAAI,GAAW,EAAE,GAAW;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAA;IACxC,IAAI,GAAG,IAAI,GAAG;QAAE,OAAO,IAAI,CAAA;IAC3B,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAS,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,GAAW,EAAE,IAAO;IAC9C,IAAI,KAAK,CAAC,IAAI,IAAI,QAAQ;QAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAA;IACpE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,IAAI,CAAC,MAAM;QAAE,OAAM;IACnB,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE;QAAE,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AAC/E,CAAC"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AACA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAA;AACpD,MAAM,QAAQ,GAAG,GAAG,CAAA;AAEpB,MAAM,UAAU,SAAS,CAAI,GAAW,EAAE,GAAW;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAA;IACxC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAAC,OAAO,IAAI,CAAA;IAAC,CAAC;IAClD,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA,CAAC,oBAAoB;IAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAS,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC,EAAE,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,GAAW,EAAE,IAAO;IAC9C,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAC,sCAAsC;IACxD,IAAI,KAAK,CAAC,IAAI,IAAI,QAAQ;QAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAA;IACpE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW,IAAU,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAC,CAAC;AAEnE,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,IAAI,CAAC,MAAM;QAAE,OAAM;IACnB,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE;QAAE,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AAC/E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/core/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAgB,MAAM,UAAU,CAAA;AA+H/E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,OAAO,CAAA;IACvB,WAAW,EAAE,iBAAiB,CAAA;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,GAAG,CAAC,CAM9D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGjD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,KAAK,MAAM,IAAI,CAAC,GAAG,IAAI,CAGzG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,IAAI,CAGtE"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/core/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAgB,MAAM,UAAU,CAAA;AAiG/E,MAAM,WAAW,cAAc;IAAG,QAAQ,EAAE,MAAM,OAAO,CAAC;IAAC,WAAW,EAAE,iBAAiB,CAAA;CAAE;AAE3F,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,GAAG,CAAC,CAE9D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAErD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAEjD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,KAAK,MAAM,IAAI,CAAC,GAAG,IAAI,CAGzG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,IAAI,CAGtE"}
@@ -1,146 +1,117 @@
1
1
  import { KSTATE_PROXY, KSTATE_PATH, KSTATE_SUBSCRIBE, KSTATE_GET_DATA } from '../types';
2
- // Store method names that should be retrieved from target, not data
3
- const STORE_METHODS = new Set([
4
- 'get', 'set', 'patch', 'update', 'delete', 'clear', 'dispose',
5
- 'add', 'create', 'getOne', 'subscribeToStatus', 'status', 'meta'
6
- ]);
7
- // Create a proxy wrapper for primitive values that supports subscription
8
- function createPrimitiveProxy(context) {
9
- const wrapper = {
10
- [KSTATE_PROXY]: true,
11
- [KSTATE_PATH]: context.path,
12
- [KSTATE_SUBSCRIBE]: context.subscribe,
13
- [KSTATE_GET_DATA]: context.getData,
14
- valueOf() { return context.getData(); },
15
- toString() { return String(context.getData()); },
2
+ const STORE_METHODS = new Set(['get', 'set', 'patch', 'update', 'delete', 'clear', 'dispose', 'add', 'create', 'getOne', 'subscribeToStatus', 'status', 'meta', 'ids']);
3
+ const ARRAY_METHODS = new Set(['map', 'filter', 'find', 'findIndex', 'some', 'every', 'forEach', 'reduce', 'indexOf', 'includes']);
4
+ const isNumeric = (s) => s.length > 0 && s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57 && Number(s) == s;
5
+ function createPrimitiveProxy(ctx) {
6
+ return {
7
+ [KSTATE_PROXY]: true, [KSTATE_PATH]: ctx.path, [KSTATE_SUBSCRIBE]: ctx.subscribe, [KSTATE_GET_DATA]: ctx.getData,
8
+ valueOf() { return ctx.getData(); },
9
+ toString() { return String(ctx.getData()); },
16
10
  [Symbol.toPrimitive](hint) {
17
- const value = context.getData();
18
- if (hint === 'number')
19
- return Number(value);
20
- if (hint === 'string')
21
- return String(value);
22
- return value;
11
+ const v = ctx.getData();
12
+ return hint === 'number' ? Number(v) : hint === 'string' ? String(v) : v;
23
13
  },
24
14
  };
25
- return wrapper;
26
15
  }
27
- function createReactiveProxy(context) {
16
+ function createNestedProxy(ctx, prop, getter, value) {
17
+ const path = ctx.path.length === 0 ? [prop] : ctx.path.concat(prop);
18
+ const newCtx = { getData: getter, subscribe: ctx.subscribe, path };
19
+ return (value === null || typeof value !== 'object') ? createPrimitiveProxy(newCtx) : createReactiveProxy(newCtx);
20
+ }
21
+ function* iterateArray(ctx, data) {
22
+ for (let i = 0; i < data.length; i++) {
23
+ const item = data[i];
24
+ if (item === null || typeof item !== 'object') {
25
+ yield item;
26
+ continue;
27
+ }
28
+ const path = ctx.path.length === 0 ? [i] : ctx.path.concat(i);
29
+ yield createReactiveProxy({ getData: () => ctx.getData()?.[i], subscribe: ctx.subscribe, path });
30
+ }
31
+ }
32
+ function* iterateMap(ctx, data) {
33
+ for (const [key, item] of data) {
34
+ if (item === null || typeof item !== 'object') {
35
+ yield [key, item];
36
+ continue;
37
+ }
38
+ const path = ctx.path.length === 0 ? [key] : ctx.path.concat(key);
39
+ yield [key, createReactiveProxy({ getData: () => ctx.getData()?.get(key), subscribe: ctx.subscribe, path })];
40
+ }
41
+ }
42
+ function createReactiveProxy(ctx) {
28
43
  const handler = {
29
44
  get(target, prop) {
30
- // Handle special symbol properties
31
45
  if (prop === KSTATE_PROXY)
32
46
  return true;
33
47
  if (prop === KSTATE_PATH)
34
- return context.path;
48
+ return ctx.path;
35
49
  if (prop === KSTATE_SUBSCRIBE)
36
- return context.subscribe;
50
+ return ctx.subscribe;
37
51
  if (prop === KSTATE_GET_DATA)
38
- return context.getData;
39
- // Handle 'value' property - returns the entire data
40
- if (prop === 'value') {
41
- return context.getData();
42
- }
43
- // Check for store methods on target (not array built-ins)
52
+ return ctx.getData;
53
+ if (prop === 'value')
54
+ return ctx.getData();
44
55
  if (typeof prop === 'string' && STORE_METHODS.has(prop)) {
45
- const targetValue = target[prop];
46
- if (targetValue !== undefined) {
47
- return targetValue;
48
- }
56
+ const v = target[prop];
57
+ if (v !== undefined)
58
+ return v;
49
59
  }
50
- const data = context.getData();
51
- if (data === null || data === undefined) {
52
- return undefined;
60
+ const data = ctx.getData();
61
+ if (data == null) {
62
+ const path = ctx.path.length === 0 ? [prop] : ctx.path.concat(prop);
63
+ return createReactiveProxy({
64
+ getData: () => { const d = ctx.getData(); return d == null ? undefined : d[prop]; },
65
+ subscribe: ctx.subscribe, path,
66
+ });
53
67
  }
54
- // Handle array length property
55
- if (prop === 'length' && Array.isArray(data)) {
68
+ if (prop === 'length' && Array.isArray(data))
56
69
  return data.length;
70
+ if (prop === 'size' && data instanceof Map)
71
+ return data.size;
72
+ if (prop === Symbol.iterator) {
73
+ if (Array.isArray(data))
74
+ return function* () { yield* iterateArray(ctx, data); };
75
+ if (data instanceof Map)
76
+ return function* () { yield* iterateMap(ctx, data); };
57
77
  }
58
- // Handle Symbol.iterator for arrays
59
- if (prop === Symbol.iterator && Array.isArray(data)) {
60
- return function* () {
61
- for (let i = 0; i < data.length; i++) {
62
- const item = data[i];
63
- // For primitive values, yield directly
64
- if (item === null || typeof item !== 'object') {
65
- yield item;
66
- }
67
- else {
68
- // For objects, yield a proxy
69
- const newPath = [...context.path, i];
70
- yield createReactiveProxy({
71
- getData: () => {
72
- const d = context.getData();
73
- return Array.isArray(d) ? d[i] : undefined;
74
- },
75
- subscribe: context.subscribe,
76
- path: newPath,
77
- });
78
- }
79
- }
80
- };
78
+ if (Array.isArray(data) && typeof prop === 'string' && ARRAY_METHODS.has(prop)) {
79
+ const m = data[prop];
80
+ if (typeof m === 'function')
81
+ return m.bind(data);
81
82
  }
82
- // Handle array methods
83
- if (Array.isArray(data) && typeof prop === 'string') {
84
- const arrayMethods = ['map', 'filter', 'find', 'findIndex', 'some', 'every', 'forEach', 'reduce', 'indexOf', 'includes'];
85
- if (arrayMethods.includes(prop)) {
86
- const method = data[prop];
87
- if (typeof method === 'function') {
88
- return method.bind(data);
89
- }
90
- }
83
+ if (data instanceof Map && typeof prop === 'string') {
84
+ const value = data.get(prop);
85
+ return createNestedProxy(ctx, prop, () => ctx.getData()?.get(prop), value);
91
86
  }
87
+ const pathKey = typeof prop === 'string' && isNumeric(prop) ? Number(prop) : prop;
92
88
  const value = data[prop];
93
- const pathKey = typeof prop === 'string' && /^\d+$/.test(prop) ? Number(prop) : prop;
94
- const newPath = [...context.path, pathKey];
95
- const newGetData = () => {
96
- const d = context.getData();
97
- if (d === null || d === undefined)
98
- return undefined;
99
- return d[prop];
100
- };
101
- // For primitive values, return a subscribable primitive wrapper
102
- if (value === null || typeof value !== 'object') {
103
- return createPrimitiveProxy({
104
- getData: newGetData,
105
- subscribe: context.subscribe,
106
- path: newPath,
107
- });
108
- }
109
- // For objects/arrays, return nested proxy
110
- return createReactiveProxy({
111
- getData: newGetData,
112
- subscribe: context.subscribe,
113
- path: newPath,
114
- });
89
+ return createNestedProxy(ctx, pathKey, () => {
90
+ const d = ctx.getData();
91
+ return d == null ? undefined : d[prop];
92
+ }, value);
115
93
  },
116
94
  };
117
- const data = context.getData();
118
- const target = (Array.isArray(data) ? [] : {});
119
- return new Proxy(target, handler);
95
+ const data = ctx.getData();
96
+ return new Proxy((Array.isArray(data) ? [] : data instanceof Map ? new Map() : {}), handler);
120
97
  }
121
98
  export function wrapStoreWithProxy(store) {
122
- return createReactiveProxy({
123
- getData: store.getValue,
124
- subscribe: (path, listener) => store.subscribers.subscribe(path, listener),
125
- path: [],
126
- });
99
+ return createReactiveProxy({ getData: store.getValue, subscribe: (path, listener) => store.subscribers.subscribe(path, listener), path: [] });
127
100
  }
128
101
  export function isKStateProxy(value) {
129
102
  return typeof value === 'object' && value !== null && value[KSTATE_PROXY] === true;
130
103
  }
131
104
  export function getProxyPath(proxy) {
132
- if (!isKStateProxy(proxy))
133
- return [];
134
- return proxy[KSTATE_PATH];
105
+ return proxy[KSTATE_PATH] ?? [];
135
106
  }
136
107
  export function getProxySubscribe(proxy) {
137
- if (!isKStateProxy(proxy))
108
+ if (proxy == null)
138
109
  return null;
139
- return proxy[KSTATE_SUBSCRIBE];
110
+ return proxy[KSTATE_SUBSCRIBE] ?? null;
140
111
  }
141
112
  export function getProxyGetData(proxy) {
142
- if (!isKStateProxy(proxy))
113
+ if (proxy == null)
143
114
  return null;
144
- return proxy[KSTATE_GET_DATA];
115
+ return proxy[KSTATE_GET_DATA] ?? null;
145
116
  }
146
117
  //# sourceMappingURL=proxy.js.map