@asaidimu/utils-persistence 2.0.4 → 2.2.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/index.d.mts CHANGED
@@ -1,59 +1,46 @@
1
- import { S as SimplePersistence } from '../types-dsQOAvmQ.js';
2
- export { a as StorageEvents, b as author } from '../types-dsQOAvmQ.js';
1
+ import { S as SimplePersistence, a as StoreConfig } from '../types-ZDD-bdCz.js';
2
+ export { b as StorageEvents, c as author } from '../types-ZDD-bdCz.js';
3
3
 
4
4
  /**
5
- * Implements SimplePersistence using web storage (localStorage or sessionStorage).
6
- * Supports cross-tab synchronization via an event bus and native storage events when using localStorage.
5
+ * Configuration options specific to the WebStoragePersistence adapter.
7
6
  */
8
- declare class WebStoragePersistence<T extends object> implements SimplePersistence<T> {
9
- private readonly storageKey;
10
- private readonly eventBus;
11
- private readonly storage;
7
+ interface WebStoragePersistenceConfig {
12
8
  /**
13
- * Initializes a new instance of WebStoragePersistence.
14
- * @param storageKey The key under which data is stored in web storage (e.g., 'user-profile').
15
- * @param session Optional flag; if true, uses sessionStorage instead of localStorage (default: false).
9
+ * The key under which data is stored in web storage (e.g., 'user-profile').
16
10
  */
17
- constructor(storageKey: string, session?: boolean);
11
+ storageKey: string;
18
12
  /**
19
- * Initializes the event bus with configured settings.
20
- * @returns Configured event bus instance.
13
+ * If true, uses sessionStorage instead of localStorage. Defaults to false.
21
14
  */
15
+ session?: boolean;
16
+ }
17
+ /**
18
+ * Implements SimplePersistence using web storage (localStorage or sessionStorage).
19
+ * Supports cross-tab synchronization and data versioning with upgrade handlers.
20
+ */
21
+ declare class WebStoragePersistence<T> implements SimplePersistence<T> {
22
+ private readonly eventBus;
23
+ private readonly storage;
24
+ private readonly config;
25
+ constructor(config: StoreConfig<T> & WebStoragePersistenceConfig);
26
+ private initialize;
22
27
  private initializeEventBus;
23
- /**
24
- * Sets up a listener for native storage events to synchronize across tabs (localStorage only).
25
- */
28
+ private getStoreName;
26
29
  private setupStorageEventListener;
27
- /**
28
- * Persists the provided state to web storage and notifies subscribers.
29
- * @param instanceId Unique identifier of the instance making the update.
30
- * @param state The state to persist.
31
- * @returns True if successful, false if an error occurs.
32
- */
33
30
  set(instanceId: string, state: T): boolean;
34
- /**
35
- * Retrieves the current state from web storage.
36
- * @returns The persisted state, or null if not found or invalid.
37
- */
38
31
  get(): T | null;
39
- /**
40
- * Subscribes to updates in the persisted state, excluding the instance’s own changes.
41
- * @param instanceId Unique identifier of the subscribing instance.
42
- * @param onStateChange Callback to invoke with the updated state.
43
- * @returns Function to unsubscribe from updates.
44
- */
45
32
  subscribe(instanceId: string, onStateChange: (state: T) => void): () => void;
46
- /**
47
- * Removes the persisted state from web storage.
48
- * @returns True if successful, false if an error occurs.
49
- */
50
33
  clear(): boolean;
34
+ stats(): {
35
+ version: string;
36
+ id: string;
37
+ };
51
38
  }
52
39
 
53
40
  /**
54
41
  * Configuration for database connections
55
42
  */
56
- interface DatabaseConfig {
43
+ interface IndexedDBPersistenceConfig {
57
44
  store: string;
58
45
  database: string;
59
46
  collection: string;
@@ -67,16 +54,26 @@ declare class IndexedDBPersistence<T> implements SimplePersistence<T> {
67
54
  private collectionPromise;
68
55
  private config;
69
56
  private eventBus;
70
- constructor(config: DatabaseConfig);
57
+ private initialized;
58
+ private initializationCallbacks;
59
+ private getStoreName;
60
+ constructor(config: StoreConfig<T> & IndexedDBPersistenceConfig);
61
+ private initialize;
62
+ private _onInitialized;
71
63
  private getCollection;
72
64
  set(id: string, state: T): Promise<boolean>;
65
+ private _get;
73
66
  get(): Promise<T | null>;
74
67
  subscribe(id: string, callback: (state: T) => void): () => void;
75
68
  clear(): Promise<boolean>;
69
+ stats(): {
70
+ version: string;
71
+ id: string;
72
+ };
76
73
  /**
77
74
  * Close a specific database
78
75
  */
79
76
  close(): Promise<void>;
80
77
  }
81
78
 
82
- export { IndexedDBPersistence, SimplePersistence, WebStoragePersistence };
79
+ export { IndexedDBPersistence, type IndexedDBPersistenceConfig, SimplePersistence, StoreConfig, WebStoragePersistence, type WebStoragePersistenceConfig };
package/index.d.ts CHANGED
@@ -1,59 +1,46 @@
1
- import { S as SimplePersistence } from '../types-dsQOAvmQ.js';
2
- export { a as StorageEvents, b as author } from '../types-dsQOAvmQ.js';
1
+ import { S as SimplePersistence, a as StoreConfig } from '../types-ZDD-bdCz.js';
2
+ export { b as StorageEvents, c as author } from '../types-ZDD-bdCz.js';
3
3
 
4
4
  /**
5
- * Implements SimplePersistence using web storage (localStorage or sessionStorage).
6
- * Supports cross-tab synchronization via an event bus and native storage events when using localStorage.
5
+ * Configuration options specific to the WebStoragePersistence adapter.
7
6
  */
8
- declare class WebStoragePersistence<T extends object> implements SimplePersistence<T> {
9
- private readonly storageKey;
10
- private readonly eventBus;
11
- private readonly storage;
7
+ interface WebStoragePersistenceConfig {
12
8
  /**
13
- * Initializes a new instance of WebStoragePersistence.
14
- * @param storageKey The key under which data is stored in web storage (e.g., 'user-profile').
15
- * @param session Optional flag; if true, uses sessionStorage instead of localStorage (default: false).
9
+ * The key under which data is stored in web storage (e.g., 'user-profile').
16
10
  */
17
- constructor(storageKey: string, session?: boolean);
11
+ storageKey: string;
18
12
  /**
19
- * Initializes the event bus with configured settings.
20
- * @returns Configured event bus instance.
13
+ * If true, uses sessionStorage instead of localStorage. Defaults to false.
21
14
  */
15
+ session?: boolean;
16
+ }
17
+ /**
18
+ * Implements SimplePersistence using web storage (localStorage or sessionStorage).
19
+ * Supports cross-tab synchronization and data versioning with upgrade handlers.
20
+ */
21
+ declare class WebStoragePersistence<T> implements SimplePersistence<T> {
22
+ private readonly eventBus;
23
+ private readonly storage;
24
+ private readonly config;
25
+ constructor(config: StoreConfig<T> & WebStoragePersistenceConfig);
26
+ private initialize;
22
27
  private initializeEventBus;
23
- /**
24
- * Sets up a listener for native storage events to synchronize across tabs (localStorage only).
25
- */
28
+ private getStoreName;
26
29
  private setupStorageEventListener;
27
- /**
28
- * Persists the provided state to web storage and notifies subscribers.
29
- * @param instanceId Unique identifier of the instance making the update.
30
- * @param state The state to persist.
31
- * @returns True if successful, false if an error occurs.
32
- */
33
30
  set(instanceId: string, state: T): boolean;
34
- /**
35
- * Retrieves the current state from web storage.
36
- * @returns The persisted state, or null if not found or invalid.
37
- */
38
31
  get(): T | null;
39
- /**
40
- * Subscribes to updates in the persisted state, excluding the instance’s own changes.
41
- * @param instanceId Unique identifier of the subscribing instance.
42
- * @param onStateChange Callback to invoke with the updated state.
43
- * @returns Function to unsubscribe from updates.
44
- */
45
32
  subscribe(instanceId: string, onStateChange: (state: T) => void): () => void;
46
- /**
47
- * Removes the persisted state from web storage.
48
- * @returns True if successful, false if an error occurs.
49
- */
50
33
  clear(): boolean;
34
+ stats(): {
35
+ version: string;
36
+ id: string;
37
+ };
51
38
  }
52
39
 
53
40
  /**
54
41
  * Configuration for database connections
55
42
  */
56
- interface DatabaseConfig {
43
+ interface IndexedDBPersistenceConfig {
57
44
  store: string;
58
45
  database: string;
59
46
  collection: string;
@@ -67,16 +54,26 @@ declare class IndexedDBPersistence<T> implements SimplePersistence<T> {
67
54
  private collectionPromise;
68
55
  private config;
69
56
  private eventBus;
70
- constructor(config: DatabaseConfig);
57
+ private initialized;
58
+ private initializationCallbacks;
59
+ private getStoreName;
60
+ constructor(config: StoreConfig<T> & IndexedDBPersistenceConfig);
61
+ private initialize;
62
+ private _onInitialized;
71
63
  private getCollection;
72
64
  set(id: string, state: T): Promise<boolean>;
65
+ private _get;
73
66
  get(): Promise<T | null>;
74
67
  subscribe(id: string, callback: (state: T) => void): () => void;
75
68
  clear(): Promise<boolean>;
69
+ stats(): {
70
+ version: string;
71
+ id: string;
72
+ };
76
73
  /**
77
74
  * Close a specific database
78
75
  */
79
76
  close(): Promise<void>;
80
77
  }
81
78
 
82
- export { IndexedDBPersistence, SimplePersistence, WebStoragePersistence };
79
+ export { IndexedDBPersistence, type IndexedDBPersistenceConfig, SimplePersistence, StoreConfig, WebStoragePersistence, type WebStoragePersistenceConfig };
package/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("@asaidimu/indexed"),t=Object.create,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,i=(e,t)=>function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports},c=(e,i,c)=>(c=null!=e?t(s(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))a.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(i=n(t,c))||i.enumerable});return e})(e&&e.__esModule?c:r(c,"default",{value:e,enumerable:!0}),e)),l=i({"node_modules/@asaidimu/events/index.js"(e,t){var r,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(i,{createEventBus:()=>c}),t.exports=(r=i,((e,t,r,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))a.call(e,c)||c===r||n(e,c,{get:()=>t[c],enumerable:!(i=o(t,c))||i.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let r=[],n=0,o=0;const s=new Map,a=new Map;let i=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?i=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{n++,o+=t,s.set(e,(s.get(e)||0)+1)},l=()=>{const t=r;r=[],t.forEach((({name:t,payload:r})=>{const n=performance.now();try{(a.get(t)||[]).forEach((e=>e(r)))}catch(n){e.errorHandler({...n,eventName:t,payload:r})}c(t,performance.now()-n)}))},u=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),f=e=>{const r=t.get(e);r?a.set(e,Array.from(r)):a.delete(e)};return i&&(i.onmessage=e=>{const{name:t,payload:r}=e.data;(a.get(t)||[]).forEach((e=>e(r)))}),{subscribe:(e,r)=>{t.has(e)||t.set(e,new Set);const n=t.get(e);return n.add(r),f(e),()=>{n.delete(r),0===n.size?(t.delete(e),a.delete(e)):f(e)}},emit:({name:t,payload:n})=>{if(e.async)return r.push({name:t,payload:n}),r.length>=e.batchSize?l():u(),void(i&&i.postMessage({name:t,payload:n}));const o=performance.now();try{(a.get(t)||[]).forEach((e=>e(n))),i&&i.postMessage({name:t,payload:n})}catch(r){e.errorHandler({...r,eventName:t,payload:n})}c(t,performance.now()-o)},getMetrics:()=>({totalEvents:n,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:s,averageEmitDuration:n>0?o/n:0}),clear:()=>{t.clear(),a.clear(),r=[],n=0,o=0,s.clear(),i&&(i.close(),i=null)}}}}}),u=i({"node_modules/@asaidimu/query/index.js"(e,t){var r,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(i,{QueryBuilder:()=>c,createJoiner:()=>g,createMatcher:()=>u,createPaginator:()=>O,createProjector:()=>q,createSorter:()=>j}),t.exports=(r=i,((e,t,r,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))!a.call(e,c)&&c!==r&&n(e,c,{get:()=>t[c],enumerable:!(i=o(t,c))||i.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=class{query;constructor(){this.query={}}where(e){return this.query.filters=e,this}orderBy(e,t){return this.query.sort||(this.query.sort=[]),this.query.sort.push({field:e,direction:t}),this}offset(e,t){return this.query.pagination={type:"offset",offset:e,limit:t},this}cursor(e,t,r){return this.query.pagination={type:"cursor",cursor:e,limit:t,direction:r},this}include(e){return this.query.projection||(this.query.projection={}),this.query.projection.include=e,this}exclude(e){return this.query.projection||(this.query.projection={}),this.query.projection.exclude=e,this}computed(e,t){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"computed",expression:e,alias:t}),this}case(e,t,r){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"case",conditions:e,else:t,alias:r}),this}join(e,t,r){return this.query.joins||(this.query.joins=[]),this.query.joins.push({relation:e,alias:r,query:t}),this}aggregate(e,t){return this.query.aggregations={groupBy:e,metrics:t},this}window(e){return this.query.window||(this.query.window=[]),this.query.window.push(e),this}hint(e){return this.query.hints||(this.query.hints=[]),this.query.hints.push(e),this}build(){return this.query}};function l(e){function t(e,t){return function(e){return"field"===e?.type}(t)?e[t.field]:function(e){return"value"===e?.type}(t)?t.value:function(e){return"function"===e?.type}(t)?n(t,e):function(e){return"computed"===e?.type}(t)?n(t.expression,e):function(e){return"case"===e?.type}(t)?function(e,t){for(let r of t.conditions)if(o(e,r.when))return r.then;return t.else}(e,t):t}let r=new Map([["and",(e,t)=>t.every((t=>o(e,t)))],["or",(e,t)=>t.some((t=>o(e,t)))],["not",(e,t)=>!t.every((t=>o(e,t)))],["nor",(e,t)=>!t.some((t=>o(e,t)))],["xor",(e,t)=>1===t.filter((t=>o(e,t))).length]]);function n(r,n){let o=r.arguments.map((e=>t(n,e)));if(e[r.function])return e[r.function](...o);throw new Error(`Function ${r.function} not found!`)}function o(n,o){if(function(e){return!!e&&void 0!==e.conditions}(o))return function(e,t){let{operator:n,conditions:o}=t,s=r.get(n);if(s)return s(e,o);throw new Error(`Unsupported logical operator: ${n}`)}(n,o);if(!o||!o.field)return!1;let{field:s,operator:a,value:i}=o,c=n[s],l=t(n,i),u=new Map([["eq",(e,t)=>e===t],["neq",(e,t)=>e!==t],["lt",(e,t)=>e<t],["lte",(e,t)=>e<=t],["gt",(e,t)=>e>t],["gte",(e,t)=>e>=t],["in",(e,t)=>Array.isArray(t)&&t.includes(e)],["nin",(e,t)=>Array.isArray(t)&&!t.includes(e)],["contains",(e,t)=>"string"==typeof e?e.includes(t):!!Array.isArray(e)&&e.includes(i)],["ncontains",(e,t)=>"string"==typeof e&&!e.includes(t)],["startswith",(e,t)=>"string"==typeof e&&e.startsWith(t)],["endswith",(e,t)=>"string"==typeof e&&e.endsWith(t)],["exists",e=>null!=e],["nexists",e=>null==e]]),f=e[a]||u.get(a);if(f)return f(c,l);throw new Error(`Unsupported comparison operator: ${a}`)}return{resolve:t,evaluate:o}}function u(e){let{evaluate:t}=l(e),r=new WeakMap;function n(e,n){let o=r.get(e);o||(o=new Map,r.set(e,o));let s=JSON.stringify(n);if(o.has(s))return o.get(s);let a=t(e,n);return o.set(s,a),a}return{matcher:n,match:n}}var f=class extends Error{constructor(e,t){super(e),this.code=t,this.name="JoinError"}},d=e=>e&&"field"in e&&"operator"in e&&"value"in e,h=(e,t)=>{if(e){if(d(e)&&e){let r=(e=>"object"==typeof e&&null!==e&&"type"in e&&"field"===e.type)(e.value)?((e,t)=>t.split(".").reduce(((e,t)=>e?.[t]),e))(t,e.value.field):e.value;return{...e,value:r}}if((e=>"operator"in e&&"conditions"in e)(e)){let r={...e};return e.conditions&&(r.conditions=e.conditions.map((e=>h(e,t)))),r}return e}},p=async(e,t,r,n)=>{try{if(((e,t)=>{if(!e.relation)throw new f("Join configuration must specify a relation","INVALID_CONFIG");if(!t[e.relation])throw new f(`Collection "${e.relation}" not found in database`,"COLLECTION_NOT_FOUND");if(e.alias&&"string"!=typeof e.alias)throw new f("Join alias must be a string","INVALID_ALIAS")})(r,e),!Array.isArray(t))throw new f("Source data must be an array","INVALID_SOURCE_DATA");let o,s=e[r.relation];return r.query?.filters&&d(r.query.filters)&&(o=((e,t)=>{let r=new Map;return e.forEach((e=>{let n=e[t];r.has(n)||r.set(n,[]),r.get(n).push(e)})),r})(s,r.query.filters.field)),(await Promise.all(t.map((async e=>{let t,a=((e,t)=>{if(!e)return{};let r=h(e.filters,t);return{...e,filters:r}})(r.query,e);return t=a.filters&&d(a.filters)&&o?.has(a.filters.value)?o.get(a.filters.value)||[]:s.filter((e=>n.matcher(e,a.filters))),((e,t,r)=>{let n=r.alias||r.relation;return[{...e,[n]:t}]})(e,await[e=>a.sort?n.sorter(e,a.sort):e,e=>a.projection?n.projector(e,a.projection):e,async e=>a.pagination?await n.paginator(e,a.pagination):e].reduce((async(e,t)=>t(await e)),Promise.resolve(t)),r)})))).flat()}catch(e){throw e instanceof f?e:new f(`Join operation failed: ${e.message}`,"JOIN_EXECUTION_ERROR")}},y=async(e,t,r,n)=>r.reduce((async(t,r)=>p(e,await t,r,n)),Promise.resolve(t));function g(){return{join:y}}var m=class extends Error{constructor(e,t){super(`Unsupported comparison between ${typeof e} and ${typeof t}`),this.name="UnsupportedComparisonError"}},b=class extends Error{constructor(e){super(`Unsupported sort direction: ${e}`),this.name="InvalidSortDirectionError"}};function w(e,t,r){if(e===t)return 0;if(null==e||null==t)return null==e?"asc"===r?-1:1:"asc"===r?1:-1;if("string"==typeof e&&"string"==typeof t)return"asc"===r?e.localeCompare(t):t.localeCompare(e);if("number"==typeof e&&"number"==typeof t)return"asc"===r?e-t:t-e;throw new m(e,t)}function v(e,t){let r=Array.from(e);return 0===t.length?r:r.sort(((e,r)=>{for(let n of t){let{field:t,direction:o}=n,s=e[t],a=r[t];try{if("asc"!==o&&"desc"!==o)throw new b(o);let e=w(s,a,o);if(0!==e)return e}catch(e){throw e instanceof m||e instanceof b?e:new Error(`Error comparing field '${t}': ${e.message}`)}}return 0}))}function j(){return{sort:v}}function q(e){let{resolve:t}=l(e);function r(e,n){let o={};return n.include?.length&&function(e,t,n){for(let o of t)if("string"!=typeof o){for(let[t,s]of Object.entries(o))if(Object.prototype.hasOwnProperty.call(e,t)){let o=r(e[t],s);n[t]=o}}else{let t=o;n[t]=e[t]}}(e,n.include,o),n.exclude?.length&&function(e,t,n){0===Object.keys(n).length&&Object.assign(n,e);for(let e of t)if("string"!=typeof e)for(let[t,o]of Object.entries(e)){if(!Object.prototype.hasOwnProperty.call(n,t))continue;let e=n[t];e&&"object"==typeof e?n[t]=r(e,o):delete n[t]}else delete n[e]}(e,n.exclude,o),n.computed?.length&&function(e,r,n){for(let o of r)n[o.alias]=t(e,o)}(e,n.computed,o),o}return{project:r}}async function*E(e,t,r=e=>String(e)){"offset"===t.type?yield*async function*(e,t){let{offset:r,limit:n}=t,o=0,s=n,a=[];for await(let t of e)s<=0&&(yield a,a=[],s=n),o<r?o++:(a.push(t),s--);a.length>0&&(yield a)}(e,t):yield*async function*(e,t,r){let{cursor:n,limit:o,direction:s}=t,a=o,i=void 0===n,c=[];if("forward"===s)for await(let t of e)a<=0&&(yield c,c=[],a=o),i?(c.push(t),a--):i=r(t)===n;else{let t=[];for await(let r of e)t.push(r);for(let e=t.length-1;e>=0;e--){let s=t[e];i?(c.push(s),a--,a<=0&&(yield c,c=[],a=o)):i=r(s)===n}}c.length>0&&(yield c)}(e,t,r)}function O(){return{paginate:E}}}}),f=c(l()),d=c(l()),h=c(u()),p=class t{static dbInstances=new Map;static collectionInstances=new Map;static eventBusMap=new Map;static defaultModelName="stores";static getDatabase(r){const{database:n,enableTelemetry:o=!1,collection:s=t.defaultModelName}=r;if(!t.dbInstances.has(n)){const r=e.DatabaseConnection({name:n,enableTelemetry:o}).then((async t=>{try{await t.createCollection({name:s,version:"1.0.0",nestedSchemas:{},fields:{store:{name:"store",type:"string",required:!0},data:{name:"data",type:"object",required:!0}}})}catch(t){if(t instanceof e.DatabaseError&&"SCHEMA_ALREADY_EXISTS"!==t.type)throw t}return t}));t.dbInstances.set(n,r)}return t.dbInstances.get(n)}static getEventBus(e,r){const n=`${e}_store_${r}`;return t.eventBusMap.has(n)||t.eventBusMap.set(n,(0,d.createEventBus)({batchSize:5,async:!0,batchDelay:16,errorHandler:t=>console.error(`Event bus error for ${e}:${r}:`,t),crossTab:!0,channelName:n})),t.eventBusMap.get(n)}static getCollection(e){const{database:r,collection:n=t.defaultModelName}=e,o=`${r}:${n}`;if(!t.collectionInstances.has(o)){const r=t.getDatabase(e).then((e=>e.collection(n)));t.collectionInstances.set(o,r)}return t.collectionInstances.get(o)}static async closeDatabase(e){const r=t.dbInstances.get(e);if(r){(await r).close(),t.dbInstances.delete(e);const n=[];t.collectionInstances.forEach(((t,r)=>{r.startsWith(`${e}:`)&&n.push(r)})),n.forEach((e=>t.collectionInstances.delete(e)));const o=[];t.eventBusMap.forEach(((t,r)=>{r.startsWith(`${e}_store_`)&&(t.clear(),o.push(r))})),o.forEach((e=>t.eventBusMap.delete(e)))}}static async closeAll(){const e=Array.from(t.dbInstances.keys()).map((e=>t.closeDatabase(e)));await Promise.all(e)}static getActiveDatabases(){return Array.from(t.dbInstances.keys())}};exports.IndexedDBPersistence=class{collection=null;collectionPromise;config;eventBus;constructor(e){this.config=e,this.collectionPromise=p.getCollection(this.config),this.collectionPromise.then((e=>{this.collection=e})).catch((e=>{console.error(`Failed to initialize collection for store ${this.config.store}:`,e)})),this.eventBus=p.getEventBus(this.config.database,this.config.store)}async getCollection(){return this.collection?this.collection:this.collectionPromise}async set(e,t){try{const r=await this.getCollection(),n=(new h.QueryBuilder).where({field:"store",operator:"eq",value:this.config.store}).build(),o=await r.find(n.filters),s={store:this.config.store,data:t};let a;return o?a=await o.update(s):(await r.create(s),a=!0),a&&this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.store,instanceId:e,state:t}}),a}catch(t){return console.error(`Failed to set state for store ${this.config.store} in database ${this.config.database} by instance ${e}:`,t),!1}}async get(){try{const e=await this.getCollection(),t=(new h.QueryBuilder).where({field:"store",operator:"eq",value:this.config.store}).build(),r=await e.find(t.filters);return r?r.read().then((()=>r.data)):null}catch(e){return console.error(`Failed to get state for store ${this.config.store} in database ${this.config.database}:`,e),null}}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:n,state:o})=>{r===this.config.store&&n!==e&&t(o)}))}async clear(){try{const e=await this.collectionPromise,t=(new h.QueryBuilder).where({field:"store",operator:"eq",value:this.config.store}).build(),r=await e.find(t.filters);return!r||await r.delete()}catch(e){return console.error(`Failed to clear state for store ${this.config.store} in database ${this.config.database}:`,e),!1}}async close(){await p.closeDatabase(this.config.database)}},exports.WebStoragePersistence=class{storageKey;eventBus;storage;constructor(e,t=!1){this.storageKey=e,this.storage=t?sessionStorage:localStorage,this.eventBus=this.initializeEventBus(),t||this.setupStorageEventListener()}initializeEventBus(){const e={async:!0,batchSize:5,batchDelay:16,errorHandler:e=>console.error(`Event bus error for ${this.storageKey}:`,e),crossTab:!0,channelName:`storage_${this.storageKey}`};return(0,f.createEventBus)(e)}setupStorageEventListener(){window.addEventListener("storage",(e=>{if(e.key===this.storageKey&&e.newValue)try{const t=JSON.parse(e.newValue);this.eventBus.emit({name:"store:updated",payload:{storageKey:this.storageKey,instanceId:"external",state:t}})}catch(e){console.error("Failed to parse storage event data:",e)}}))}set(e,t){try{const r=JSON.stringify(t);return this.storage.setItem(this.storageKey,r),this.eventBus.emit({name:"store:updated",payload:{storageKey:this.storageKey,instanceId:e,state:t}}),!0}catch(e){return console.error(`Failed to persist state to web storage for ${this.storageKey}:`,e),!1}}get(){try{const e=this.storage.getItem(this.storageKey);return e?JSON.parse(e):null}catch(e){return console.error(`Failed to retrieve state from web storage for ${this.storageKey}:`,e),null}}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:n,state:o})=>{r===this.storageKey&&n!==e&&t(o)}))}clear(){try{return this.storage.removeItem(this.storageKey),!0}catch(e){return console.error(`Failed to clear persisted state for ${this.storageKey}:`,e),!1}}},exports.author="https://github.com/asaidimu";
1
+ "use strict";var e=require("@asaidimu/indexed"),t=Object.create,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,o=Object.getPrototypeOf,s=Object.prototype.hasOwnProperty,a=(e,t)=>function(){return t||(0,e[i(e)[0]])((t={exports:{}}).exports,t),t.exports},c=(e,a,c)=>(c=null!=e?t(o(e)):{},((e,t,o,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of i(t))s.call(e,c)||c===o||r(e,c,{get:()=>t[c],enumerable:!(a=n(t,c))||a.enumerable});return e})(e&&e.__esModule?c:r(c,"default",{value:e,enumerable:!0}),e)),l=a({"node_modules/@asaidimu/events/index.js"(e,t){var r,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(a,{createEventBus:()=>c}),t.exports=(r=a,((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))s.call(e,c)||c===r||n(e,c,{get:()=>t[c],enumerable:!(a=i(t,c))||a.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let r=[],n=0,i=0;const o=new Map,s=new Map;let a=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?a=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{n++,i+=t,o.set(e,(o.get(e)||0)+1)},l=()=>{const t=r;r=[],t.forEach((({name:t,payload:r})=>{const n=performance.now();try{(s.get(t)||[]).forEach((e=>e(r)))}catch(n){e.errorHandler({...n,eventName:t,payload:r})}c(t,performance.now()-n)}))},u=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),p=e=>{const r=t.get(e);r?s.set(e,Array.from(r)):s.delete(e)};return a&&(a.onmessage=e=>{const{name:t,payload:r}=e.data;(s.get(t)||[]).forEach((e=>e(r)))}),{subscribe:(e,r)=>{t.has(e)||t.set(e,new Set);const n=t.get(e);return n.add(r),p(e),()=>{n.delete(r),0===n.size?(t.delete(e),s.delete(e)):p(e)}},emit:({name:t,payload:n})=>{if(e.async)return r.push({name:t,payload:n}),r.length>=e.batchSize?l():u(),void(a&&a.postMessage({name:t,payload:n}));const i=performance.now();try{(s.get(t)||[]).forEach((e=>e(n))),a&&a.postMessage({name:t,payload:n})}catch(r){e.errorHandler({...r,eventName:t,payload:n})}c(t,performance.now()-i)},getMetrics:()=>({totalEvents:n,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:o,averageEmitDuration:n>0?i/n:0}),clear:()=>{t.clear(),s.clear(),r=[],n=0,i=0,o.clear(),a&&(a.close(),a=null)}}}}}),u=a({"node_modules/@asaidimu/query/index.js"(e,t){var r,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(a,{QueryBuilder:()=>c,createJoiner:()=>g,createMatcher:()=>u,createPaginator:()=>E,createProjector:()=>q,createSorter:()=>j}),t.exports=(r=a,((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))!s.call(e,c)&&c!==r&&n(e,c,{get:()=>t[c],enumerable:!(a=i(t,c))||a.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=class{query;constructor(){this.query={}}where(e){return this.query.filters=e,this}orderBy(e,t){return this.query.sort||(this.query.sort=[]),this.query.sort.push({field:e,direction:t}),this}offset(e,t){return this.query.pagination={type:"offset",offset:e,limit:t},this}cursor(e,t,r){return this.query.pagination={type:"cursor",cursor:e,limit:t,direction:r},this}include(e){return this.query.projection||(this.query.projection={}),this.query.projection.include=e,this}exclude(e){return this.query.projection||(this.query.projection={}),this.query.projection.exclude=e,this}computed(e,t){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"computed",expression:e,alias:t}),this}case(e,t,r){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"case",conditions:e,else:t,alias:r}),this}join(e,t,r){return this.query.joins||(this.query.joins=[]),this.query.joins.push({relation:e,alias:r,query:t}),this}aggregate(e,t){return this.query.aggregations={groupBy:e,metrics:t},this}window(e){return this.query.window||(this.query.window=[]),this.query.window.push(e),this}hint(e){return this.query.hints||(this.query.hints=[]),this.query.hints.push(e),this}build(){return this.query}};function l(e){function t(e,t){return function(e){return"field"===e?.type}(t)?e[t.field]:function(e){return"value"===e?.type}(t)?t.value:function(e){return"function"===e?.type}(t)?n(t,e):function(e){return"computed"===e?.type}(t)?n(t.expression,e):function(e){return"case"===e?.type}(t)?function(e,t){for(let r of t.conditions)if(i(e,r.when))return r.then;return t.else}(e,t):t}let r=new Map([["and",(e,t)=>t.every((t=>i(e,t)))],["or",(e,t)=>t.some((t=>i(e,t)))],["not",(e,t)=>!t.every((t=>i(e,t)))],["nor",(e,t)=>!t.some((t=>i(e,t)))],["xor",(e,t)=>1===t.filter((t=>i(e,t))).length]]);function n(r,n){let i=r.arguments.map((e=>t(n,e)));if(e[r.function])return e[r.function](...i);throw new Error(`Function ${r.function} not found!`)}function i(n,i){if(function(e){return!!e&&void 0!==e.conditions}(i))return function(e,t){let{operator:n,conditions:i}=t,o=r.get(n);if(o)return o(e,i);throw new Error(`Unsupported logical operator: ${n}`)}(n,i);if(!i||!i.field)return!1;let{field:o,operator:s,value:a}=i,c=n[o],l=t(n,a),u=new Map([["eq",(e,t)=>e===t],["neq",(e,t)=>e!==t],["lt",(e,t)=>e<t],["lte",(e,t)=>e<=t],["gt",(e,t)=>e>t],["gte",(e,t)=>e>=t],["in",(e,t)=>Array.isArray(t)&&t.includes(e)],["nin",(e,t)=>Array.isArray(t)&&!t.includes(e)],["contains",(e,t)=>"string"==typeof e?e.includes(t):!!Array.isArray(e)&&e.includes(a)],["ncontains",(e,t)=>"string"==typeof e&&!e.includes(t)],["startswith",(e,t)=>"string"==typeof e&&e.startsWith(t)],["endswith",(e,t)=>"string"==typeof e&&e.endsWith(t)],["exists",e=>null!=e],["nexists",e=>null==e]]),p=e[s]||u.get(s);if(p)return p(c,l);throw new Error(`Unsupported comparison operator: ${s}`)}return{resolve:t,evaluate:i}}function u(e){let{evaluate:t}=l(e),r=new WeakMap;function n(e,n){let i=r.get(e);i||(i=new Map,r.set(e,i));let o=JSON.stringify(n);if(i.has(o))return i.get(o);let s=t(e,n);return i.set(o,s),s}return{matcher:n,match:n}}var p=class extends Error{constructor(e,t){super(e),this.code=t,this.name="JoinError"}},h=e=>e&&"field"in e&&"operator"in e&&"value"in e,f=(e,t)=>{if(e){if(h(e)&&e){let r=(e=>"object"==typeof e&&null!==e&&"type"in e&&"field"===e.type)(e.value)?((e,t)=>t.split(".").reduce(((e,t)=>e?.[t]),e))(t,e.value.field):e.value;return{...e,value:r}}if((e=>"operator"in e&&"conditions"in e)(e)){let r={...e};return e.conditions&&(r.conditions=e.conditions.map((e=>f(e,t)))),r}return e}},d=async(e,t,r,n)=>{try{if(((e,t)=>{if(!e.relation)throw new p("Join configuration must specify a relation","INVALID_CONFIG");if(!t[e.relation])throw new p(`Collection "${e.relation}" not found in database`,"COLLECTION_NOT_FOUND");if(e.alias&&"string"!=typeof e.alias)throw new p("Join alias must be a string","INVALID_ALIAS")})(r,e),!Array.isArray(t))throw new p("Source data must be an array","INVALID_SOURCE_DATA");let i,o=e[r.relation];return r.query?.filters&&h(r.query.filters)&&(i=((e,t)=>{let r=new Map;return e.forEach((e=>{let n=e[t];r.has(n)||r.set(n,[]),r.get(n).push(e)})),r})(o,r.query.filters.field)),(await Promise.all(t.map((async e=>{let t,s=((e,t)=>{if(!e)return{};let r=f(e.filters,t);return{...e,filters:r}})(r.query,e);return t=s.filters&&h(s.filters)&&i?.has(s.filters.value)?i.get(s.filters.value)||[]:o.filter((e=>n.matcher(e,s.filters))),((e,t,r)=>{let n=r.alias||r.relation;return[{...e,[n]:t}]})(e,await[e=>s.sort?n.sorter(e,s.sort):e,e=>s.projection?n.projector(e,s.projection):e,async e=>s.pagination?await n.paginator(e,s.pagination):e].reduce((async(e,t)=>t(await e)),Promise.resolve(t)),r)})))).flat()}catch(e){throw e instanceof p?e:new p(`Join operation failed: ${e.message}`,"JOIN_EXECUTION_ERROR")}},y=async(e,t,r,n)=>r.reduce((async(t,r)=>d(e,await t,r,n)),Promise.resolve(t));function g(){return{join:y}}var m=class extends Error{constructor(e,t){super(`Unsupported comparison between ${typeof e} and ${typeof t}`),this.name="UnsupportedComparisonError"}},b=class extends Error{constructor(e){super(`Unsupported sort direction: ${e}`),this.name="InvalidSortDirectionError"}};function w(e,t,r){if(e===t)return 0;if(null==e||null==t)return null==e?"asc"===r?-1:1:"asc"===r?1:-1;if("string"==typeof e&&"string"==typeof t)return"asc"===r?e.localeCompare(t):t.localeCompare(e);if("number"==typeof e&&"number"==typeof t)return"asc"===r?e-t:t-e;throw new m(e,t)}function v(e,t){let r=Array.from(e);return 0===t.length?r:r.sort(((e,r)=>{for(let n of t){let{field:t,direction:i}=n,o=e[t],s=r[t];try{if("asc"!==i&&"desc"!==i)throw new b(i);let e=w(o,s,i);if(0!==e)return e}catch(e){throw e instanceof m||e instanceof b?e:new Error(`Error comparing field '${t}': ${e.message}`)}}return 0}))}function j(){return{sort:v}}function q(e){let{resolve:t}=l(e);function r(e,n){let i={};return n.include?.length&&function(e,t,n){for(let i of t)if("string"!=typeof i){for(let[t,o]of Object.entries(i))if(Object.prototype.hasOwnProperty.call(e,t)){let i=r(e[t],o);n[t]=i}}else{let t=i;n[t]=e[t]}}(e,n.include,i),n.exclude?.length&&function(e,t,n){0===Object.keys(n).length&&Object.assign(n,e);for(let e of t)if("string"!=typeof e)for(let[t,i]of Object.entries(e)){if(!Object.prototype.hasOwnProperty.call(n,t))continue;let e=n[t];e&&"object"==typeof e?n[t]=r(e,i):delete n[t]}else delete n[e]}(e,n.exclude,i),n.computed?.length&&function(e,r,n){for(let i of r)n[i.alias]=t(e,i)}(e,n.computed,i),i}return{project:r}}async function*S(e,t,r=e=>String(e)){"offset"===t.type?yield*async function*(e,t){let{offset:r,limit:n}=t,i=0,o=n,s=[];for await(let t of e)o<=0&&(yield s,s=[],o=n),i<r?i++:(s.push(t),o--);s.length>0&&(yield s)}(e,t):yield*async function*(e,t,r){let{cursor:n,limit:i,direction:o}=t,s=i,a=void 0===n,c=[];if("forward"===o)for await(let t of e)s<=0&&(yield c,c=[],s=i),a?(c.push(t),s--):a=r(t)===n;else{let t=[];for await(let r of e)t.push(r);for(let e=t.length-1;e>=0;e--){let o=t[e];a?(c.push(o),s--,s<=0&&(yield c,c=[],s=i)):a=r(o)===n}}c.length>0&&(yield c)}(e,t,r)}function E(){return{paginate:S}}}}),p=c(l()),h=c(l()),f=c(u()),d=class t{static dbInstances=new Map;static collectionInstances=new Map;static eventBusMap=new Map;static defaultModelName="stores";static getDatabase(r){const{database:n,enableTelemetry:i=!1,collection:o=t.defaultModelName}=r;if(!t.dbInstances.has(n)){const r=e.DatabaseConnection({name:n,enableTelemetry:i}).then((async t=>{try{await t.createCollection({name:o,version:"1.0.0",nestedSchemas:{},fields:{store:{name:"store",type:"string",required:!0},data:{name:"data",type:"object",required:!0},version:{name:"version",type:"string",required:!0},app:{name:"app",type:"string",required:!0}}})}catch(t){if(t instanceof e.DatabaseError&&"SCHEMA_ALREADY_EXISTS"!==t.type)throw t}return t}));t.dbInstances.set(n,r)}return t.dbInstances.get(n)}static getEventBus(e,r){const n=`${e}_store_${r}`;return t.eventBusMap.has(n)||t.eventBusMap.set(n,(0,h.createEventBus)({batchSize:5,async:!0,batchDelay:16,errorHandler:t=>console.error(`Event bus error for ${e}:${r}:`,t),crossTab:!0,channelName:n})),t.eventBusMap.get(n)}static getCollection(e){const{database:r,collection:n=t.defaultModelName}=e,i=`${r}:${n}`;if(!t.collectionInstances.has(i)){const r=t.getDatabase(e).then((e=>e.collection(n)));t.collectionInstances.set(i,r)}return t.collectionInstances.get(i)}static async closeDatabase(e){const r=t.dbInstances.get(e);if(r){(await r).close(),t.dbInstances.delete(e);const n=[];t.collectionInstances.forEach(((t,r)=>{r.startsWith(`${e}:`)&&n.push(r)})),n.forEach((e=>t.collectionInstances.delete(e)));const i=[];t.eventBusMap.forEach(((t,r)=>{r.startsWith(`${e}_store_`)&&(t.clear(),i.push(r))})),i.forEach((e=>t.eventBusMap.delete(e)))}}static async closeAll(){const e=Array.from(t.dbInstances.keys()).map((e=>t.closeDatabase(e)));await Promise.all(e)}static getActiveDatabases(){return Array.from(t.dbInstances.keys())}};exports.IndexedDBPersistence=class{collection=null;collectionPromise;config;eventBus;initialized=!1;initializationCallbacks=[];getStoreName(){return`_${this.config.app}_${this.config.store}_`}constructor(e){this.config=e,this.collectionPromise=d.getCollection(this.config),this.collectionPromise.then((e=>{this.collection=e,this.initialize()})).catch((e=>{console.error(`Failed to initialize collection for store ${this.getStoreName()}:`,e)})),this.eventBus=d.getEventBus(this.config.database,this.getStoreName())}async initialize(){try{const e=await this._get();if(e&&e.version!==this.config.version&&this.config.onUpgrade){const{state:t}=this.config.onUpgrade({data:e.data,version:e.version,app:e.app});await this.set("migration",t)}this.initialized=!0,this.initializationCallbacks.forEach((e=>e())),this.initializationCallbacks=[]}catch(e){console.error(`Failed to initialize and upgrade store ${this.getStoreName()}:`,e)}}_onInitialized(e){this.initialized?e():this.initializationCallbacks.push(e)}async getCollection(){return this.collection?this.collection:this.collectionPromise}async set(e,t){try{const r=await this.getCollection(),n=(new f.QueryBuilder).where({field:"store",operator:"eq",value:this.getStoreName()}).build(),i=await r.find(n.filters),o={store:this.getStoreName(),data:t,version:this.config.version,app:this.config.app};let s;return i?s=await i.update(o):(await r.create(o),s=!0),s&&this.eventBus.emit({name:"store:updated",payload:{storageKey:this.getStoreName(),instanceId:e,state:t,version:this.config.version,app:this.config.app}}),s}catch(t){return console.error(`Failed to set state for store ${this.getStoreName()} in database ${this.config.database} by instance ${e}:`,t),!1}}async _get(){try{const e=await this.getCollection(),t=(new f.QueryBuilder).where({field:"store",operator:"eq",value:this.getStoreName()}).build(),r=await e.find(t.filters);return r?r.read().then((()=>r)):null}catch(e){return console.error(`Failed to get state for store ${this.getStoreName()} in database ${this.config.database}:`,e),null}}async get(){this.initialized||await new Promise((e=>{this._onInitialized(e)}));const e=await this._get();return e?e.data:null}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:n,state:i})=>{r===this.getStoreName()&&n!==e&&t(i)}))}async clear(){this.initialized||await new Promise((e=>{this._onInitialized(e)}));try{const e=await this.collectionPromise,t=(new f.QueryBuilder).where({field:"store",operator:"eq",value:this.getStoreName()}).build(),r=await e.find(t.filters);return!r||await r.delete()}catch(e){return console.error(`Failed to clear state for store ${this.getStoreName()} in database ${this.config.database}:`,e),!1}}stats(){return{version:this.config.version,id:this.config.app}}async close(){await d.closeDatabase(this.config.database)}},exports.WebStoragePersistence=class{eventBus;storage;config;constructor(e){this.config=e,this.storage=e.session?sessionStorage:localStorage,this.eventBus=this.initializeEventBus(),this.initialize(),e.session||this.setupStorageEventListener()}initialize(){try{const e=this.storage.getItem(this.getStoreName());if(!e)return;const t=JSON.parse(e);if(t.version!==this.config.version&&this.config.onUpgrade){const{state:e}=this.config.onUpgrade({data:t.state,version:t.version,app:t.app});this.set("migration",e)}}catch(e){console.error(`Failed to initialize WebStoragePersistence for ${this.config.storageKey}:`,e)}}initializeEventBus(){return(0,p.createEventBus)({async:!0,batchSize:5,batchDelay:16,errorHandler:e=>console.error(`Event bus error for ${this.config.storageKey}:`,e),crossTab:!0,channelName:`storage_${this.getStoreName()}`})}getStoreName(){return`_${this.config.app}_${this.config.storageKey}_`}setupStorageEventListener(){window.addEventListener("storage",(e=>{if(e.key===this.getStoreName()&&e.newValue)try{const t=JSON.parse(e.newValue);t&&this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.storageKey,instanceId:"external",state:t.state,version:t.version,app:t.app}})}catch(e){console.error("Failed to parse storage event data:",e)}}))}set(e,t){try{const r={state:structuredClone(t),version:this.config.version,app:this.config.app},n=JSON.stringify(r);return this.storage.setItem(this.getStoreName(),n),this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.storageKey,instanceId:e,state:t,version:this.config.version,app:this.config.app}}),!0}catch(e){return console.error(`Failed to persist state to web storage for ${this.config.storageKey}:`,e),!1}}get(){try{const e=this.storage.getItem(this.getStoreName());if(!e)return null;return JSON.parse(e).state}catch(e){return console.error(`Failed to retrieve state from web storage for ${this.config.storageKey}:`,e),null}}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:n,state:i})=>{r===this.config.storageKey&&n!==e&&t(i)}))}clear(){try{return this.storage.removeItem(this.getStoreName()),this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.storageKey,instanceId:"clear-initiator",state:null,version:this.config.version,app:this.config.app}}),!0}catch(e){return console.error(`Failed to clear persisted state for ${this.config.storageKey}:`,e),!1}}stats(){return{version:this.config.version,id:this.config.app}}},exports.author="https://github.com/asaidimu";
package/index.mjs CHANGED
@@ -1 +1 @@
1
- import{DatabaseConnection as e,DatabaseError as t}from"@asaidimu/indexed";var r=Object.create,o=Object.defineProperty,n=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.getPrototypeOf,i=Object.prototype.hasOwnProperty,c=(e,t)=>function(){return t||(0,e[s(e)[0]])((t={exports:{}}).exports,t),t.exports},l=(e,t,c)=>(c=null!=e?r(a(e)):{},((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))i.call(e,c)||c===r||o(e,c,{get:()=>t[c],enumerable:!(a=n(t,c))||a.enumerable});return e})(e&&e.__esModule?c:o(c,"default",{value:e,enumerable:!0}),e)),u=c({"node_modules/@asaidimu/events/index.js"(e,t){var r,o=Object.defineProperty,n=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var r in t)o(e,r,{get:t[r],enumerable:!0})})(i,{createEventBus:()=>c}),t.exports=(r=i,((e,t,r,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))a.call(e,c)||c===r||o(e,c,{get:()=>t[c],enumerable:!(i=n(t,c))||i.enumerable});return e})(o({},"__esModule",{value:!0}),r));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let r=[],o=0,n=0;const s=new Map,a=new Map;let i=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?i=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{o++,n+=t,s.set(e,(s.get(e)||0)+1)},l=()=>{const t=r;r=[],t.forEach((({name:t,payload:r})=>{const o=performance.now();try{(a.get(t)||[]).forEach((e=>e(r)))}catch(o){e.errorHandler({...o,eventName:t,payload:r})}c(t,performance.now()-o)}))},u=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),f=e=>{const r=t.get(e);r?a.set(e,Array.from(r)):a.delete(e)};return i&&(i.onmessage=e=>{const{name:t,payload:r}=e.data;(a.get(t)||[]).forEach((e=>e(r)))}),{subscribe:(e,r)=>{t.has(e)||t.set(e,new Set);const o=t.get(e);return o.add(r),f(e),()=>{o.delete(r),0===o.size?(t.delete(e),a.delete(e)):f(e)}},emit:({name:t,payload:o})=>{if(e.async)return r.push({name:t,payload:o}),r.length>=e.batchSize?l():u(),void(i&&i.postMessage({name:t,payload:o}));const n=performance.now();try{(a.get(t)||[]).forEach((e=>e(o))),i&&i.postMessage({name:t,payload:o})}catch(r){e.errorHandler({...r,eventName:t,payload:o})}c(t,performance.now()-n)},getMetrics:()=>({totalEvents:o,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:s,averageEmitDuration:o>0?n/o:0}),clear:()=>{t.clear(),a.clear(),r=[],o=0,n=0,s.clear(),i&&(i.close(),i=null)}}}}}),f=c({"node_modules/@asaidimu/query/index.js"(e,t){var r,o=Object.defineProperty,n=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,i={};((e,t)=>{for(var r in t)o(e,r,{get:t[r],enumerable:!0})})(i,{QueryBuilder:()=>c,createJoiner:()=>g,createMatcher:()=>u,createPaginator:()=>E,createProjector:()=>q,createSorter:()=>j}),t.exports=(r=i,((e,t,r,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of s(t))!a.call(e,c)&&c!==r&&o(e,c,{get:()=>t[c],enumerable:!(i=n(t,c))||i.enumerable});return e})(o({},"__esModule",{value:!0}),r));var c=class{query;constructor(){this.query={}}where(e){return this.query.filters=e,this}orderBy(e,t){return this.query.sort||(this.query.sort=[]),this.query.sort.push({field:e,direction:t}),this}offset(e,t){return this.query.pagination={type:"offset",offset:e,limit:t},this}cursor(e,t,r){return this.query.pagination={type:"cursor",cursor:e,limit:t,direction:r},this}include(e){return this.query.projection||(this.query.projection={}),this.query.projection.include=e,this}exclude(e){return this.query.projection||(this.query.projection={}),this.query.projection.exclude=e,this}computed(e,t){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"computed",expression:e,alias:t}),this}case(e,t,r){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"case",conditions:e,else:t,alias:r}),this}join(e,t,r){return this.query.joins||(this.query.joins=[]),this.query.joins.push({relation:e,alias:r,query:t}),this}aggregate(e,t){return this.query.aggregations={groupBy:e,metrics:t},this}window(e){return this.query.window||(this.query.window=[]),this.query.window.push(e),this}hint(e){return this.query.hints||(this.query.hints=[]),this.query.hints.push(e),this}build(){return this.query}};function l(e){function t(e,t){return function(e){return"field"===e?.type}(t)?e[t.field]:function(e){return"value"===e?.type}(t)?t.value:function(e){return"function"===e?.type}(t)?o(t,e):function(e){return"computed"===e?.type}(t)?o(t.expression,e):function(e){return"case"===e?.type}(t)?function(e,t){for(let r of t.conditions)if(n(e,r.when))return r.then;return t.else}(e,t):t}let r=new Map([["and",(e,t)=>t.every((t=>n(e,t)))],["or",(e,t)=>t.some((t=>n(e,t)))],["not",(e,t)=>!t.every((t=>n(e,t)))],["nor",(e,t)=>!t.some((t=>n(e,t)))],["xor",(e,t)=>1===t.filter((t=>n(e,t))).length]]);function o(r,o){let n=r.arguments.map((e=>t(o,e)));if(e[r.function])return e[r.function](...n);throw new Error(`Function ${r.function} not found!`)}function n(o,n){if(function(e){return!!e&&void 0!==e.conditions}(n))return function(e,t){let{operator:o,conditions:n}=t,s=r.get(o);if(s)return s(e,n);throw new Error(`Unsupported logical operator: ${o}`)}(o,n);if(!n||!n.field)return!1;let{field:s,operator:a,value:i}=n,c=o[s],l=t(o,i),u=new Map([["eq",(e,t)=>e===t],["neq",(e,t)=>e!==t],["lt",(e,t)=>e<t],["lte",(e,t)=>e<=t],["gt",(e,t)=>e>t],["gte",(e,t)=>e>=t],["in",(e,t)=>Array.isArray(t)&&t.includes(e)],["nin",(e,t)=>Array.isArray(t)&&!t.includes(e)],["contains",(e,t)=>"string"==typeof e?e.includes(t):!!Array.isArray(e)&&e.includes(i)],["ncontains",(e,t)=>"string"==typeof e&&!e.includes(t)],["startswith",(e,t)=>"string"==typeof e&&e.startsWith(t)],["endswith",(e,t)=>"string"==typeof e&&e.endsWith(t)],["exists",e=>null!=e],["nexists",e=>null==e]]),f=e[a]||u.get(a);if(f)return f(c,l);throw new Error(`Unsupported comparison operator: ${a}`)}return{resolve:t,evaluate:n}}function u(e){let{evaluate:t}=l(e),r=new WeakMap;function o(e,o){let n=r.get(e);n||(n=new Map,r.set(e,n));let s=JSON.stringify(o);if(n.has(s))return n.get(s);let a=t(e,o);return n.set(s,a),a}return{matcher:o,match:o}}var f=class extends Error{constructor(e,t){super(e),this.code=t,this.name="JoinError"}},d=e=>e&&"field"in e&&"operator"in e&&"value"in e,h=(e,t)=>{if(e){if(d(e)&&e){let r=(e=>"object"==typeof e&&null!==e&&"type"in e&&"field"===e.type)(e.value)?((e,t)=>t.split(".").reduce(((e,t)=>e?.[t]),e))(t,e.value.field):e.value;return{...e,value:r}}if((e=>"operator"in e&&"conditions"in e)(e)){let r={...e};return e.conditions&&(r.conditions=e.conditions.map((e=>h(e,t)))),r}return e}},p=async(e,t,r,o)=>{try{if(((e,t)=>{if(!e.relation)throw new f("Join configuration must specify a relation","INVALID_CONFIG");if(!t[e.relation])throw new f(`Collection "${e.relation}" not found in database`,"COLLECTION_NOT_FOUND");if(e.alias&&"string"!=typeof e.alias)throw new f("Join alias must be a string","INVALID_ALIAS")})(r,e),!Array.isArray(t))throw new f("Source data must be an array","INVALID_SOURCE_DATA");let n,s=e[r.relation];return r.query?.filters&&d(r.query.filters)&&(n=((e,t)=>{let r=new Map;return e.forEach((e=>{let o=e[t];r.has(o)||r.set(o,[]),r.get(o).push(e)})),r})(s,r.query.filters.field)),(await Promise.all(t.map((async e=>{let t,a=((e,t)=>{if(!e)return{};let r=h(e.filters,t);return{...e,filters:r}})(r.query,e);return t=a.filters&&d(a.filters)&&n?.has(a.filters.value)?n.get(a.filters.value)||[]:s.filter((e=>o.matcher(e,a.filters))),((e,t,r)=>{let o=r.alias||r.relation;return[{...e,[o]:t}]})(e,await[e=>a.sort?o.sorter(e,a.sort):e,e=>a.projection?o.projector(e,a.projection):e,async e=>a.pagination?await o.paginator(e,a.pagination):e].reduce((async(e,t)=>t(await e)),Promise.resolve(t)),r)})))).flat()}catch(e){throw e instanceof f?e:new f(`Join operation failed: ${e.message}`,"JOIN_EXECUTION_ERROR")}},y=async(e,t,r,o)=>r.reduce((async(t,r)=>p(e,await t,r,o)),Promise.resolve(t));function g(){return{join:y}}var m=class extends Error{constructor(e,t){super(`Unsupported comparison between ${typeof e} and ${typeof t}`),this.name="UnsupportedComparisonError"}},b=class extends Error{constructor(e){super(`Unsupported sort direction: ${e}`),this.name="InvalidSortDirectionError"}};function w(e,t,r){if(e===t)return 0;if(null==e||null==t)return null==e?"asc"===r?-1:1:"asc"===r?1:-1;if("string"==typeof e&&"string"==typeof t)return"asc"===r?e.localeCompare(t):t.localeCompare(e);if("number"==typeof e&&"number"==typeof t)return"asc"===r?e-t:t-e;throw new m(e,t)}function v(e,t){let r=Array.from(e);return 0===t.length?r:r.sort(((e,r)=>{for(let o of t){let{field:t,direction:n}=o,s=e[t],a=r[t];try{if("asc"!==n&&"desc"!==n)throw new b(n);let e=w(s,a,n);if(0!==e)return e}catch(e){throw e instanceof m||e instanceof b?e:new Error(`Error comparing field '${t}': ${e.message}`)}}return 0}))}function j(){return{sort:v}}function q(e){let{resolve:t}=l(e);function r(e,o){let n={};return o.include?.length&&function(e,t,o){for(let n of t)if("string"!=typeof n){for(let[t,s]of Object.entries(n))if(Object.prototype.hasOwnProperty.call(e,t)){let n=r(e[t],s);o[t]=n}}else{let t=n;o[t]=e[t]}}(e,o.include,n),o.exclude?.length&&function(e,t,o){0===Object.keys(o).length&&Object.assign(o,e);for(let e of t)if("string"!=typeof e)for(let[t,n]of Object.entries(e)){if(!Object.prototype.hasOwnProperty.call(o,t))continue;let e=o[t];e&&"object"==typeof e?o[t]=r(e,n):delete o[t]}else delete o[e]}(e,o.exclude,n),o.computed?.length&&function(e,r,o){for(let n of r)o[n.alias]=t(e,n)}(e,o.computed,n),n}return{project:r}}async function*O(e,t,r=e=>String(e)){"offset"===t.type?yield*async function*(e,t){let{offset:r,limit:o}=t,n=0,s=o,a=[];for await(let t of e)s<=0&&(yield a,a=[],s=o),n<r?n++:(a.push(t),s--);a.length>0&&(yield a)}(e,t):yield*async function*(e,t,r){let{cursor:o,limit:n,direction:s}=t,a=n,i=void 0===o,c=[];if("forward"===s)for await(let t of e)a<=0&&(yield c,c=[],a=n),i?(c.push(t),a--):i=r(t)===o;else{let t=[];for await(let r of e)t.push(r);for(let e=t.length-1;e>=0;e--){let s=t[e];i?(c.push(s),a--,a<=0&&(yield c,c=[],a=n)):i=r(s)===o}}c.length>0&&(yield c)}(e,t,r)}function E(){return{paginate:O}}}}),d="https://github.com/asaidimu",h=l(u()),p=class{storageKey;eventBus;storage;constructor(e,t=!1){this.storageKey=e,this.storage=t?sessionStorage:localStorage,this.eventBus=this.initializeEventBus(),t||this.setupStorageEventListener()}initializeEventBus(){const e={async:!0,batchSize:5,batchDelay:16,errorHandler:e=>console.error(`Event bus error for ${this.storageKey}:`,e),crossTab:!0,channelName:`storage_${this.storageKey}`};return(0,h.createEventBus)(e)}setupStorageEventListener(){window.addEventListener("storage",(e=>{if(e.key===this.storageKey&&e.newValue)try{const t=JSON.parse(e.newValue);this.eventBus.emit({name:"store:updated",payload:{storageKey:this.storageKey,instanceId:"external",state:t}})}catch(e){console.error("Failed to parse storage event data:",e)}}))}set(e,t){try{const r=JSON.stringify(t);return this.storage.setItem(this.storageKey,r),this.eventBus.emit({name:"store:updated",payload:{storageKey:this.storageKey,instanceId:e,state:t}}),!0}catch(e){return console.error(`Failed to persist state to web storage for ${this.storageKey}:`,e),!1}}get(){try{const e=this.storage.getItem(this.storageKey);return e?JSON.parse(e):null}catch(e){return console.error(`Failed to retrieve state from web storage for ${this.storageKey}:`,e),null}}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:o,state:n})=>{r===this.storageKey&&o!==e&&t(n)}))}clear(){try{return this.storage.removeItem(this.storageKey),!0}catch(e){return console.error(`Failed to clear persisted state for ${this.storageKey}:`,e),!1}}},y=l(u()),g=l(f()),m=class r{static dbInstances=new Map;static collectionInstances=new Map;static eventBusMap=new Map;static defaultModelName="stores";static getDatabase(o){const{database:n,enableTelemetry:s=!1,collection:a=r.defaultModelName}=o;if(!r.dbInstances.has(n)){const o=e({name:n,enableTelemetry:s}).then((async e=>{try{await e.createCollection({name:a,version:"1.0.0",nestedSchemas:{},fields:{store:{name:"store",type:"string",required:!0},data:{name:"data",type:"object",required:!0}}})}catch(e){if(e instanceof t&&"SCHEMA_ALREADY_EXISTS"!==e.type)throw e}return e}));r.dbInstances.set(n,o)}return r.dbInstances.get(n)}static getEventBus(e,t){const o=`${e}_store_${t}`;return r.eventBusMap.has(o)||r.eventBusMap.set(o,(0,y.createEventBus)({batchSize:5,async:!0,batchDelay:16,errorHandler:r=>console.error(`Event bus error for ${e}:${t}:`,r),crossTab:!0,channelName:o})),r.eventBusMap.get(o)}static getCollection(e){const{database:t,collection:o=r.defaultModelName}=e,n=`${t}:${o}`;if(!r.collectionInstances.has(n)){const t=r.getDatabase(e).then((e=>e.collection(o)));r.collectionInstances.set(n,t)}return r.collectionInstances.get(n)}static async closeDatabase(e){const t=r.dbInstances.get(e);if(t){(await t).close(),r.dbInstances.delete(e);const o=[];r.collectionInstances.forEach(((t,r)=>{r.startsWith(`${e}:`)&&o.push(r)})),o.forEach((e=>r.collectionInstances.delete(e)));const n=[];r.eventBusMap.forEach(((t,r)=>{r.startsWith(`${e}_store_`)&&(t.clear(),n.push(r))})),n.forEach((e=>r.eventBusMap.delete(e)))}}static async closeAll(){const e=Array.from(r.dbInstances.keys()).map((e=>r.closeDatabase(e)));await Promise.all(e)}static getActiveDatabases(){return Array.from(r.dbInstances.keys())}},b=class{collection=null;collectionPromise;config;eventBus;constructor(e){this.config=e,this.collectionPromise=m.getCollection(this.config),this.collectionPromise.then((e=>{this.collection=e})).catch((e=>{console.error(`Failed to initialize collection for store ${this.config.store}:`,e)})),this.eventBus=m.getEventBus(this.config.database,this.config.store)}async getCollection(){return this.collection?this.collection:this.collectionPromise}async set(e,t){try{const r=await this.getCollection(),o=(new g.QueryBuilder).where({field:"store",operator:"eq",value:this.config.store}).build(),n=await r.find(o.filters),s={store:this.config.store,data:t};let a;return n?a=await n.update(s):(await r.create(s),a=!0),a&&this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.store,instanceId:e,state:t}}),a}catch(t){return console.error(`Failed to set state for store ${this.config.store} in database ${this.config.database} by instance ${e}:`,t),!1}}async get(){try{const e=await this.getCollection(),t=(new g.QueryBuilder).where({field:"store",operator:"eq",value:this.config.store}).build(),r=await e.find(t.filters);return r?r.read().then((()=>r.data)):null}catch(e){return console.error(`Failed to get state for store ${this.config.store} in database ${this.config.database}:`,e),null}}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:o,state:n})=>{r===this.config.store&&o!==e&&t(n)}))}async clear(){try{const e=await this.collectionPromise,t=(new g.QueryBuilder).where({field:"store",operator:"eq",value:this.config.store}).build(),r=await e.find(t.filters);return!r||await r.delete()}catch(e){return console.error(`Failed to clear state for store ${this.config.store} in database ${this.config.database}:`,e),!1}}async close(){await m.closeDatabase(this.config.database)}};export{b as IndexedDBPersistence,p as WebStoragePersistence,d as author};
1
+ import{DatabaseConnection as e,DatabaseError as t}from"@asaidimu/indexed";var r=Object.create,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,c=(e,t)=>function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports},l=(e,t,c)=>(c=null!=e?r(s(e)):{},((e,t,r,s)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))a.call(e,c)||c===r||n(e,c,{get:()=>t[c],enumerable:!(s=i(t,c))||s.enumerable});return e})(e&&e.__esModule?c:n(c,"default",{value:e,enumerable:!0}),e)),u=c({"node_modules/@asaidimu/events/index.js"(e,t){var r,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(a,{createEventBus:()=>c}),t.exports=(r=a,((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))s.call(e,c)||c===r||n(e,c,{get:()=>t[c],enumerable:!(a=i(t,c))||a.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let r=[],n=0,i=0;const o=new Map,s=new Map;let a=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?a=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{n++,i+=t,o.set(e,(o.get(e)||0)+1)},l=()=>{const t=r;r=[],t.forEach((({name:t,payload:r})=>{const n=performance.now();try{(s.get(t)||[]).forEach((e=>e(r)))}catch(n){e.errorHandler({...n,eventName:t,payload:r})}c(t,performance.now()-n)}))},u=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),p=e=>{const r=t.get(e);r?s.set(e,Array.from(r)):s.delete(e)};return a&&(a.onmessage=e=>{const{name:t,payload:r}=e.data;(s.get(t)||[]).forEach((e=>e(r)))}),{subscribe:(e,r)=>{t.has(e)||t.set(e,new Set);const n=t.get(e);return n.add(r),p(e),()=>{n.delete(r),0===n.size?(t.delete(e),s.delete(e)):p(e)}},emit:({name:t,payload:n})=>{if(e.async)return r.push({name:t,payload:n}),r.length>=e.batchSize?l():u(),void(a&&a.postMessage({name:t,payload:n}));const i=performance.now();try{(s.get(t)||[]).forEach((e=>e(n))),a&&a.postMessage({name:t,payload:n})}catch(r){e.errorHandler({...r,eventName:t,payload:n})}c(t,performance.now()-i)},getMetrics:()=>({totalEvents:n,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:o,averageEmitDuration:n>0?i/n:0}),clear:()=>{t.clear(),s.clear(),r=[],n=0,i=0,o.clear(),a&&(a.close(),a=null)}}}}}),p=c({"node_modules/@asaidimu/query/index.js"(e,t){var r,n=Object.defineProperty,i=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})(a,{QueryBuilder:()=>c,createJoiner:()=>g,createMatcher:()=>u,createPaginator:()=>O,createProjector:()=>q,createSorter:()=>j}),t.exports=(r=a,((e,t,r,a)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of o(t))!s.call(e,c)&&c!==r&&n(e,c,{get:()=>t[c],enumerable:!(a=i(t,c))||a.enumerable});return e})(n({},"__esModule",{value:!0}),r));var c=class{query;constructor(){this.query={}}where(e){return this.query.filters=e,this}orderBy(e,t){return this.query.sort||(this.query.sort=[]),this.query.sort.push({field:e,direction:t}),this}offset(e,t){return this.query.pagination={type:"offset",offset:e,limit:t},this}cursor(e,t,r){return this.query.pagination={type:"cursor",cursor:e,limit:t,direction:r},this}include(e){return this.query.projection||(this.query.projection={}),this.query.projection.include=e,this}exclude(e){return this.query.projection||(this.query.projection={}),this.query.projection.exclude=e,this}computed(e,t){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"computed",expression:e,alias:t}),this}case(e,t,r){return this.query.projection||(this.query.projection={}),this.query.projection.computed||(this.query.projection.computed=[]),this.query.projection.computed.push({type:"case",conditions:e,else:t,alias:r}),this}join(e,t,r){return this.query.joins||(this.query.joins=[]),this.query.joins.push({relation:e,alias:r,query:t}),this}aggregate(e,t){return this.query.aggregations={groupBy:e,metrics:t},this}window(e){return this.query.window||(this.query.window=[]),this.query.window.push(e),this}hint(e){return this.query.hints||(this.query.hints=[]),this.query.hints.push(e),this}build(){return this.query}};function l(e){function t(e,t){return function(e){return"field"===e?.type}(t)?e[t.field]:function(e){return"value"===e?.type}(t)?t.value:function(e){return"function"===e?.type}(t)?n(t,e):function(e){return"computed"===e?.type}(t)?n(t.expression,e):function(e){return"case"===e?.type}(t)?function(e,t){for(let r of t.conditions)if(i(e,r.when))return r.then;return t.else}(e,t):t}let r=new Map([["and",(e,t)=>t.every((t=>i(e,t)))],["or",(e,t)=>t.some((t=>i(e,t)))],["not",(e,t)=>!t.every((t=>i(e,t)))],["nor",(e,t)=>!t.some((t=>i(e,t)))],["xor",(e,t)=>1===t.filter((t=>i(e,t))).length]]);function n(r,n){let i=r.arguments.map((e=>t(n,e)));if(e[r.function])return e[r.function](...i);throw new Error(`Function ${r.function} not found!`)}function i(n,i){if(function(e){return!!e&&void 0!==e.conditions}(i))return function(e,t){let{operator:n,conditions:i}=t,o=r.get(n);if(o)return o(e,i);throw new Error(`Unsupported logical operator: ${n}`)}(n,i);if(!i||!i.field)return!1;let{field:o,operator:s,value:a}=i,c=n[o],l=t(n,a),u=new Map([["eq",(e,t)=>e===t],["neq",(e,t)=>e!==t],["lt",(e,t)=>e<t],["lte",(e,t)=>e<=t],["gt",(e,t)=>e>t],["gte",(e,t)=>e>=t],["in",(e,t)=>Array.isArray(t)&&t.includes(e)],["nin",(e,t)=>Array.isArray(t)&&!t.includes(e)],["contains",(e,t)=>"string"==typeof e?e.includes(t):!!Array.isArray(e)&&e.includes(a)],["ncontains",(e,t)=>"string"==typeof e&&!e.includes(t)],["startswith",(e,t)=>"string"==typeof e&&e.startsWith(t)],["endswith",(e,t)=>"string"==typeof e&&e.endsWith(t)],["exists",e=>null!=e],["nexists",e=>null==e]]),p=e[s]||u.get(s);if(p)return p(c,l);throw new Error(`Unsupported comparison operator: ${s}`)}return{resolve:t,evaluate:i}}function u(e){let{evaluate:t}=l(e),r=new WeakMap;function n(e,n){let i=r.get(e);i||(i=new Map,r.set(e,i));let o=JSON.stringify(n);if(i.has(o))return i.get(o);let s=t(e,n);return i.set(o,s),s}return{matcher:n,match:n}}var p=class extends Error{constructor(e,t){super(e),this.code=t,this.name="JoinError"}},f=e=>e&&"field"in e&&"operator"in e&&"value"in e,h=(e,t)=>{if(e){if(f(e)&&e){let r=(e=>"object"==typeof e&&null!==e&&"type"in e&&"field"===e.type)(e.value)?((e,t)=>t.split(".").reduce(((e,t)=>e?.[t]),e))(t,e.value.field):e.value;return{...e,value:r}}if((e=>"operator"in e&&"conditions"in e)(e)){let r={...e};return e.conditions&&(r.conditions=e.conditions.map((e=>h(e,t)))),r}return e}},d=async(e,t,r,n)=>{try{if(((e,t)=>{if(!e.relation)throw new p("Join configuration must specify a relation","INVALID_CONFIG");if(!t[e.relation])throw new p(`Collection "${e.relation}" not found in database`,"COLLECTION_NOT_FOUND");if(e.alias&&"string"!=typeof e.alias)throw new p("Join alias must be a string","INVALID_ALIAS")})(r,e),!Array.isArray(t))throw new p("Source data must be an array","INVALID_SOURCE_DATA");let i,o=e[r.relation];return r.query?.filters&&f(r.query.filters)&&(i=((e,t)=>{let r=new Map;return e.forEach((e=>{let n=e[t];r.has(n)||r.set(n,[]),r.get(n).push(e)})),r})(o,r.query.filters.field)),(await Promise.all(t.map((async e=>{let t,s=((e,t)=>{if(!e)return{};let r=h(e.filters,t);return{...e,filters:r}})(r.query,e);return t=s.filters&&f(s.filters)&&i?.has(s.filters.value)?i.get(s.filters.value)||[]:o.filter((e=>n.matcher(e,s.filters))),((e,t,r)=>{let n=r.alias||r.relation;return[{...e,[n]:t}]})(e,await[e=>s.sort?n.sorter(e,s.sort):e,e=>s.projection?n.projector(e,s.projection):e,async e=>s.pagination?await n.paginator(e,s.pagination):e].reduce((async(e,t)=>t(await e)),Promise.resolve(t)),r)})))).flat()}catch(e){throw e instanceof p?e:new p(`Join operation failed: ${e.message}`,"JOIN_EXECUTION_ERROR")}},y=async(e,t,r,n)=>r.reduce((async(t,r)=>d(e,await t,r,n)),Promise.resolve(t));function g(){return{join:y}}var m=class extends Error{constructor(e,t){super(`Unsupported comparison between ${typeof e} and ${typeof t}`),this.name="UnsupportedComparisonError"}},b=class extends Error{constructor(e){super(`Unsupported sort direction: ${e}`),this.name="InvalidSortDirectionError"}};function w(e,t,r){if(e===t)return 0;if(null==e||null==t)return null==e?"asc"===r?-1:1:"asc"===r?1:-1;if("string"==typeof e&&"string"==typeof t)return"asc"===r?e.localeCompare(t):t.localeCompare(e);if("number"==typeof e&&"number"==typeof t)return"asc"===r?e-t:t-e;throw new m(e,t)}function v(e,t){let r=Array.from(e);return 0===t.length?r:r.sort(((e,r)=>{for(let n of t){let{field:t,direction:i}=n,o=e[t],s=r[t];try{if("asc"!==i&&"desc"!==i)throw new b(i);let e=w(o,s,i);if(0!==e)return e}catch(e){throw e instanceof m||e instanceof b?e:new Error(`Error comparing field '${t}': ${e.message}`)}}return 0}))}function j(){return{sort:v}}function q(e){let{resolve:t}=l(e);function r(e,n){let i={};return n.include?.length&&function(e,t,n){for(let i of t)if("string"!=typeof i){for(let[t,o]of Object.entries(i))if(Object.prototype.hasOwnProperty.call(e,t)){let i=r(e[t],o);n[t]=i}}else{let t=i;n[t]=e[t]}}(e,n.include,i),n.exclude?.length&&function(e,t,n){0===Object.keys(n).length&&Object.assign(n,e);for(let e of t)if("string"!=typeof e)for(let[t,i]of Object.entries(e)){if(!Object.prototype.hasOwnProperty.call(n,t))continue;let e=n[t];e&&"object"==typeof e?n[t]=r(e,i):delete n[t]}else delete n[e]}(e,n.exclude,i),n.computed?.length&&function(e,r,n){for(let i of r)n[i.alias]=t(e,i)}(e,n.computed,i),i}return{project:r}}async function*N(e,t,r=e=>String(e)){"offset"===t.type?yield*async function*(e,t){let{offset:r,limit:n}=t,i=0,o=n,s=[];for await(let t of e)o<=0&&(yield s,s=[],o=n),i<r?i++:(s.push(t),o--);s.length>0&&(yield s)}(e,t):yield*async function*(e,t,r){let{cursor:n,limit:i,direction:o}=t,s=i,a=void 0===n,c=[];if("forward"===o)for await(let t of e)s<=0&&(yield c,c=[],s=i),a?(c.push(t),s--):a=r(t)===n;else{let t=[];for await(let r of e)t.push(r);for(let e=t.length-1;e>=0;e--){let o=t[e];a?(c.push(o),s--,s<=0&&(yield c,c=[],s=i)):a=r(o)===n}}c.length>0&&(yield c)}(e,t,r)}function O(){return{paginate:N}}}}),f="https://github.com/asaidimu",h=l(u()),d=class{eventBus;storage;config;constructor(e){this.config=e,this.storage=e.session?sessionStorage:localStorage,this.eventBus=this.initializeEventBus(),this.initialize(),e.session||this.setupStorageEventListener()}initialize(){try{const e=this.storage.getItem(this.getStoreName());if(!e)return;const t=JSON.parse(e);if(t.version!==this.config.version&&this.config.onUpgrade){const{state:e}=this.config.onUpgrade({data:t.state,version:t.version,app:t.app});this.set("migration",e)}}catch(e){console.error(`Failed to initialize WebStoragePersistence for ${this.config.storageKey}:`,e)}}initializeEventBus(){return(0,h.createEventBus)({async:!0,batchSize:5,batchDelay:16,errorHandler:e=>console.error(`Event bus error for ${this.config.storageKey}:`,e),crossTab:!0,channelName:`storage_${this.getStoreName()}`})}getStoreName(){return`_${this.config.app}_${this.config.storageKey}_`}setupStorageEventListener(){window.addEventListener("storage",(e=>{if(e.key===this.getStoreName()&&e.newValue)try{const t=JSON.parse(e.newValue);t&&this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.storageKey,instanceId:"external",state:t.state,version:t.version,app:t.app}})}catch(e){console.error("Failed to parse storage event data:",e)}}))}set(e,t){try{const r={state:structuredClone(t),version:this.config.version,app:this.config.app},n=JSON.stringify(r);return this.storage.setItem(this.getStoreName(),n),this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.storageKey,instanceId:e,state:t,version:this.config.version,app:this.config.app}}),!0}catch(e){return console.error(`Failed to persist state to web storage for ${this.config.storageKey}:`,e),!1}}get(){try{const e=this.storage.getItem(this.getStoreName());if(!e)return null;return JSON.parse(e).state}catch(e){return console.error(`Failed to retrieve state from web storage for ${this.config.storageKey}:`,e),null}}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:n,state:i})=>{r===this.config.storageKey&&n!==e&&t(i)}))}clear(){try{return this.storage.removeItem(this.getStoreName()),this.eventBus.emit({name:"store:updated",payload:{storageKey:this.config.storageKey,instanceId:"clear-initiator",state:null,version:this.config.version,app:this.config.app}}),!0}catch(e){return console.error(`Failed to clear persisted state for ${this.config.storageKey}:`,e),!1}}stats(){return{version:this.config.version,id:this.config.app}}},y=l(u()),g=l(p()),m=class r{static dbInstances=new Map;static collectionInstances=new Map;static eventBusMap=new Map;static defaultModelName="stores";static getDatabase(n){const{database:i,enableTelemetry:o=!1,collection:s=r.defaultModelName}=n;if(!r.dbInstances.has(i)){const n=e({name:i,enableTelemetry:o}).then((async e=>{try{await e.createCollection({name:s,version:"1.0.0",nestedSchemas:{},fields:{store:{name:"store",type:"string",required:!0},data:{name:"data",type:"object",required:!0},version:{name:"version",type:"string",required:!0},app:{name:"app",type:"string",required:!0}}})}catch(e){if(e instanceof t&&"SCHEMA_ALREADY_EXISTS"!==e.type)throw e}return e}));r.dbInstances.set(i,n)}return r.dbInstances.get(i)}static getEventBus(e,t){const n=`${e}_store_${t}`;return r.eventBusMap.has(n)||r.eventBusMap.set(n,(0,y.createEventBus)({batchSize:5,async:!0,batchDelay:16,errorHandler:r=>console.error(`Event bus error for ${e}:${t}:`,r),crossTab:!0,channelName:n})),r.eventBusMap.get(n)}static getCollection(e){const{database:t,collection:n=r.defaultModelName}=e,i=`${t}:${n}`;if(!r.collectionInstances.has(i)){const t=r.getDatabase(e).then((e=>e.collection(n)));r.collectionInstances.set(i,t)}return r.collectionInstances.get(i)}static async closeDatabase(e){const t=r.dbInstances.get(e);if(t){(await t).close(),r.dbInstances.delete(e);const n=[];r.collectionInstances.forEach(((t,r)=>{r.startsWith(`${e}:`)&&n.push(r)})),n.forEach((e=>r.collectionInstances.delete(e)));const i=[];r.eventBusMap.forEach(((t,r)=>{r.startsWith(`${e}_store_`)&&(t.clear(),i.push(r))})),i.forEach((e=>r.eventBusMap.delete(e)))}}static async closeAll(){const e=Array.from(r.dbInstances.keys()).map((e=>r.closeDatabase(e)));await Promise.all(e)}static getActiveDatabases(){return Array.from(r.dbInstances.keys())}},b=class{collection=null;collectionPromise;config;eventBus;initialized=!1;initializationCallbacks=[];getStoreName(){return`_${this.config.app}_${this.config.store}_`}constructor(e){this.config=e,this.collectionPromise=m.getCollection(this.config),this.collectionPromise.then((e=>{this.collection=e,this.initialize()})).catch((e=>{console.error(`Failed to initialize collection for store ${this.getStoreName()}:`,e)})),this.eventBus=m.getEventBus(this.config.database,this.getStoreName())}async initialize(){try{const e=await this._get();if(e&&e.version!==this.config.version&&this.config.onUpgrade){const{state:t}=this.config.onUpgrade({data:e.data,version:e.version,app:e.app});await this.set("migration",t)}this.initialized=!0,this.initializationCallbacks.forEach((e=>e())),this.initializationCallbacks=[]}catch(e){console.error(`Failed to initialize and upgrade store ${this.getStoreName()}:`,e)}}_onInitialized(e){this.initialized?e():this.initializationCallbacks.push(e)}async getCollection(){return this.collection?this.collection:this.collectionPromise}async set(e,t){try{const r=await this.getCollection(),n=(new g.QueryBuilder).where({field:"store",operator:"eq",value:this.getStoreName()}).build(),i=await r.find(n.filters),o={store:this.getStoreName(),data:t,version:this.config.version,app:this.config.app};let s;return i?s=await i.update(o):(await r.create(o),s=!0),s&&this.eventBus.emit({name:"store:updated",payload:{storageKey:this.getStoreName(),instanceId:e,state:t,version:this.config.version,app:this.config.app}}),s}catch(t){return console.error(`Failed to set state for store ${this.getStoreName()} in database ${this.config.database} by instance ${e}:`,t),!1}}async _get(){try{const e=await this.getCollection(),t=(new g.QueryBuilder).where({field:"store",operator:"eq",value:this.getStoreName()}).build(),r=await e.find(t.filters);return r?r.read().then((()=>r)):null}catch(e){return console.error(`Failed to get state for store ${this.getStoreName()} in database ${this.config.database}:`,e),null}}async get(){this.initialized||await new Promise((e=>{this._onInitialized(e)}));const e=await this._get();return e?e.data:null}subscribe(e,t){return this.eventBus.subscribe("store:updated",(({storageKey:r,instanceId:n,state:i})=>{r===this.getStoreName()&&n!==e&&t(i)}))}async clear(){this.initialized||await new Promise((e=>{this._onInitialized(e)}));try{const e=await this.collectionPromise,t=(new g.QueryBuilder).where({field:"store",operator:"eq",value:this.getStoreName()}).build(),r=await e.find(t.filters);return!r||await r.delete()}catch(e){return console.error(`Failed to clear state for store ${this.getStoreName()} in database ${this.config.database}:`,e),!1}}stats(){return{version:this.config.version,id:this.config.app}}async close(){await m.closeDatabase(this.config.database)}};export{b as IndexedDBPersistence,d as WebStoragePersistence,f as author};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asaidimu/utils-persistence",
3
- "version": "2.0.4",
3
+ "version": "2.2.0",
4
4
  "description": "Persistence utilities.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",