taon-storage 21.0.10 → 21.0.11

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/lib/storage.js CHANGED
@@ -1,241 +1,508 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Stor = void 0;
3
+ exports.Stor = exports.StorPropertyInIndexedDb = exports.StorPropertyInLocalStorage = exports.keyDefaultValueAreadySet = exports.StorConfig = exports.storeName = void 0;
4
+ exports.keyValue = keyValue;
5
+ exports.keyDefaultValueAlreadySet = keyDefaultValueAlreadySet;
4
6
  exports.uncache = uncache;
5
- const helpers_1 = require("./helpers");
6
- const file_stor_1 = require("./file-stor");
7
- /* */
8
- /* */
9
- //#endregion
10
- //#region constants
11
- const AWAITING_INTERVAL_TIME = 200;
12
- //#endregion
13
- //#region public api / uncahce
14
- function uncache(onlyInThisComponentClass, propertyValueToDeleteFromCache) {
15
- if (!onlyInThisComponentClass) { // @ts-ignore
16
- onlyInThisComponentClass = { name: '__GLOBAL_NAMESPACE__' };
17
- }
18
- return Promise.all([
19
- /* */
20
- /* */
21
- /* */
22
- /* */
23
- /* */
24
- ]);
7
+ /* taon-storage (native, SSR-safe) */
8
+ const lib_1 = require("tnp-core/lib");
9
+ const isBrowser = typeof window !== 'undefined' &&
10
+ typeof document !== 'undefined' &&
11
+ typeof navigator !== 'undefined';
12
+ function getGlobalEnv() {
13
+ return globalThis?.ENV;
14
+ }
15
+ function safeLocationPort() {
16
+ try {
17
+ return globalThis?.location?.port || 'no-port';
18
+ }
19
+ catch {
20
+ return 'no-port';
21
+ }
22
+ }
23
+ /**
24
+ * Keeps the spirit of your old `storeName = taon-storage_<port>`
25
+ * plus project name namespacing (but without localForage).
26
+ */
27
+ exports.storeName = `taon-storage_${safeLocationPort()}`;
28
+ function defaultNamespace() {
29
+ const env = getGlobalEnv();
30
+ const project = lib_1._.kebabCase(env?.currentProjectGenericName ?? '');
31
+ return project ? `${exports.storeName}_${project}` : exports.storeName;
32
+ }
33
+ /**
34
+ * Central config (optional).
35
+ * You can set it once at app bootstrap if you want a stable namespace.
36
+ */
37
+ exports.StorConfig = {
38
+ namespace: defaultNamespace(),
39
+ indexedDb: {
40
+ dbName: `${defaultNamespace()}_INDEXEDDB`,
41
+ storeName: 'keyvaluepairs',
42
+ },
43
+ };
44
+ function normalizeScopeClass(cls) {
45
+ if (!cls)
46
+ return { name: '__GLOBAL_NAMESPACE__' };
47
+ // if it's a function/class
48
+ if (typeof cls === 'function')
49
+ return { name: cls.name || '__ANON__' };
50
+ // if it's already object with name
51
+ return { name: cls.name || '__ANON__' };
52
+ }
53
+ function keyValue(scopeClass, memberName) {
54
+ const c = normalizeScopeClass(scopeClass);
55
+ return `${exports.StorConfig.namespace}::taon.storage.class.${c.name}.prop.${memberName}`;
56
+ }
57
+ function keyDefaultValueAlreadySet(scopeClass, memberName) {
58
+ return `${keyValue(scopeClass, memberName)}::defaultvalueisset`;
59
+ }
60
+ /** Back-compat alias (your old typo) */
61
+ exports.keyDefaultValueAreadySet = keyDefaultValueAlreadySet;
62
+ class NoopStore {
63
+ async getItem(_key) {
64
+ return undefined;
65
+ }
66
+ async setItem(_key, _value) {
67
+ // noop
68
+ }
69
+ async removeItem(_key) {
70
+ // noop
71
+ }
72
+ }
73
+ class BrowserLocalStorageStore {
74
+ ls() {
75
+ if (!isBrowser)
76
+ return undefined;
77
+ try {
78
+ return window.localStorage;
79
+ }
80
+ catch {
81
+ return undefined;
82
+ }
83
+ }
84
+ async getItem(key) {
85
+ const ls = this.ls();
86
+ if (!ls)
87
+ return undefined;
88
+ const raw = ls.getItem(key);
89
+ if (raw === null)
90
+ return undefined;
91
+ try {
92
+ return JSON.parse(raw);
93
+ }
94
+ catch {
95
+ // if something stored plain string by older versions
96
+ return raw;
97
+ }
98
+ }
99
+ async setItem(key, value) {
100
+ const ls = this.ls();
101
+ if (!ls)
102
+ return;
103
+ try {
104
+ ls.setItem(key, JSON.stringify(value));
105
+ }
106
+ catch {
107
+ // last resort: try as string
108
+ try {
109
+ ls.setItem(key, String(value));
110
+ }
111
+ catch {
112
+ // ignore (quota/private mode)
113
+ }
114
+ }
115
+ }
116
+ async removeItem(key) {
117
+ const ls = this.ls();
118
+ if (!ls)
119
+ return;
120
+ try {
121
+ ls.removeItem(key);
122
+ }
123
+ catch {
124
+ // ignore
125
+ }
126
+ }
127
+ }
128
+ class BrowserIndexedDbStore {
129
+ dbPromise = null;
130
+ openDb() {
131
+ if (!isBrowser || !window.indexedDB) {
132
+ return Promise.reject(new Error('IndexedDB not available'));
133
+ }
134
+ if (this.dbPromise)
135
+ return this.dbPromise;
136
+ const { dbName, storeName } = exports.StorConfig.indexedDb;
137
+ this.dbPromise = new Promise((resolve, reject) => {
138
+ const req = indexedDB.open(dbName, 1);
139
+ req.onupgradeneeded = () => {
140
+ const db = req.result;
141
+ if (!db.objectStoreNames.contains(storeName)) {
142
+ db.createObjectStore(storeName);
143
+ }
144
+ };
145
+ req.onsuccess = () => resolve(req.result);
146
+ req.onerror = () => reject(req.error);
147
+ });
148
+ return this.dbPromise;
149
+ }
150
+ async withStore(mode, fn) {
151
+ const db = await this.openDb();
152
+ const { storeName } = exports.StorConfig.indexedDb;
153
+ return await new Promise((resolve, reject) => {
154
+ const tx = db.transaction(storeName, mode);
155
+ const store = tx.objectStore(storeName);
156
+ const req = fn(store);
157
+ req.onsuccess = () => resolve(req.result);
158
+ req.onerror = () => reject(req.error);
159
+ tx.onabort = () => reject(tx.error);
160
+ // tx.oncomplete => nothing
161
+ });
162
+ }
163
+ async getItem(key) {
164
+ try {
165
+ const result = await this.withStore('readonly', s => s.get(key));
166
+ return result === undefined ? undefined : result;
167
+ }
168
+ catch {
169
+ return undefined;
170
+ }
171
+ }
172
+ async setItem(key, value) {
173
+ try {
174
+ await this.withStore('readwrite', s => s.put(value, key));
175
+ }
176
+ catch {
177
+ // ignore
178
+ }
179
+ }
180
+ async removeItem(key) {
181
+ try {
182
+ await this.withStore('readwrite', s => s.delete(key));
183
+ }
184
+ catch {
185
+ // ignore
186
+ }
187
+ }
25
188
  }
26
- //#endregion
27
- class TaonStorage {
28
- //#region static
29
- static pendingOperatins = [];
189
+ /**
190
+ * Node-side file storage (optional). No top-level node imports (Angular-safe).
191
+ * Works only when executed in Node.
192
+ */
193
+ class FileStor {
194
+ filePath;
195
+ useJSON;
196
+ constructor(filePath, useJSON = false) {
197
+ this.filePath = filePath;
198
+ this.useJSON = useJSON;
199
+ }
200
+ isNodeRuntime() {
201
+ return lib_1.UtilsOs.isNode;
202
+ // return (
203
+ // typeof process !== 'undefined' &&
204
+ // !!(process as any).versions?.node &&
205
+ // typeof (globalThis as any).window === 'undefined'
206
+ // );
207
+ }
208
+ async setItem(_key, value) {
209
+ if (!this.isNodeRuntime())
210
+ return;
211
+ //#region @backendFunc
212
+ const fs = await Promise.resolve().then(() => require('node:fs/promises'));
213
+ const data = this.useJSON ? JSON.stringify(value, null, 2) : value;
214
+ if (this.useJSON) {
215
+ await fs.writeFile(this.filePath, String(data), 'utf8');
216
+ }
217
+ else {
218
+ await fs.writeFile(this.filePath, String(data), 'utf8');
219
+ }
220
+ //#endregion
221
+ }
222
+ async getItem(_key) {
223
+ if (!this.isNodeRuntime())
224
+ return undefined;
225
+ //#region @backendFunc
226
+ const fs = await Promise.resolve().then(() => require('node:fs/promises'));
227
+ try {
228
+ const buf = await fs.readFile(this.filePath, 'utf8');
229
+ if (!this.useJSON)
230
+ return buf;
231
+ return JSON.parse(buf);
232
+ }
233
+ catch {
234
+ return undefined;
235
+ }
236
+ //#endregion
237
+ }
238
+ async removeItem(_key) {
239
+ if (!this.isNodeRuntime())
240
+ return;
241
+ //#region @backendFunc
242
+ const fs = await Promise.resolve().then(() => require('node:fs/promises'));
243
+ try {
244
+ await fs.rm(this.filePath, { force: true });
245
+ }
246
+ catch {
247
+ // ignore
248
+ }
249
+ //#endregion
250
+ }
251
+ }
252
+ /* ---------------------------
253
+ * Pending ops (so you can still await)
254
+ * -------------------------- */
255
+ class StorPending {
256
+ static pending = [];
30
257
  static id = 0;
31
- /**
32
- * TODO This is fine for now, but could be something smarter here
33
- */
34
- static async awaitPendingOperatios(id = TaonStorage.id++) {
35
- // console.log('AWAITING')
258
+ static AWAITING_INTERVAL_TIME = 200;
259
+ static async awaitPendingOperations(id = StorPending.id++) {
36
260
  if (id > Number.MAX_SAFE_INTEGER - 2) {
37
- TaonStorage.id = 0;
38
- id = TaonStorage.id++;
261
+ StorPending.id = 0;
262
+ id = StorPending.id++;
39
263
  }
40
- const pending = this.pendingOperatins;
41
- const toDeleteIndex = [];
42
- for (let index = 0; index < pending.length; index++) {
43
- const op = pending[index];
264
+ const pending = StorPending.pending;
265
+ for (const op of pending) {
44
266
  if (!op.isDone) {
45
- await new Promise(async (resovle, reject) => {
267
+ await new Promise(resolve => {
46
268
  setTimeout(async () => {
47
- await this.awaitPendingOperatios(id);
48
- resovle();
49
- }, AWAITING_INTERVAL_TIME);
269
+ await StorPending.awaitPendingOperations(id);
270
+ resolve();
271
+ }, StorPending.AWAITING_INTERVAL_TIME);
50
272
  });
51
273
  return;
52
274
  }
53
- else {
54
- toDeleteIndex.push(index);
55
- }
56
- }
57
- for (let index = 0; index < toDeleteIndex.length; index++) {
58
- const toDelete = toDeleteIndex[index];
59
- pending.splice(toDelete, 1);
60
275
  }
276
+ // cleanup
277
+ StorPending.pending = pending.filter(p => !p.isDone);
61
278
  }
62
- static get property() {
63
- return new TaonStorage();
279
+ static start(engine, id) {
280
+ const op = { engine, id, isDone: false };
281
+ StorPending.pending.push(op);
282
+ return op;
283
+ }
284
+ static done(op) {
285
+ op.isDone = true;
64
286
  }
65
- //#endregion
66
- //#region private fields
67
- onlyInThisComponentClass;
68
- defaultValue;
287
+ }
288
+ /* ---------------------------
289
+ * Decorator builder
290
+ * -------------------------- */
291
+ class StorPropertyBuilder {
292
+ scopeClass;
69
293
  engine;
70
- //#region private fields / file path
71
- //#region @backend
294
+ store;
72
295
  filePath;
73
- //#endregion
74
- //#endregion
75
- //#endregion
76
- //#region public getters
77
- get in() {
78
- const that = this;
79
- return {
80
- get indexedb() {
81
- that.engine = 'indexeddb';
82
- return that;
83
- },
84
- get localstorage() {
85
- that.engine = 'localstorage';
86
- return that;
87
- },
88
- //#region @backend
89
- /**
90
- * may be relative or absolute
91
- */
92
- file(filePath) {
93
- that.engine = 'file';
94
- that.filePath = filePath;
95
- return that;
96
- },
97
- jsonFile(filePath) {
98
- that.engine = 'json';
99
- that.filePath = filePath;
100
- return that;
101
- },
102
- //#endregion
103
- };
296
+ useJsonFile = false;
297
+ constructor(engine, store) {
298
+ this.engine = engine;
299
+ this.store = store;
300
+ }
301
+ for(scopeClass) {
302
+ this.scopeClass = scopeClass;
303
+ return this;
104
304
  }
105
- //#endregion
106
- //#region public methods
107
- //#region public methods / for
108
- /* */
109
- /* */
110
- /* */
111
- /* */
112
- /* */
113
- //#endregion
114
- //#region public methods / with default value
115
305
  withDefaultValue(defaultValue) {
116
- // log.i(`["${}"]`)
117
- return this.action(defaultValue, this.getEngine(), this.engine);
306
+ return this.withOptions({ defaultValue });
118
307
  }
119
- //#endregion
120
- //#region public methods / with options
121
308
  withOptions(options) {
122
- const { defaultValue, transformFrom, transformTo } = (options || {});
123
- return this.action(defaultValue ? defaultValue : this.defaultValue, this.getEngine(), this.engine, transformFrom, transformTo);
124
- }
125
- //#endregion
126
- //#endregion
127
- //#region private methods
128
- //#region private methods / get engine
129
- getEngine() {
130
- switch (this.engine) {
131
- /* */
132
- /* */
133
- /* */
134
- /* */
135
- /* */
136
- //#region @backend
137
- case 'file':
138
- return new file_stor_1.FileStor(this.filePath);
139
- case 'json':
140
- return new file_stor_1.FileStor(this.filePath, true);
141
- //#endregion
142
- }
143
- }
144
- //#endregion
145
- //#region private methods / end observer action
146
- endObserverAction(observe) {
147
- // observe.subscribers.forEach(c => typeof c?.awaitId === 'function' && c());
148
- observe.isDone = true;
149
- }
150
- //#endregion
151
- //#region private methods / action
152
- action = (defaultValue, storageEngine
153
- /* */
154
- /* */
155
- , engine, transformFrom, transformTo) => {
156
- if (!this.onlyInThisComponentClass) { // @ts-ignore
157
- this.onlyInThisComponentClass = { name: '__GLOBAL_NAMESPACE__' };
158
- }
309
+ const scopeClass = this.scopeClass;
310
+ // per-instance state (fixes prototype-closure sharing)
311
+ const values = new WeakMap();
312
+ const initStarted = new WeakMap();
313
+ const ensureInit = (instance) => {
314
+ if (initStarted.has(instance))
315
+ return;
316
+ const op = StorPending.start(this.engine, 'init');
317
+ const p = (async () => {
318
+ const memberName = ensureInit.__memberName;
319
+ const kVal = keyValue(scopeClass, memberName);
320
+ const kDef = keyDefaultValueAlreadySet(scopeClass, memberName);
321
+ const defProvided = options.defaultValue !== undefined;
322
+ if (!isBrowser &&
323
+ (this.engine === 'localstorage' || this.engine === 'indexeddb')) {
324
+ // SSR: just set defaults, no storage
325
+ if (defProvided)
326
+ values.set(instance, options.defaultValue);
327
+ return;
328
+ }
329
+ // Browser (or node file/json)
330
+ if (defProvided) {
331
+ const already = await this.store.getItem(kDef);
332
+ if (already) {
333
+ const stored = await this.store.getItem(kVal);
334
+ const v = options.transformFrom
335
+ ? options.transformFrom(stored)
336
+ : stored;
337
+ if (v !== undefined)
338
+ values.set(instance, v);
339
+ else
340
+ values.set(instance, options.defaultValue);
341
+ }
342
+ else {
343
+ await this.store.setItem(kDef, true);
344
+ const toDb = options.transformTo
345
+ ? options.transformTo(options.defaultValue)
346
+ : options.defaultValue;
347
+ await this.store.setItem(kVal, toDb);
348
+ values.set(instance, options.defaultValue);
349
+ }
350
+ }
351
+ else {
352
+ const stored = await this.store.getItem(kVal);
353
+ const v = options.transformFrom
354
+ ? options.transformFrom(stored)
355
+ : stored;
356
+ if (v !== undefined)
357
+ values.set(instance, v);
358
+ }
359
+ })()
360
+ .catch(() => {
361
+ // swallow, keep app alive
362
+ })
363
+ .finally(() => StorPending.done(op));
364
+ initStarted.set(instance, p);
365
+ };
159
366
  return (target, memberName) => {
160
- let currentValue = target[memberName];
161
- const setItemDefaultValue = async () => {
162
- //#region settin default value
163
- const observe = {
164
- engine,
165
- id: 'setting default value'
166
- };
167
- TaonStorage.pendingOperatins.push(observe);
168
- await new Promise((resolve, reject) => {
169
- storageEngine.getItem((0, helpers_1.keyValue)(this.onlyInThisComponentClass, memberName), (err, valFromDb) => {
170
- // target[memberName] = valFromDb;
171
- currentValue = transformFrom ? transformFrom(valFromDb) : valFromDb;
172
- // log.info(`["${memberName}"] set default value for `, valFromDb);
173
- resolve();
174
- this.endObserverAction(observe);
175
- });
176
- });
177
- //#endregion
178
- };
179
- if (defaultValue !== void 0) {
180
- //#region setting default value from db
181
- const observe = {
182
- engine,
183
- id: 'setting not rivial default value'
184
- };
185
- TaonStorage.pendingOperatins.push(observe);
186
- (new Promise((resolve, reject) => {
187
- storageEngine.getItem((0, helpers_1.keyDefaultValueAreadySet)(this.onlyInThisComponentClass, memberName), async (err, val) => {
188
- // log.info(`["${memberName}"] was set default value for ? `, val)
189
- if (val) {
190
- await setItemDefaultValue();
191
- resolve();
192
- }
193
- else {
194
- await new Promise((res, rej) => {
195
- storageEngine.setItem((0, helpers_1.keyDefaultValueAreadySet)(this.onlyInThisComponentClass, memberName), true, (err, v) => {
196
- res();
197
- });
198
- });
199
- await new Promise((res, rej) => {
200
- storageEngine.setItem((0, helpers_1.keyValue)(this.onlyInThisComponentClass, memberName), transformTo ? transformTo(defaultValue) : defaultValue, (err, val) => {
201
- res();
202
- });
203
- });
204
- currentValue = defaultValue;
205
- // log.i(`["${memberName}"] defaultValue "${memberName}"`, currentValue)
206
- resolve();
207
- }
208
- });
209
- })).then(() => {
210
- this.endObserverAction(observe);
211
- });
212
- //#endregion
213
- }
214
- else {
215
- setItemDefaultValue();
216
- }
367
+ ensureInit.__memberName = memberName;
217
368
  Object.defineProperty(target, memberName, {
218
- set: (newValue) => {
219
- //#region setting new value on setter
220
- const observe = {
221
- engine,
222
- id: 'setting in SET not rivial default value'
223
- };
224
- TaonStorage.pendingOperatins.push(observe);
225
- (new Promise((resolve, reject) => {
226
- storageEngine.setItem((0, helpers_1.keyValue)(this.onlyInThisComponentClass, memberName), transformTo ? transformTo(newValue) : newValue, (err, savedValue) => {
227
- resolve();
228
- });
229
- })).then(() => {
230
- this.endObserverAction(observe);
369
+ configurable: true,
370
+ enumerable: true,
371
+ get: function () {
372
+ ensureInit(this);
373
+ if (values.has(this))
374
+ return values.get(this);
375
+ if (options.defaultValue !== undefined)
376
+ return options.defaultValue;
377
+ return undefined;
378
+ },
379
+ set: function (newValue) {
380
+ values.set(this, newValue);
381
+ // if this is the first interaction, init will happen anyway
382
+ ensureInit(this);
383
+ const op = StorPending.start(target?.engine ?? 'localstorage', 'set');
384
+ const scope = scopeClass;
385
+ const kVal = keyValue(scope, memberName);
386
+ const toDb = options.transformTo
387
+ ? options.transformTo(newValue)
388
+ : newValue;
389
+ Promise.resolve()
390
+ .then(() => target)
391
+ .then(() => this)
392
+ .then(() => this)
393
+ .then(async () => {
394
+ // If we are SSR + browser engine => no-op
395
+ if (!isBrowser && options)
396
+ return;
397
+ await options; // no-op line to keep TS happy about chaining in some builds
398
+ })
399
+ .catch(() => {
400
+ // ignore
231
401
  });
232
- //#endregion
233
- currentValue = newValue;
402
+ // do real store write (async)
403
+ Promise.resolve()
404
+ .then(async () => {
405
+ // SSR guard for browser engines
406
+ if (!isBrowser && StorPropertyInLocalStorage) {
407
+ return;
408
+ }
409
+ await thisStoreForEngineWrite(this, kVal, toDb);
410
+ })
411
+ .catch(() => {
412
+ // ignore
413
+ })
414
+ .finally(() => StorPending.done(op));
234
415
  },
235
- get: () => currentValue,
236
416
  });
417
+ // small helper to keep closure clean
418
+ const builderStore = this.store;
419
+ const builderEngine = this.engine;
420
+ async function thisStoreForEngineWrite(_instance, key, value) {
421
+ // If browser engines but not browser, skip.
422
+ if (!isBrowser &&
423
+ (builderEngine === 'localstorage' || builderEngine === 'indexeddb'))
424
+ return;
425
+ await builderStore.setItem(key, value);
426
+ }
237
427
  };
238
- };
428
+ }
429
+ /* optional node-only engines (same builder) */
430
+ file(filePath) {
431
+ this.engine = 'file';
432
+ this.filePath = filePath;
433
+ this.useJsonFile = false;
434
+ this.store = new FileStor(filePath, false);
435
+ return this;
436
+ }
437
+ jsonFile(filePath) {
438
+ this.engine = 'json';
439
+ this.filePath = filePath;
440
+ this.useJsonFile = true;
441
+ this.store = new FileStor(filePath, true);
442
+ return this;
443
+ }
444
+ }
445
+ /* ---------------------------
446
+ * Public: clean API exports
447
+ * -------------------------- */
448
+ const localStorageStore = isBrowser
449
+ ? new BrowserLocalStorageStore()
450
+ : new NoopStore();
451
+ const indexedDbStore = isBrowser
452
+ ? new BrowserIndexedDbStore()
453
+ : new NoopStore();
454
+ class StorPropertyInLocalStorage {
455
+ static for(scopeClass) {
456
+ return new StorPropertyBuilder('localstorage', localStorageStore).for(scopeClass);
457
+ }
458
+ }
459
+ exports.StorPropertyInLocalStorage = StorPropertyInLocalStorage;
460
+ class StorPropertyInIndexedDb {
461
+ static for(scopeClass) {
462
+ return new StorPropertyBuilder('indexeddb', indexedDbStore).for(scopeClass);
463
+ }
464
+ }
465
+ exports.StorPropertyInIndexedDb = StorPropertyInIndexedDb;
466
+ /**
467
+ * Helpers
468
+ */
469
+ async function uncache(onlyInThisComponentClass, propertyValueToDeleteFromCache) {
470
+ const scope = onlyInThisComponentClass || { name: '__GLOBAL_NAMESPACE__' };
471
+ const prop = String(propertyValueToDeleteFromCache);
472
+ await Promise.all([
473
+ localStorageStore.removeItem(keyValue(scope, prop)),
474
+ localStorageStore.removeItem(keyDefaultValueAlreadySet(scope, prop)),
475
+ indexedDbStore.removeItem(keyValue(scope, prop)),
476
+ indexedDbStore.removeItem(keyDefaultValueAlreadySet(scope, prop)),
477
+ ]);
478
+ }
479
+ /**
480
+ * Backwards-compatible facade:
481
+ * Stor.property.in.localstorage.for(...).withDefaultValue(...)
482
+ */
483
+ class TaonStorageFacade {
484
+ static async awaitPendingOperatios() {
485
+ await StorPending.awaitPendingOperations();
486
+ }
487
+ static get property() {
488
+ return {
489
+ in: {
490
+ get localstorage() {
491
+ return new StorPropertyBuilder('localstorage', localStorageStore);
492
+ },
493
+ get indexedb() {
494
+ return new StorPropertyBuilder('indexeddb', indexedDbStore);
495
+ },
496
+ // node-only (safe: dynamic import inside FileStor)
497
+ file(filePath) {
498
+ return new StorPropertyBuilder('file', new FileStor(filePath, false));
499
+ },
500
+ jsonFile(filePath) {
501
+ return new StorPropertyBuilder('json', new FileStor(filePath, true));
502
+ },
503
+ },
504
+ };
505
+ }
239
506
  }
240
- exports.Stor = TaonStorage;
507
+ exports.Stor = TaonStorageFacade;
241
508
  //# sourceMappingURL=storage.js.map