@plures/unum 0.2.2 → 0.3.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 (58) hide show
  1. package/README.md +3 -6
  2. package/dist/adapters/index.d.ts +3 -0
  3. package/dist/adapters/index.d.ts.map +1 -0
  4. package/dist/adapters/index.js +3 -0
  5. package/dist/adapters/index.js.map +1 -0
  6. package/dist/adapters/memory.d.ts +7 -0
  7. package/dist/adapters/memory.d.ts.map +1 -0
  8. package/dist/adapters/memory.js +116 -0
  9. package/dist/adapters/memory.js.map +1 -0
  10. package/dist/adapters/pluresdb.d.ts +14 -0
  11. package/dist/adapters/pluresdb.d.ts.map +1 -0
  12. package/dist/adapters/pluresdb.js +48 -0
  13. package/dist/adapters/pluresdb.js.map +1 -0
  14. package/dist/context.d.ts +29 -0
  15. package/dist/context.d.ts.map +1 -0
  16. package/dist/context.js +43 -0
  17. package/dist/context.js.map +1 -0
  18. package/dist/index.d.ts +8 -53
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +9 -196
  21. package/dist/index.js.map +1 -1
  22. package/dist/runes.d.ts +17 -161
  23. package/dist/runes.d.ts.map +1 -1
  24. package/dist/runes.js +121 -290
  25. package/dist/runes.js.map +1 -1
  26. package/dist/store.d.ts +10 -21
  27. package/dist/store.d.ts.map +1 -1
  28. package/dist/store.js +31 -135
  29. package/dist/store.js.map +1 -1
  30. package/dist/types.d.ts +69 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +7 -0
  33. package/dist/types.js.map +1 -0
  34. package/package.json +54 -49
  35. package/dist/GunContext.d.ts +0 -17
  36. package/dist/GunContext.d.ts.map +0 -1
  37. package/dist/GunContext.js +0 -180
  38. package/dist/GunContext.js.map +0 -1
  39. package/dist/actions.d.ts +0 -39
  40. package/dist/actions.d.ts.map +0 -1
  41. package/dist/actions.js +0 -89
  42. package/dist/actions.js.map +0 -1
  43. package/dist/gunComponent.d.ts +0 -44
  44. package/dist/gunComponent.d.ts.map +0 -1
  45. package/dist/gunComponent.js +0 -205
  46. package/dist/gunComponent.js.map +0 -1
  47. package/dist/gunify.d.ts +0 -46
  48. package/dist/gunify.d.ts.map +0 -1
  49. package/dist/gunify.js +0 -294
  50. package/dist/gunify.js.map +0 -1
  51. package/dist/plures-helper.d.ts +0 -41
  52. package/dist/plures-helper.d.ts.map +0 -1
  53. package/dist/plures-helper.js +0 -114
  54. package/dist/plures-helper.js.map +0 -1
  55. package/dist/universalGunBind.d.ts +0 -219
  56. package/dist/universalGunBind.d.ts.map +0 -1
  57. package/dist/universalGunBind.js +0 -394
  58. package/dist/universalGunBind.js.map +0 -1
package/dist/runes.d.ts CHANGED
@@ -1,184 +1,40 @@
1
1
  /**
2
- * Creates a reactive connection to a PluresDB path
3
- * This is the primary API for Svelte 5 components to use PluresDB data
2
+ * pluresData() reactive data bindings for Svelte.
4
3
  *
5
- * @example
6
- * ```svelte
7
- * <script>
8
- * import { pluresData } from 'unum';
9
- *
10
- * // Create a reactive connection to PluresDB data
11
- * const todos = pluresData('todos');
12
- *
13
- * // Access a specific todo by ID
14
- * const todo = pluresData('todos', 'specific-id');
15
- *
16
- * // Create a new todo
17
- * function addTodo(text) {
18
- * todos.add({ text, completed: false });
19
- * }
20
- *
21
- * // Toggle a todo's completed status
22
- * function toggleTodo(id) {
23
- * todo.update(id, current => ({ ...current, completed: !current.completed }));
24
- * }
25
- *
26
- * // Delete a todo
27
- * function deleteTodo(id) {
28
- * todos.remove(id);
29
- * }
30
- * </script>
31
- *
32
- * <!-- Use the data directly in the template -->
33
- * <ul>
34
- * {#each todos.list() as item}
35
- * <li>{item.text}</li>
36
- * {/each}
37
- * </ul>
38
- * ```
4
+ * Works with Svelte 4 (stores) and Svelte 5 (subscribe protocol).
5
+ * No polling. Pure subscription-based reactivity.
39
6
  */
