dolphin-server-modules 2.2.1 → 2.2.5
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/DOLPHIN_MASTER_GUIDE_NEPALI.md +64 -24
- package/LICENSE +15 -0
- package/README.md +74 -143
- package/TUTORIAL_NEPALI.md +73 -193
- package/dist/adapters/mongoose/index.js.map +1 -1
- package/dist/adapters/mongoose/index.test.js.map +1 -1
- package/dist/adapters/mongoose/integration.test.js.map +1 -1
- package/dist/auth/auth.js.map +1 -1
- package/dist/auth/auth.test.js.map +1 -1
- package/dist/authController/authController.js.map +1 -1
- package/dist/authController/authController.test.js.map +1 -1
- package/dist/bin/cli.d.ts +2 -0
- package/dist/bin/cli.js +405 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/controller/controller.js.map +1 -1
- package/dist/controller/controller.test.js.map +1 -1
- package/dist/curd/crud.d.ts +1 -0
- package/dist/curd/crud.js +37 -12
- package/dist/curd/crud.js.map +1 -1
- package/dist/curd/crud.test.js.map +1 -1
- package/dist/demo-server.js.map +1 -1
- package/dist/djson/djson.js.map +1 -1
- package/dist/djson/djson.test.js.map +1 -1
- package/dist/dolphin-bench.d.ts +1 -0
- package/dist/dolphin-bench.js +68 -0
- package/dist/dolphin-bench.js.map +1 -0
- package/dist/hard-performance-test.d.ts +1 -0
- package/dist/hard-performance-test.js +102 -0
- package/dist/hard-performance-test.js.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/zod.js.map +1 -1
- package/dist/middleware/zod.test.js.map +1 -1
- package/dist/performance-test.d.ts +1 -0
- package/dist/performance-test.js +97 -0
- package/dist/performance-test.js.map +1 -0
- package/dist/real-test-mongoose.d.ts +1 -0
- package/dist/real-test-mongoose.js +109 -0
- package/dist/real-test-mongoose.js.map +1 -0
- package/dist/realtime/codec.js +5 -5
- package/dist/realtime/codec.js.map +1 -1
- package/dist/realtime/core.d.ts +1 -1
- package/dist/realtime/core.js +44 -14
- package/dist/realtime/core.js.map +1 -1
- package/dist/realtime/devicemanager.js.map +1 -1
- package/dist/realtime/index.js.map +1 -1
- package/dist/realtime/plugins.js.map +1 -1
- package/dist/realtime/realtime.test.js.map +1 -1
- package/dist/realtime/trie.js.map +1 -1
- package/dist/router/router.js +1 -0
- package/dist/router/router.js.map +1 -1
- package/dist/router/router.test.js.map +1 -1
- package/dist/server/server.js +2 -1
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.test.js.map +1 -1
- package/dist/signaling/index.js.map +1 -1
- package/dist/signaling/signaling.test.d.ts +1 -0
- package/dist/signaling/signaling.test.js +114 -0
- package/dist/signaling/signaling.test.js.map +1 -0
- package/dist/swagger/swagger.js.map +1 -1
- package/dist/swagger/swagger.test.js.map +1 -1
- package/dist/test-2fa-real.d.ts +1 -0
- package/dist/test-2fa-real.js +110 -0
- package/dist/test-2fa-real.js.map +1 -0
- package/dist/test-dolphin.d.ts +1 -0
- package/dist/test-dolphin.js +100 -0
- package/dist/test-dolphin.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +82 -20
- package/scripts/client.js +176 -8
- package/scripts/dolphin-persist.js +211 -0
package/scripts/client.js
CHANGED
|
@@ -176,11 +176,6 @@ class AuthHandler {
|
|
|
176
176
|
this.user = null;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
/**
|
|
180
|
-
* @param {string} email
|
|
181
|
-
* @param {string} password
|
|
182
|
-
* @returns {Promise<any>}
|
|
183
|
-
*/
|
|
184
179
|
async login(email, password) {
|
|
185
180
|
const res = await this.client.api.post('/auth/login', { email, password });
|
|
186
181
|
if (res.accessToken) {
|
|
@@ -190,12 +185,10 @@ class AuthHandler {
|
|
|
190
185
|
return res;
|
|
191
186
|
}
|
|
192
187
|
|
|
193
|
-
/** @param {any} data */
|
|
194
188
|
async register(data) {
|
|
195
189
|
return await this.client.api.post('/auth/register', data);
|
|
196
190
|
}
|
|
197
191
|
|
|
198
|
-
/** @returns {Promise<DolphinResponse>} */
|
|
199
192
|
async me() {
|
|
200
193
|
const res = await this.client.api.get('/auth/me');
|
|
201
194
|
if (res.success) {
|
|
@@ -216,6 +209,170 @@ class AuthHandler {
|
|
|
216
209
|
}
|
|
217
210
|
}
|
|
218
211
|
|
|
212
|
+
/**
|
|
213
|
+
* DolphinStore - Reactive State Sync (Zustand Alternative)
|
|
214
|
+
* Automatically syncs database collections with local state.
|
|
215
|
+
*/
|
|
216
|
+
class DolphinStore {
|
|
217
|
+
/** @param {DolphinClient} client */
|
|
218
|
+
constructor(client) {
|
|
219
|
+
this.client = client;
|
|
220
|
+
/** @type {Map<string, { items: any[], loading: boolean, error: string|null, success: boolean }>} */
|
|
221
|
+
this.data = new Map();
|
|
222
|
+
/** @type {Set<function()>} */
|
|
223
|
+
this.listeners = new Set();
|
|
224
|
+
/** @type {Set<string>} */
|
|
225
|
+
this.subscribed = new Set();
|
|
226
|
+
|
|
227
|
+
return new Proxy(this, {
|
|
228
|
+
get: (target, prop) => {
|
|
229
|
+
if (prop in target) return target[prop];
|
|
230
|
+
if (typeof prop === 'string') {
|
|
231
|
+
return this._getCollection(prop);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** @private */
|
|
238
|
+
_getCollection(name) {
|
|
239
|
+
if (!this.data.has(name)) {
|
|
240
|
+
const collection = {
|
|
241
|
+
_rawItems: [],
|
|
242
|
+
items: [],
|
|
243
|
+
loading: true,
|
|
244
|
+
error: null,
|
|
245
|
+
success: false,
|
|
246
|
+
_filter: null,
|
|
247
|
+
_sort: null,
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* फिल्टर सेट गर्ने (Local filtering)
|
|
251
|
+
* @param {function(any): boolean} fn
|
|
252
|
+
*/
|
|
253
|
+
where: (fn) => {
|
|
254
|
+
collection._filter = fn;
|
|
255
|
+
this._applyTransform(collection);
|
|
256
|
+
return collection;
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* सर्टिङ सेट गर्ने
|
|
261
|
+
* @param {string} key
|
|
262
|
+
* @param {'asc'|'desc'} [direction]
|
|
263
|
+
*/
|
|
264
|
+
orderBy: (key, direction = 'asc') => {
|
|
265
|
+
collection._sort = { key, direction };
|
|
266
|
+
this._applyTransform(collection);
|
|
267
|
+
return collection;
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* फिल्टर र सर्ट हटाउने
|
|
272
|
+
*/
|
|
273
|
+
clear: () => {
|
|
274
|
+
collection._filter = null;
|
|
275
|
+
collection._sort = null;
|
|
276
|
+
this._applyTransform(collection);
|
|
277
|
+
return collection;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
this.data.set(name, collection);
|
|
282
|
+
this._fetchAndSync(name);
|
|
283
|
+
}
|
|
284
|
+
return this.data.get(name);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** @private */
|
|
288
|
+
async _fetchAndSync(name) {
|
|
289
|
+
const state = this.data.get(name);
|
|
290
|
+
try {
|
|
291
|
+
// 1. Initial Fetch
|
|
292
|
+
const res = await this.client.api.get(`/${name.toLowerCase()}`);
|
|
293
|
+
state._rawItems = Array.isArray(res) ? res : (res.data || []);
|
|
294
|
+
state.loading = false;
|
|
295
|
+
state.success = true;
|
|
296
|
+
state.error = null;
|
|
297
|
+
this._applyTransform(state);
|
|
298
|
+
|
|
299
|
+
// 2. Realtime Sync (if connected)
|
|
300
|
+
if (!this.subscribed.has(name)) {
|
|
301
|
+
const topic = `db:sync/${name.toLowerCase()}`;
|
|
302
|
+
this.client.subscribe(topic, (update) => {
|
|
303
|
+
this._handleRemoteUpdate(name, update);
|
|
304
|
+
});
|
|
305
|
+
this.subscribed.add(name);
|
|
306
|
+
}
|
|
307
|
+
} catch (e) {
|
|
308
|
+
state.loading = false;
|
|
309
|
+
state.success = false;
|
|
310
|
+
state.error = e.data?.error || e.message || 'Fetch failed';
|
|
311
|
+
this._notify();
|
|
312
|
+
console.error(`[DolphinStore] Sync failed for ${name}:`, e);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** @private */
|
|
317
|
+
_applyTransform(state) {
|
|
318
|
+
let result = [...state._rawItems];
|
|
319
|
+
|
|
320
|
+
// 1. Filter
|
|
321
|
+
if (state._filter) {
|
|
322
|
+
result = result.filter(state._filter);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// 2. Sort
|
|
326
|
+
if (state._sort) {
|
|
327
|
+
const { key, direction } = state._sort;
|
|
328
|
+
result.sort((a, b) => {
|
|
329
|
+
const av = a[key];
|
|
330
|
+
const bv = b[key];
|
|
331
|
+
if (av === bv) return 0;
|
|
332
|
+
const compare = av > bv ? 1 : -1;
|
|
333
|
+
return direction === 'asc' ? compare : -compare;
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
state.items = result;
|
|
338
|
+
this._notify();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** @private */
|
|
342
|
+
_handleRemoteUpdate(collection, update) {
|
|
343
|
+
const state = this.data.get(collection);
|
|
344
|
+
if (!state) return;
|
|
345
|
+
|
|
346
|
+
let items = state._rawItems;
|
|
347
|
+
const { type, data } = update; // type: 'create', 'update', 'delete'
|
|
348
|
+
|
|
349
|
+
if (type === 'create') {
|
|
350
|
+
items = [...items, data];
|
|
351
|
+
} else if (type === 'update') {
|
|
352
|
+
items = items.map(item => (item.id === data.id || item._id === data._id) ? { ...item, ...data } : item);
|
|
353
|
+
} else if (type === 'delete') {
|
|
354
|
+
items = items.filter(item => (item.id !== data.id && item._id !== data._id));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
state._rawItems = items;
|
|
358
|
+
this._applyTransform(state);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Subscribe for React components (useSyncExternalStore) */
|
|
362
|
+
subscribe(listener) {
|
|
363
|
+
this.listeners.add(listener);
|
|
364
|
+
return () => this.listeners.delete(listener);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
getSnapshot(collection) {
|
|
368
|
+
return this.data.get(collection) || { items: [], loading: false, error: null, success: false };
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
_notify() {
|
|
372
|
+
this.listeners.forEach(l => l());
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
219
376
|
class DolphinClient {
|
|
220
377
|
/**
|
|
221
378
|
* @param {string} [url]
|
|
@@ -256,6 +413,7 @@ class DolphinClient {
|
|
|
256
413
|
// Sub-handlers
|
|
257
414
|
this.api = new APIHandler(this);
|
|
258
415
|
this.auth = new AuthHandler(this);
|
|
416
|
+
this.store = new DolphinStore(this);
|
|
259
417
|
|
|
260
418
|
/** @type {Map<string, Set<TopicCallback>>} */
|
|
261
419
|
this.handlers = new Map(); // topic -> Set of callbacks
|
|
@@ -395,7 +553,13 @@ class DolphinClient {
|
|
|
395
553
|
* @param {TopicCallback} callback
|
|
396
554
|
*/
|
|
397
555
|
subscribe(topic, callback) {
|
|
398
|
-
if (!this.handlers.has(topic))
|
|
556
|
+
if (!this.handlers.has(topic)) {
|
|
557
|
+
this.handlers.set(topic, new Set());
|
|
558
|
+
// Tell server we want to sub
|
|
559
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
560
|
+
this.socket.send(JSON.stringify({ type: 'sub', topic }));
|
|
561
|
+
}
|
|
562
|
+
}
|
|
399
563
|
this.handlers.get(topic).add(callback);
|
|
400
564
|
}
|
|
401
565
|
|
|
@@ -409,6 +573,10 @@ class DolphinClient {
|
|
|
409
573
|
callbacks.delete(callback);
|
|
410
574
|
if (callbacks.size === 0) {
|
|
411
575
|
this.handlers.delete(topic);
|
|
576
|
+
// Tell server we want to unsub
|
|
577
|
+
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
578
|
+
this.socket.send(JSON.stringify({ type: 'unsub', topic }));
|
|
579
|
+
}
|
|
412
580
|
}
|
|
413
581
|
}
|
|
414
582
|
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DolphinPersist - Offline Cache Plugin for Dolphin Client
|
|
3
|
+
*
|
|
4
|
+
* Optional, zero-dependency persistence layer for DolphinStore.
|
|
5
|
+
* Supports both localStorage (simple) and IndexedDB (large data).
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* // Auto-detect best storage:
|
|
9
|
+
* const persist = new DolphinPersist();
|
|
10
|
+
* dolphin.store.use(persist);
|
|
11
|
+
*
|
|
12
|
+
* // Force localStorage:
|
|
13
|
+
* const persist = new DolphinPersist({ driver: 'localstorage' });
|
|
14
|
+
*
|
|
15
|
+
* // Force IndexedDB:
|
|
16
|
+
* const persist = new DolphinPersist({ driver: 'indexeddb' });
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
class DolphinPersist {
|
|
20
|
+
/**
|
|
21
|
+
* @param {{ driver?: 'auto'|'localstorage'|'indexeddb', prefix?: string, ttl?: number }} options
|
|
22
|
+
*/
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
this.driver = options.driver || 'auto';
|
|
25
|
+
this.prefix = options.prefix || 'dolphin_persist_';
|
|
26
|
+
this.ttl = options.ttl || 0; // 0 = no expiry (milliseconds)
|
|
27
|
+
this._db = null;
|
|
28
|
+
this._ready = false;
|
|
29
|
+
this._readyPromise = this._init();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async _init() {
|
|
33
|
+
if (this.driver === 'auto') {
|
|
34
|
+
this.driver = typeof indexedDB !== 'undefined' ? 'indexeddb' : 'localstorage';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (this.driver === 'indexeddb') {
|
|
38
|
+
try {
|
|
39
|
+
await this._openIndexedDB();
|
|
40
|
+
} catch {
|
|
41
|
+
console.warn('[DolphinPersist] IndexedDB unavailable, falling back to localStorage');
|
|
42
|
+
this.driver = 'localstorage';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this._ready = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_openIndexedDB() {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const req = indexedDB.open('dolphin_persist', 1);
|
|
52
|
+
req.onupgradeneeded = (e) => {
|
|
53
|
+
const db = e.target.result;
|
|
54
|
+
if (!db.objectStoreNames.contains('cache')) {
|
|
55
|
+
db.createObjectStore('cache', { keyPath: 'key' });
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
req.onsuccess = (e) => { this._db = e.target.result; resolve(); };
|
|
59
|
+
req.onerror = () => reject(req.error);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async set(collection, data) {
|
|
64
|
+
await this._readyPromise;
|
|
65
|
+
const entry = {
|
|
66
|
+
data,
|
|
67
|
+
savedAt: Date.now(),
|
|
68
|
+
expiresAt: this.ttl ? Date.now() + this.ttl : null
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
if (this.driver === 'indexeddb') {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
const tx = this._db.transaction('cache', 'readwrite');
|
|
74
|
+
tx.objectStore('cache').put({ key: this.prefix + collection, ...entry });
|
|
75
|
+
tx.oncomplete = resolve;
|
|
76
|
+
tx.onerror = reject;
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
try {
|
|
80
|
+
localStorage.setItem(this.prefix + collection, JSON.stringify(entry));
|
|
81
|
+
} catch (e) {
|
|
82
|
+
console.warn('[DolphinPersist] localStorage write failed:', e.message);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async get(collection) {
|
|
88
|
+
await this._readyPromise;
|
|
89
|
+
let entry = null;
|
|
90
|
+
|
|
91
|
+
if (this.driver === 'indexeddb') {
|
|
92
|
+
entry = await new Promise((resolve, reject) => {
|
|
93
|
+
const tx = this._db.transaction('cache', 'readonly');
|
|
94
|
+
const req = tx.objectStore('cache').get(this.prefix + collection);
|
|
95
|
+
req.onsuccess = () => resolve(req.result || null);
|
|
96
|
+
req.onerror = reject;
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
try {
|
|
100
|
+
const raw = localStorage.getItem(this.prefix + collection);
|
|
101
|
+
entry = raw ? JSON.parse(raw) : null;
|
|
102
|
+
} catch { entry = null; }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!entry) return null;
|
|
106
|
+
|
|
107
|
+
// TTL check
|
|
108
|
+
if (entry.expiresAt && Date.now() > entry.expiresAt) {
|
|
109
|
+
await this.clear(collection);
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return entry.data;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async clear(collection) {
|
|
117
|
+
await this._readyPromise;
|
|
118
|
+
if (this.driver === 'indexeddb') {
|
|
119
|
+
return new Promise((resolve) => {
|
|
120
|
+
const tx = this._db.transaction('cache', 'readwrite');
|
|
121
|
+
tx.objectStore('cache').delete(this.prefix + collection);
|
|
122
|
+
tx.oncomplete = resolve;
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
localStorage.removeItem(this.prefix + collection);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async clearAll() {
|
|
130
|
+
await this._readyPromise;
|
|
131
|
+
if (this.driver === 'indexeddb') {
|
|
132
|
+
return new Promise((resolve) => {
|
|
133
|
+
const tx = this._db.transaction('cache', 'readwrite');
|
|
134
|
+
tx.objectStore('cache').clear();
|
|
135
|
+
tx.oncomplete = resolve;
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
const keysToRemove = [];
|
|
139
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
140
|
+
const k = localStorage.key(i);
|
|
141
|
+
if (k && k.startsWith(this.prefix)) keysToRemove.push(k);
|
|
142
|
+
}
|
|
143
|
+
keysToRemove.forEach(k => localStorage.removeItem(k));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Check what's cached */
|
|
148
|
+
async info(collection) {
|
|
149
|
+
await this._readyPromise;
|
|
150
|
+
const entry = await this.get(collection);
|
|
151
|
+
if (!entry) return null;
|
|
152
|
+
return {
|
|
153
|
+
collection,
|
|
154
|
+
items: entry.length,
|
|
155
|
+
driver: this.driver,
|
|
156
|
+
savedAt: new Date(entry.savedAt)
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================
|
|
162
|
+
// Extend DolphinStore to support persist plugin
|
|
163
|
+
// ============================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Monkey-patches the DolphinStore to support .use(persist) plugin.
|
|
167
|
+
* Call this after DolphinClient is loaded.
|
|
168
|
+
*/
|
|
169
|
+
function enablePersist(storeInstance, persist) {
|
|
170
|
+
const originalFetch = storeInstance._fetchAndSync.bind(storeInstance);
|
|
171
|
+
|
|
172
|
+
storeInstance._fetchAndSync = async function(name) {
|
|
173
|
+
// 1. Load from cache first (instant render)
|
|
174
|
+
const cached = await persist.get(name);
|
|
175
|
+
if (cached && cached.length > 0) {
|
|
176
|
+
storeInstance.data.set(name, cached);
|
|
177
|
+
storeInstance._notify();
|
|
178
|
+
console.log(`[DolphinPersist] Loaded "${name}" from ${persist.driver} cache (${cached.length} items)`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 2. Fetch fresh from server
|
|
182
|
+
await originalFetch(name);
|
|
183
|
+
|
|
184
|
+
// 3. Save updated data to cache
|
|
185
|
+
const fresh = storeInstance.data.get(name) || [];
|
|
186
|
+
await persist.set(name, fresh);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Also persist on every realtime update
|
|
190
|
+
const originalUpdate = storeInstance._handleRemoteUpdate.bind(storeInstance);
|
|
191
|
+
storeInstance._handleRemoteUpdate = async function(collection, update) {
|
|
192
|
+
originalUpdate(collection, update);
|
|
193
|
+
const updated = storeInstance.data.get(collection) || [];
|
|
194
|
+
await persist.set(collection, updated);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
console.log(`[DolphinPersist] Persistence enabled using ${persist.driver}`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ============================================
|
|
201
|
+
// Exports
|
|
202
|
+
// ============================================
|
|
203
|
+
|
|
204
|
+
if (typeof window !== 'undefined') {
|
|
205
|
+
window.DolphinPersist = DolphinPersist;
|
|
206
|
+
window.enablePersist = enablePersist;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
210
|
+
module.exports = { DolphinPersist, enablePersist };
|
|
211
|
+
}
|