@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.
- package/README.md +3 -6
- package/dist/adapters/index.d.ts +3 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +3 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/memory.d.ts +7 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js +116 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/pluresdb.d.ts +14 -0
- package/dist/adapters/pluresdb.d.ts.map +1 -0
- package/dist/adapters/pluresdb.js +48 -0
- package/dist/adapters/pluresdb.js.map +1 -0
- package/dist/context.d.ts +29 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +43 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +8 -53
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -196
- package/dist/index.js.map +1 -1
- package/dist/runes.d.ts +17 -161
- package/dist/runes.d.ts.map +1 -1
- package/dist/runes.js +121 -290
- package/dist/runes.js.map +1 -1
- package/dist/store.d.ts +10 -21
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +31 -135
- package/dist/store.js.map +1 -1
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -49
- package/dist/GunContext.d.ts +0 -17
- package/dist/GunContext.d.ts.map +0 -1
- package/dist/GunContext.js +0 -180
- package/dist/GunContext.js.map +0 -1
- package/dist/actions.d.ts +0 -39
- package/dist/actions.d.ts.map +0 -1
- package/dist/actions.js +0 -89
- package/dist/actions.js.map +0 -1
- package/dist/gunComponent.d.ts +0 -44
- package/dist/gunComponent.d.ts.map +0 -1
- package/dist/gunComponent.js +0 -205
- package/dist/gunComponent.js.map +0 -1
- package/dist/gunify.d.ts +0 -46
- package/dist/gunify.d.ts.map +0 -1
- package/dist/gunify.js +0 -294
- package/dist/gunify.js.map +0 -1
- package/dist/plures-helper.d.ts +0 -41
- package/dist/plures-helper.d.ts.map +0 -1
- package/dist/plures-helper.js +0 -114
- package/dist/plures-helper.js.map +0 -1
- package/dist/universalGunBind.d.ts +0 -219
- package/dist/universalGunBind.d.ts.map +0 -1
- package/dist/universalGunBind.js +0 -394
- package/dist/universalGunBind.js.map +0 -1
package/dist/runes.d.ts
CHANGED
|
@@ -1,184 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* This is the primary API for Svelte 5 components to use PluresDB data
|
|
2
|
+
* pluresData() — reactive data bindings for Svelte.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
9
|
+
* Create a reactive binding to a PluresDB path.
|
|
52
10
|
*
|
|
53
|
-
* @
|
|
54
|
-
*
|
|
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 {
|
|
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
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
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
|
|
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
|
-
*
|
|
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
|
|
163
|
-
readonly value:
|
|
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
|
-
*
|
|
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
|
|
37
|
+
export declare function pluresBind(source: DataRef, field: string): {
|
|
182
38
|
value: any;
|
|
183
39
|
destroy(): void;
|
|
184
40
|
};
|
package/dist/runes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runes.d.ts","sourceRoot":"","sources":["../src/runes.
|
|
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
|
-
*
|
|
2
|
+
* pluresData() — reactive data bindings for Svelte.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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 {
|
|
7
|
+
import { getRoot } from './context.js';
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
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
|
|
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
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
function
|
|
56
|
-
for (const
|
|
57
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
-
*
|
|
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(
|
|
254
|
-
let
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
|
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
|
-
*
|
|
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(
|
|
299
|
-
let
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
|
311
|
-
set value(
|
|
312
|
-
|
|
313
|
-
|
|
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
|