40
- export function pluresData(path: any, id?: any): {
41
- readonly state: {};
42
- readonly value: {};
43
- list: () => any[];
44
- add: (data: any) => void;
45
- update: (itemId: any, updater: any) => void;
46
- remove: (itemId?: any) => void;
47
- subscribe: (callback: any) => () => void;
48
- destroy: () => void;
49
- };
7
+ import type { DataRef } from './types.js';
50
8
  /**
51
- * Creates a derived state from PluresDB data - allows transforming/filtering PluresDB data
9
+ * Create a reactive binding to a PluresDB path.
52
10
  *
53
- * @example
54
- * ```svelte
55
- * <script>
56
- * import { pluresData, pluresDerived } from 'unum';
57
- *
58
- * const todos = pluresData('todos');
59
- * const completedTodos = pluresDerived(todos, items => items.filter(item => item.completed));
60
- * </script>
61
- *
62
- * <h2>Completed Todos</h2>
63
- * <ul>
64
- * {#each completedTodos.value as item}
65
- * <li>{item.text}</li>
66
- * {/each}
67
- * </ul>
68
- * ```
69
- */
70
- export function pluresDerived(pluresData: any, transformer: any): {
71
- readonly value: any[];
72
- destroy(): void;
73
- };
74
- /**
75
- * Creates a two-way binding between a form input and PluresDB data
11
+ * @param path - Collection/document path (e.g. 'todos', 'users/profile')
12
+ * @param id - Optional item ID for single-document binding
76
13
  *
77
14
  * @example
78
15
  * ```svelte
79
16
  * <script>
80
- * import { pluresBind } from 'unum';
81
- *
82
- * const userProfile = pluresData('userProfile');
83
- * const nameBinding = pluresBind(userProfile, 'name');
84
- * </script>
85
- *
86
- * <input type="text" bind:value={nameBinding.value} />
87
- * ```
88
- */
89
- export function pluresBind(pluresData: any, field: any): {
90
- value: any;
91
- destroy(): void;
92
- };
93
- /**
94
- * Creates a reactive connection to a PluresDB path
95
- * This is the primary API for Svelte 5 components to use PluresDB data
96
- *
97
- * @example
98
- * ```svelte
99
- * <script>
100
- * import { pluresData } from 'unum';
101
- *
102
- * // Create a reactive connection to PluresDB data
17
+ * import { pluresData } from '@plures/unum';
103
18
  * const todos = pluresData('todos');
104
- *
105
- * // Access a specific todo by ID
106
- * const todo = pluresData('todos', 'specific-id');
107
- *
108
- * // Create a new todo
109
- * function addTodo(text) {
110
- * todos.add({ text, completed: false });
111
- * }
112
- *
113
- * // Toggle a todo's completed status
114
- * function toggleTodo(id) {
115
- * todo.update(id, current => ({ ...current, completed: !current.completed }));
116
- * }
117
- *
118
- * // Delete a todo
119
- * function deleteTodo(id) {
120
- * todos.remove(id);
121
- * }
122
19
  * </script>
123
20
  *
124
- * <!-- Use the data directly in the template -->
125
- * <ul>
126
- * {#each todos.list() as item}
127
- * <li>{item.text}</li>
128
- * {/each}
129
- * </ul>
21
+ * {#each todos.list() as todo}
22
+ * <p>{todo.text}</p>
23
+ * {/each}
130
24
  * ```
131
25
  */
132
- export function gunData(path: any, id?: any): {
133
- readonly state: {};
134
- readonly value: {};
135
- list: () => any[];
136
- add: (data: any) => void;
137
- update: (itemId: any, updater: any) => void;
138
- remove: (itemId?: any) => void;
139
- subscribe: (callback: any) => () => void;
140
- destroy: () => void;
141
- };
26
+ export declare function pluresData<T extends Record<string, any> = Record<string, any>>(path: string, id?: string | null): DataRef<T>;
142
27
  /**
143
- * Creates a derived state from PluresDB data - allows transforming/filtering PluresDB data
144
- *
145
- * @example
146
- * ```svelte
147
- * <script>
148
- * import { pluresData, pluresDerived } from 'unum';
149
- *
150
- * const todos = pluresData('todos');
151
- * const completedTodos = pluresDerived(todos, items => items.filter(item => item.completed));
152
- * </script>
153
- *
154
- * <h2>Completed Todos</h2>
155
- * <ul>
156
- * {#each completedTodos.value as item}
157
- * <li>{item.text}</li>
158
- * {/each}
159
- * </ul>
160
- * ```
28
+ * Derived view subscription-based, no polling.
161
29
  */
162
- export function gunDerived(pluresData: any, transformer: any): {
163
- readonly value: any[];
30
+ export declare function pluresDerived<T = any>(source: DataRef, transform: (items: any[]) => T[]): {
31
+ readonly value: T[];
164
32
  destroy(): void;
165
33
  };
166
34
  /**
167
- * Creates a two-way binding between a form input and PluresDB data
168
- *
169
- * @example
170
- * ```svelte
171
- * <script>
172
- * import { pluresBind } from 'unum';
173
- *
174
- * const userProfile = pluresData('userProfile');
175
- * const nameBinding = pluresBind(userProfile, 'name');
176
- * </script>
177
- *
178
- * <input type="text" bind:value={nameBinding.value} />
179
- * ```
35
+ * Two-way binding helper for form inputs.
180
36
  */
181
- export function gunBind(pluresData: any, field: any): {
37
+ export declare function pluresBind(source: DataRef, field: string): {
182
38
  value: any;
183
39
  destroy(): void;
184
40
  };
@@ -1 +1 @@
1
- {"version":3,"file":"runes.d.ts","sourceRoot":"","sources":["../src/runes.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH;;;;;;;;;EA+MC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;EAiCC;AAED;;;;;;;;;;;;;;GAcG;AACH;;;EA4BC;AA1VD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH;;;;;;;;;EA+MC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;EAiCC;AAED;;;;;;;;;;;;;;GAcG;AACH;;;EA4BC"}
1
+ {"version":3,"file":"runes.d.ts","sourceRoot":"","sources":["../src/runes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,YAAY,CAAC;AAErE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5E,IAAI,EAAE,MAAM,EACZ,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC,CAAC,CAAC,CAqGZ;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,GAAG,EACnC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,GAC/B;IAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAAE,CAS1C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM;WAOxC,GAAG;;EAMnB"}
package/dist/runes.js CHANGED
@@ -1,327 +1,158 @@
1
1
  /**
2
- * unum - Svelte 5 Runes API for PluresDB
2
+ * pluresData() reactive data bindings for Svelte.
3
3
  *
4
- * This module provides a seamless binding between PluresDB and Svelte 5 components
5
- * using the new Runes reactivity system. Components can work with PluresDB data without
6
- * knowing about PluresDB specifics.
4
+ * Works with Svelte 4 (stores) and Svelte 5 (subscribe protocol).
5
+ * No polling. Pure subscription-based reactivity.
7
6
  */
8
- import { gun as dbStore } from './GunContext.js';
7
+ import { getRoot } from './context.js';
9
8
  /**
10
- * Creates a reactive connection to a PluresDB path
11
- * This is the primary API for Svelte 5 components to use PluresDB data
9
+ * Create a reactive binding to a PluresDB path.
10
+ *
11
+ * @param path - Collection/document path (e.g. 'todos', 'users/profile')
12
+ * @param id - Optional item ID for single-document binding
12
13
  *
13
14
  * @example
14
15
  * ```svelte
15
16
  * <script>
16
- * import { pluresData } from 'unum';
17
- *
18
- * // Create a reactive connection to PluresDB data
17
+ * import { pluresData } from '@plures/unum';
19
18
  * const todos = pluresData('todos');
20
- *
21
- * // Access a specific todo by ID
22
- * const todo = pluresData('todos', 'specific-id');
23
- *
24
- * // Create a new todo
25
- * function addTodo(text) {
26
- * todos.add({ text, completed: false });
27
- * }
28
- *
29
- * // Toggle a todo's completed status
30
- * function toggleTodo(id) {
31
- * todo.update(id, current => ({ ...current, completed: !current.completed }));
32
- * }
33
- *
34
- * // Delete a todo
35
- * function deleteTodo(id) {
36
- * todos.remove(id);
37
- * }
38
19
  * </script>
39
20
  *
40
- * <!-- Use the data directly in the template -->
41
- * <ul>
42
- * {#each todos.list() as item}
43
- * <li>{item.text}</li>
44
- * {/each}
45
- * </ul>
21
+ * {#each todos.list() as todo}
22
+ * <p>{todo.text}</p>
23
+ * {/each}
46
24
  * ```
47
25
  */
48
- export function pluresData(path, id = null) {
49
- // Using a plain object, not $state since this isn't a .svelte file
26
+ export function pluresData(path, id) {
50
27
  let state = {};
51
- let listeners = [];
52
- let db = null; // Reference to PluresDB instance
53
- let unsubscribe = null; // Store unsubscription function
54
- // Notify all listeners when state changes
55
- function notifyListeners() {
56
- for (const listener of listeners) {
57
- listener(state);
28
+ let subs = [];
29
+ const unsubs = [];
30
+ const root = getRoot();
31
+ const ref = root.get(path);
32
+ function notify() {
33
+ for (const cb of subs) {
34
+ try {
35
+ cb(state);
36
+ }
37
+ catch (e) {
38
+ console.error('[pluresData]', e);
39
+ }
58
40
  }
59
41
  }
60
- // Create the subscription to PluresDB data
61
- function initialize() {
62
- // Unsubscribe from any existing subscription
63
- if (unsubscribe) {
64
- unsubscribe();
65
- unsubscribe = null;
66
- }
67
- // Subscribe to PluresDB instance
68
- const storeUnsubscribe = dbStore.subscribe(dbInstance => {
69
- if (!dbInstance)
42
+ if (id) {
43
+ // Single item binding
44
+ const u = ref.get(id).on((data) => {
45
+ if (data) {
46
+ state = { ...data };
47
+ notify();
48
+ }
49
+ });
50
+ unsubs.push(u);
51
+ }
52
+ else {
53
+ // Collection binding
54
+ const u = ref.map().on((data, key) => {
55
+ if (!key || key === '_')
70
56
  return;
71
- // Store PluresDB instance reference
72
- db = dbInstance;
73
- // Create reference to the PluresDB path
74
- let ref = db.get(path);
75
- // If an ID is provided, narrow to that specific item
76
- if (id) {
77
- ref = ref.get(id);
78
- // Set up subscription to a single item
79
- const itemUnsubscribe = ref.on((data) => {
80
- if (data) {
81
- // Update state
82
- state = { ...(data || {}) };
83
- notifyListeners();
84
- }
85
- });
86
- // Update unsubscribe function
87
- unsubscribe = () => {
88
- ref.off();
89
- itemUnsubscribe();
90
- storeUnsubscribe();
91
- };
57
+ if (data === null || data === undefined) {
58
+ const next = { ...state };
59
+ delete next[key];
60
+ state = next;
92
61
  }
93
62
  else {
94
- // Set up subscription to a collection
95
- const mapUnsubscribe = ref.map().on((data, key) => {
96
- if (key === '_')
97
- return; // Skip internal PluresDB keys
98
- if (data === null) {
99
- // Item was deleted - create a new object to trigger updates
100
- const newState = { ...state };
101
- delete newState[key];
102
- state = newState;
103
- notifyListeners();
104
- }
105
- else {
106
- // Item was added or updated
107
- state = {
108
- ...state,
109
- [key]: { ...(data || {}), id: key, text: data.text || '' }
110
- };
111
- notifyListeners();
112
- }
113
- });
114
- // Update unsubscribe function
115
- unsubscribe = () => {
116
- ref.map().off();
117
- mapUnsubscribe();
118
- storeUnsubscribe();
119
- };
63
+ state = { ...state, [key]: { ...data, id: key } };
120
64
  }
65
+ notify();
121
66
  });
67
+ unsubs.push(u);
122
68
  }
123
- // Start the initialization
124
- initialize();
125
- // For collections, get an array of items suitable for #each loops
126
- function list() {
127
- if (id)
128
- return []; // Not applicable for single items
129
- return Object.values(state)
130
- .filter(item => item && typeof item === 'object')
131
- .map(item => ({ ...item, text: item.text || '' }));
132
- }
133
- // Add a new item to a collection
134
- function add(data) {
135
- if (!db || id)
136
- return; // Can't add to a single item reference
137
- const itemId = data.id || Date.now().toString();
138
- const newItem = {
139
- ...data,
140
- text: data.text || '' // Ensure text is never undefined
141
- };
142
- // Add to PluresDB directly
143
- db.get(path).get(itemId).put(newItem);
144
- // Also update local state for immediate UI updates
145
- state = {
146
- ...state,
147
- [itemId]: { ...newItem, id: itemId }
148
- };
149
- notifyListeners();
150
- }
151
- // Update an item (or the current item if this is a single item reference)
152
- function update(itemId, updater) {
153
- if (!db)
154
- return;
155
- if (id) {
156
- // This is a single item reference
157
- const updatedData = typeof updater === 'function'
158
- ? updater(state)
159
- : updater;
160
- db.get(path).get(id).put(updatedData);
161
- // Update local state immediately
162
- state = { ...state, ...updatedData };
163
- notifyListeners();
164
- }
165
- else {
166
- // This is a collection
167
- const item = state[itemId];
168
- if (!item)
169
- return;
170
- const updatedData = typeof updater === 'function'
171
- ? updater(item)
172
- : updater;
173
- db.get(path).get(itemId).put(updatedData);
174
- // Update local state immediately
175
- state = {
176
- ...state,
177
- [itemId]: { ...item, ...updatedData }
178
- };
179
- notifyListeners();
180
- }
181
- }
182
- // Remove an item (or all items if this is a collection and no id is provided)
183
- function remove(itemId = null) {
184
- if (!db)
185
- return;
186
- if (id) {
187
- // This is a single item reference - null it out
188
- db.get(path).get(id).put(null);
189
- state = {};
190
- notifyListeners();
191
- }
192
- else if (itemId) {
193
- // Remove a specific item from the collection
194
- db.get(path).get(itemId).put(null);
195
- // Update local state immediately
196
- const newState = { ...state };
197
- delete newState[itemId];
198
- state = newState;
199
- notifyListeners();
200
- }
201
- }
202
- // Subscribe to changes - this is needed for Svelte components to react
203
- function subscribe(callback) {
204
- listeners.push(callback);
205
- callback(state); // Initial call with current state
206
- // Return unsubscribe function
207
- return () => {
208
- listeners = listeners.filter(l => l !== callback);
209
- };
210
- }
211
- // Cleanup function
212
- function destroy() {
213
- if (unsubscribe) {
214
- unsubscribe();
215
- unsubscribe = null;
216
- }
217
- listeners = [];
218
- }
219
- // Return methods and data
220
- return {
221
- // Data access
69
+ const dataRef = {
222
70
  get state() { return state; },
223
- get value() { return id ? state : list(); },
224
- // Methods
225
- list,
226
- add,
227
- update,
228
- remove,
229
- subscribe,
230
- destroy
71
+ get value() { return id ? state : this.list(); },
72
+ list() {
73
+ return Object.values(state).filter((v) => v != null && typeof v === 'object');
74
+ },
75
+ add(data) {
76
+ if (id)
77
+ return;
78
+ const itemId = data.id ?? crypto.randomUUID().slice(0, 8);
79
+ const { id: _strip, ...rest } = data;
80
+ ref.get(itemId).put(rest);
81
+ state = { ...state, [itemId]: { ...rest, id: itemId } };
82
+ notify();
83
+ },
84
+ update(idOrUpdater, updater) {
85
+ if (id) {
86
+ const updated = typeof idOrUpdater === 'function' ? idOrUpdater(state) : idOrUpdater;
87
+ ref.get(id).put(updated);
88
+ state = { ...state, ...updated };
89
+ notify();
90
+ }
91
+ else if (typeof idOrUpdater === 'string' && updater != null) {
92
+ const item = state[idOrUpdater];
93
+ if (!item)
94
+ return;
95
+ const updated = typeof updater === 'function' ? updater(item) : updater;
96
+ ref.get(idOrUpdater).put(updated);
97
+ state = { ...state, [idOrUpdater]: { ...item, ...updated } };
98
+ notify();
99
+ }
100
+ },
101
+ remove(itemId) {
102
+ if (id) {
103
+ ref.get(id).put(null);
104
+ state = {};
105
+ }
106
+ else if (itemId) {
107
+ ref.get(itemId).put(null);
108
+ const next = { ...state };
109
+ delete next[itemId];
110
+ state = next;
111
+ }
112
+ notify();
113
+ },
114
+ subscribe(cb) {
115
+ subs.push(cb);
116
+ cb(state);
117
+ return () => { subs = subs.filter(s => s !== cb); };
118
+ },
119
+ destroy() {
120
+ for (const u of unsubs)
121
+ u();
122
+ unsubs.length = 0;
123
+ subs = [];
124
+ },
231
125
  };
126
+ return dataRef;
232
127
  }
233
128
  /**
234
- * Creates a derived state from PluresDB data - allows transforming/filtering PluresDB data
235
- *
236
- * @example
237
- * ```svelte
238
- * <script>
239
- * import { pluresData, pluresDerived } from 'unum';
240
- *
241
- * const todos = pluresData('todos');
242
- * const completedTodos = pluresDerived(todos, items => items.filter(item => item.completed));
243
- * </script>
244
- *
245
- * <h2>Completed Todos</h2>
246
- * <ul>
247
- * {#each completedTodos.value as item}
248
- * <li>{item.text}</li>
249
- * {/each}
250
- * </ul>
251
- * ```
129
+ * Derived view subscription-based, no polling.
252
130
  */
253
- export function pluresDerived(pluresData, transformer) {
254
- let $state = []; // Derived state
255
- // Create a computed value that updates when the source data changes
256
- function compute() {
257
- const sourceData = pluresData.list ? pluresData.list() : pluresData.value;
258
- $state = transformer(sourceData);
259
- }
260
- // Initial computation
261
- compute();
262
- // Set up a watcher to recompute when source data changes
263
- // This would be cleaner with Svelte 5's createEffect, but for now we'll use a workaround
264
- let previousSourceData = JSON.stringify(pluresData.list ? pluresData.list() : pluresData.value);
265
- // Check periodically for changes (not ideal, but works until Svelte 5 effects are stable)
266
- const interval = setInterval(() => {
267
- const currentSourceData = JSON.stringify(pluresData.list ? pluresData.list() : pluresData.value);
268
- if (previousSourceData !== currentSourceData) {
269
- previousSourceData = currentSourceData;
270
- compute();
271
- }
272
- }, 100);
273
- // Return reactive state and methods
131
+ export function pluresDerived(source, transform) {
132
+ let derived = [];
133
+ const unsub = source.subscribe(() => {
134
+ derived = transform(source.list());
135
+ });
274
136
  return {
275
- get value() { return $state; },
276
- destroy() {
277
- clearInterval(interval);
278
- if (pluresData.destroy)
279
- pluresData.destroy();
280
- }
137
+ get value() { return derived; },
138
+ destroy() { unsub(); },
281
139
  };
282
140
  }
283
141
  /**
284
- * Creates a two-way binding between a form input and PluresDB data
285
- *
286
- * @example
287
- * ```svelte
288
- * <script>
289
- * import { pluresBind } from 'unum';
290
- *
291
- * const userProfile = pluresData('userProfile');
292
- * const nameBinding = pluresBind(userProfile, 'name');
293
- * </script>
294
- *
295
- * <input type="text" bind:value={nameBinding.value} />
296
- * ```
142
+ * Two-way binding helper for form inputs.
297
143
  */
298
- export function pluresBind(pluresData, field) {
299
- let $value = pluresData.state && pluresData.state[field] || '';
300
- // Set up a watcher for changes to the PluresDB data
301
- let previousData = JSON.stringify(pluresData.state);
302
- const interval = setInterval(() => {
303
- const currentData = JSON.stringify(pluresData.state);
304
- if (previousData !== currentData) {
305
- previousData = currentData;
306
- $value = pluresData.state && pluresData.state[field] || '';
307
- }
308
- }, 100);
144
+ export function pluresBind(source, field) {
145
+ let _value = source.state?.[field] ?? '';
146
+ const unsub = source.subscribe((state) => {
147
+ _value = state?.[field] ?? '';
148
+ });
309
149
  return {
310
- get value() { return $value; },
311
- set value(newValue) {
312
- $value = newValue;
313
- // Update the PluresDB data
314
- if (pluresData.update) {
315
- pluresData.update({ [field]: newValue });
316
- }
150
+ get value() { return _value; },
151
+ set value(v) {
152
+ _value = v;
153
+ source.update({ [field]: v });
317
154
  },
318
- destroy() {
319
- clearInterval(interval);
320
- }
155
+ destroy() { unsub(); },
321
156
  };
322
157
  }
323
- // Legacy exports for backward compatibility
324
- export const gunData = pluresData;
325
- export const gunDerived = pluresDerived;
326
- export const gunBind = pluresBind;
327
158
  //# sourceMappingURL=runes.js.map