qortex-core 0.3.0-beta.4 → 0.3.0-beta.6

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.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DefaultConfig, Q as QueryKey, a as QueryOptions, F as Fetcher, I as InferFetcherResult, b as QueryState } from './types-14ced1fe.js';
2
- export { E as EqualityFn, c as EqualityStrategy, d as QueryStatus, R as RefetchOnSubscribeOptions } from './types-14ced1fe.js';
1
+ import { D as DefaultConfig, Q as QueryKey, a as QueryOptions, F as Fetcher, I as InferFetcherResult, b as QueryState } from './types-96ae2039.js';
2
+ export { E as EqualityFn, c as EqualityStrategy, d as QueryStatus, R as RefetchOnSubscribeOptions } from './types-96ae2039.js';
3
3
 
4
4
  /**
5
5
  * Core query manager that handles caching, fetching, and state management
@@ -12,32 +12,7 @@ declare class QueryManagerCore {
12
12
  private throttleTime;
13
13
  private persister;
14
14
  private hasQueriesBeenUsed;
15
- /**
16
- * ⚠️ DANGER: Clear all cached data and subscriptions
17
- *
18
- * This method completely wipes all internal state including:
19
- * - All cached query data
20
- * - All active subscriptions
21
- * - All state references
22
- * - All persisted data
23
- *
24
- * @warning This should ONLY be used in testing environments or when you need to completely reset the query manager state. Using this in production will cause all active queries to lose their data and subscriptions to break.
25
- *
26
- * @example
27
- * ```typescript
28
- * // ✅ Safe usage in tests
29
- * beforeEach(() => {
30
- * queryManager.dangerClearCache();
31
- * });
32
- *
33
- * // ❌ Dangerous usage in production
34
- * // queryManager.dangerClearCache(); // Don't do this!
35
- * ```
36
- */
37
15
  dangerClearCache(): void;
38
- /**
39
- * Set default configuration for all queries
40
- */
41
16
  setDefaultConfig({ throttleTime, persister, ...config }: DefaultConfig): void;
42
17
  /**
43
18
  * Ensures a query state exists in cache, creating it if necessary
@@ -48,54 +23,24 @@ declare class QueryManagerCore {
48
23
  * Notifies all subscribers of a query state change
49
24
  */
50
25
  private emit;
51
- /**
52
- * Registers a fetcher function for a query key
53
- * Automatically fetches if enabled is not false
54
- * Enhanced with automatic type inference from fetcher
55
- */
56
26
  registerFetcher<T = any>(key: QueryKey, opts: QueryOptions<T>): void;
57
27
  registerFetcher<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
58
28
  fetcher: F;
59
29
  }): void;
60
- /**
61
- * Executes a fetch operation with proper error handling and state management
62
- * Prevents duplicate fetches
63
- * Enhanced with automatic type inference from fetcher
64
- */
65
30
  fetchQuery<T = any>(key: QueryKey, opts?: QueryOptions<T>): Promise<T>;
66
31
  fetchQuery<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
67
32
  fetcher: F;
68
33
  }): Promise<InferFetcherResult<F>>;
69
- /**
70
- * Manually sets query data without triggering a fetch
71
- * Marks query as successful
72
- */
73
34
  setQueryData<T = any>(key: QueryKey, data: T): void;
74
- /**
75
- * Gets query data
76
- * Handles mount logic to potentially start fetching
77
- */
78
35
  getQueryData<T = any>(key: QueryKey, opts?: QueryOptions<T>): T | undefined;
79
36
  getQueryData<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
80
37
  fetcher: F;
81
38
  }): InferFetcherResult<F> | undefined;
82
- /**
83
- * Gets comprehensive query state including computed flags
84
- * Handles placeholder data and error states appropriately
85
- * Handles mount logic to potentially start fetching
86
- */
87
39
  getQueryState<T = unknown>(key: QueryKey, opts?: QueryOptions<T>): QueryState<T>;
88
40
  getQueryState<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
89
41
  fetcher: F;
90
42
  }): QueryState<InferFetcherResult<F>>;
91
- /**
92
- * Marks a query as invalidated, triggering refetch
93
- */
94
43
  invalidateQuery(key: QueryKey): void;
95
- /**
96
- * Subscribes to query state changes with automatic subscription management
97
- * Handles mount logic to potentially start fetching
98
- */
99
44
  subscribeQuery(key: QueryKey, cb: (state: QueryState<any>) => void): () => void;
100
45
  subscribeQuery<F extends Fetcher>(key: QueryKey, cb: (state: QueryState<InferFetcherResult<F>>) => void, opts: QueryOptions<InferFetcherResult<F>> & {
101
46
  fetcher: F;
@@ -109,15 +54,168 @@ declare class QueryManagerCore {
109
54
  }
110
55
 
111
56
  declare const _queryManager: QueryManagerCore;
112
- declare const registerFetcher: QueryManagerCore["registerFetcher"];
113
- declare const fetchQuery: QueryManagerCore["fetchQuery"];
114
- declare const setQueryData: QueryManagerCore["setQueryData"];
115
- declare const getQueryData: QueryManagerCore["getQueryData"];
116
- declare const getQueryState: QueryManagerCore["getQueryState"];
117
- declare const invalidateQuery: QueryManagerCore["invalidateQuery"];
118
- declare const subscribeQuery: QueryManagerCore["subscribeQuery"];
119
- declare const setDefaultConfig: QueryManagerCore["setDefaultConfig"];
120
- declare const dangerClearCache: QueryManagerCore["dangerClearCache"];
57
+
58
+ /**
59
+ * Registers a fetcher function for a query key and sets up the query state
60
+ *
61
+ * @param key - Unique identifier for the query (string or array of primitives)
62
+ * @param opts - Query configuration options
63
+ * @param opts.fetcher - Async function that fetches data for this query
64
+ * @param opts.enabled - Whether the query should be active (default: true)
65
+ * @param opts.staleTime - Time in ms before data is considered stale (default: 0)
66
+ * @param opts.equalityStrategy - How to compare data for changes ('shallow' | 'deep')
67
+ * @param opts.equalityFn - Custom equality function for data comparison
68
+ * @param opts.refetchOnSubscribe - When to refetch on subscription ('always' | 'stale' | false)
69
+ * @param opts.placeholderData - Initial data to show while loading
70
+ * @param opts.usePreviousDataOnError - Keep previous data when error occurs
71
+ * @param opts.usePlaceholderOnError - Use placeholder data when error occurs
72
+ *
73
+ * Automatically triggers initial fetch if enabled is not false. Enhanced with automatic type inference from fetcher function.
74
+ */
75
+ declare const registerFetcher: {
76
+ <T = any>(key: QueryKey, opts: QueryOptions<T>): void;
77
+ <F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
78
+ fetcher: F;
79
+ }): void;
80
+ };
81
+ /**
82
+ * Executes a fetch operation with proper error handling and state management
83
+ *
84
+ * @param key - Unique identifier for the query
85
+ * @param opts - Optional query configuration (if not already registered)
86
+ * @returns Promise that resolves to the fetched data
87
+ *
88
+ * Prevents duplicate fetches by tracking ongoing promises. Enhanced with automatic type inference from fetcher function.
89
+ * Updates query state with loading, success, or error status. Handles race conditions and concurrent requests.
90
+ */
91
+ declare const fetchQuery: {
92
+ <T = any>(key: QueryKey, opts?: QueryOptions<T>): Promise<T>;
93
+ <F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
94
+ fetcher: F;
95
+ }): Promise<InferFetcherResult<F>>;
96
+ };
97
+ /**
98
+ * Manually sets query data without triggering a fetch operation
99
+ *
100
+ * @param key - Unique identifier for the query
101
+ * @param data - Data to set for the query
102
+ *
103
+ * Marks the query as successful and updates the cache. Useful for optimistic updates or setting initial data.
104
+ * Triggers all subscribers with the new data. Does not affect the fetcher function or trigger network requests.
105
+ */
106
+ declare const setQueryData: <T = any>(key: QueryKey, data: T) => void;
107
+ /**
108
+ * Gets the current data for a query
109
+ *
110
+ * @param key - Unique identifier for the query
111
+ * @param opts - Optional query configuration (if not already registered)
112
+ * @returns The current data value or undefined if not available
113
+ *
114
+ * Handles mount logic to potentially start fetching if data is stale or missing.
115
+ * Returns undefined if the query has never been fetched or if an error occurred.
116
+ */
117
+ declare const getQueryData: {
118
+ <T = any>(key: QueryKey, opts?: QueryOptions<T>): T | undefined;
119
+ <F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
120
+ fetcher: F;
121
+ }): InferFetcherResult<F> | undefined;
122
+ };
123
+ /**
124
+ * Gets the complete query state including loading, error, and computed flags
125
+ *
126
+ * @param key - Unique identifier for the query
127
+ * @param opts - Optional query configuration (if not already registered)
128
+ * @returns QueryState object with data, error, status, and computed flags
129
+ *
130
+ * Returns an object containing:
131
+ * - data: The current data value
132
+ * - error: Any error that occurred during fetching
133
+ * - status: Current status ('idle' | 'fetching' | 'success' | 'error')
134
+ * - isStale: Whether the data is considered stale
135
+ * - isLoading: Whether the query is currently loading
136
+ * - isFetching: Whether a fetch is in progress
137
+ * - isError: Whether the query is in an error state
138
+ * - isSuccess: Whether the query completed successfully
139
+ * - refetch: Function to manually trigger a refetch
140
+ *
141
+ * Handles mount logic to potentially start fetching if data is stale or missing.
142
+ */
143
+ declare const getQueryState: {
144
+ <T = unknown>(key: QueryKey, opts?: QueryOptions<T>): QueryState<T>;
145
+ <F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
146
+ fetcher: F;
147
+ }): QueryState<InferFetcherResult<F>>;
148
+ };
149
+ /**
150
+ * Invalidates a query, marking it as stale and triggering a refetch
151
+ *
152
+ * @param key - Unique identifier for the query
153
+ *
154
+ * Marks the query as invalidated and immediately triggers a refetch operation.
155
+ * Useful for forcing data refresh after mutations or when you know data is outdated.
156
+ * All subscribers will be notified of the state changes.
157
+ */
158
+ declare const invalidateQuery: (key: QueryKey) => void;
159
+ /**
160
+ * Subscribes to query state changes and returns an unsubscribe function
161
+ *
162
+ * @param key - Unique identifier for the query
163
+ * @param callback - Function called whenever the query state changes
164
+ * @param opts - Optional query configuration (if not already registered)
165
+ * @returns Unsubscribe function to stop receiving updates
166
+ *
167
+ * The callback receives the current QueryState object. Handles mount logic to potentially start fetching.
168
+ * Returns a cleanup function that should be called when the subscription is no longer needed.
169
+ * Multiple subscribers can be registered for the same query key.
170
+ */
171
+ declare const subscribeQuery: {
172
+ (key: QueryKey, cb: (state: QueryState<any>) => void): () => void;
173
+ <F extends Fetcher>(key: QueryKey, cb: (state: QueryState<InferFetcherResult<F>>) => void, opts: QueryOptions<InferFetcherResult<F>> & {
174
+ fetcher: F;
175
+ }): () => void;
176
+ <T = any>(key: QueryKey, cb: (state: QueryState<T>) => void, opts?: QueryOptions<T>): () => void;
177
+ };
178
+ /**
179
+ * Sets default configuration that applies to all queries
180
+ *
181
+ * @param config - Default configuration object
182
+ * @param config.enabled - Default enabled state for all queries
183
+ * @param config.staleTime - Default stale time in milliseconds
184
+ * @param config.refetchOnSubscribe - Default refetch behavior on subscription
185
+ * @param config.equalityStrategy - Default equality comparison strategy
186
+ * @param config.equalityFn - Default equality function
187
+ * @param config.usePreviousDataOnError - Default behavior for previous data on error
188
+ * @param config.usePlaceholderOnError - Default behavior for placeholder data on error
189
+ * @param config.throttleTime - Time in ms to throttle fetch requests (default: 1000)
190
+ * @param config.persister - Persister instance for data persistence
191
+ *
192
+ * These defaults will be merged with individual query options. Useful for setting global behavior
193
+ * like default stale times, error handling, or persistence configuration.
194
+ */
195
+ declare const setDefaultConfig: ({ throttleTime, persister, ...config }: DefaultConfig) => void;
196
+ /**
197
+ * ⚠️ DANGER: Clear all cached data and subscriptions
198
+ *
199
+ * This method completely wipes all internal state including:
200
+ * - All cached query data
201
+ * - All active subscriptions
202
+ * - All state references
203
+ * - All persisted data
204
+ *
205
+ * @warning This should ONLY be used in testing environments or when you need to completely reset the query manager state. Using this in production will cause all active queries to lose their data and subscriptions to break.
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * // ✅ Safe usage in tests
210
+ * beforeEach(() => {
211
+ * dangerClearCache();
212
+ * });
213
+ *
214
+ * // ❌ Dangerous usage in production
215
+ * // dangerClearCache(); // Don't do this!
216
+ * ```
217
+ */
218
+ declare const dangerClearCache: () => void;
121
219
 
122
220
  /**
123
221
  * Normalizes query keys to a consistent string format for internal storage
package/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
- function c(t){return Array.isArray(t)?t.join(","):String(t)}function l(t,r,a="shallow"){if(t===r)return !0;if(t==null||r==null)return t===r;if(typeof t!="object"||typeof r!="object")return !1;try{let e=t,s=r;if(Array.isArray(e)&&Array.isArray(s)){if(e.length!==s.length)return !1;for(let o=0;o<e.length;o++)if(a==="deep"){if(!l(e[o],s[o],a))return !1}else if(e[o]!==s[o])return !1;return !0}if(Array.isArray(e)||Array.isArray(s))return !1;let n=Object.keys(e),u=Object.keys(s);if(n.length!==u.length)return !1;for(let o=0;o<n.length;o++){let y=n[o];if(a==="deep"){if(!l(e[y],s[y],a))return !1}else if(e[y]!==s[y])return !1}return !0}catch{return !1}}function d(t,r){return r||((a,e)=>l(a,e,t||"shallow"))}function Q(t,r){return {status:"idle",updatedAt:void 0,staleTime:t?.staleTime??0,isInvalidated:!1,fetcher:t?.fetcher,equalityFn:d(t?.equalityStrategy,t?.equalityFn),equalityStrategy:t?.equalityStrategy??"shallow",placeholderData:t?.placeholderData,usePreviousDataOnError:t?.usePreviousDataOnError??!1,usePlaceholderOnError:t?.usePlaceholderOnError??!1,refetchOnSubscribe:t?.refetchOnSubscribe??"stale",enabled:t?.enabled!==!1,refetch:r||(()=>Promise.resolve(void 0)),isSuccess:!1,isError:!1,lastReturnedState:void 0}}function f(t){let r=Date.now(),a=t.updatedAt!==void 0&&r-t.updatedAt>t.staleTime||t.isInvalidated,e,s=!1;switch(t.status){case"error":t.usePreviousDataOnError&&t.data!==void 0?e=t.data:t.usePlaceholderOnError&&t.placeholderData!==void 0&&(e=t.placeholderData,s=!0);break;case"fetching":t.data!==void 0?(e=t.data,s=!1):t.placeholderData&&(e=t.placeholderData,s=!0);break;case"success":case"idle":e=t.data??t.placeholderData,s=t.data?!1:!!t.placeholderData;break}return {data:e,error:t.error,status:t.status,updatedAt:t.updatedAt,isStale:a,isPlaceholderData:s,isLoading:t.status==="fetching"&&!t.updatedAt,isFetching:t.status==="fetching",isError:t.isError,isSuccess:t.isSuccess,refetch:t.refetch}}function p(t){console.warn(`[qortex] No fetcher or data for key "${c(t)}". Register a fetcher or set initial data.`);}var h=class{constructor(){this.cache=new Map;this.subs=new Map;this.defaultConfig={};this.throttleTime=50;this.persister=null;this.hasQueriesBeenUsed=!1;}dangerClearCache(){this.cache.clear(),this.subs.clear(),this.persister?.clear();}setDefaultConfig({throttleTime:r,persister:a,...e}){this.defaultConfig={...this.defaultConfig,...e},r!==void 0&&(this.throttleTime=r),a&&(this.persister=a,this.persister?.load(this.cache,this.hasQueriesBeenUsed));}ensureState(r,a={}){this.hasQueriesBeenUsed=!0;let e=c(r),s=this.cache.get(e);if(s){let n={...this.defaultConfig,...s,...a};Object.assign(s,n),s.enabled=n.enabled!==!1,this.cache.set(e,s);}else {let n={...this.defaultConfig,...a},u=Q(n,()=>this.fetchQuery(r));this.cache.set(e,u);}return this.cache.get(e)}emit(r,a){let e=c(r);this.cache.set(e,a),this.persister?.sync(this.cache);let s=this.subs.get(e);if(!s)return;let n=f(a);for(let u of Array.from(s))u(n);}registerFetcher(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);}fetchQuery(r,a){let e=this.ensureState(r,a);if(e.fetchPromise)return e.fetchPromise;let s=e.fetcher;if(!s)return e.updatedAt===void 0&&p(r),Promise.resolve(e.data);let n=s();return e.fetchPromise=n,e.status="fetching",e.lastFetchTime=Date.now(),this.emit(r,e),n.then(u=>{let o=d(e.equalityStrategy,e.equalityFn);e.data=o(e.data,u)?e.data:u,e.status="success",e.isError=!1,e.isSuccess=!0,e.updatedAt=Date.now(),e.fetchPromise=void 0,e.error=void 0,this.emit(r,e);}).catch(u=>{e.error=u,e.status="error",e.isError=!0,e.isSuccess=!1,e.updatedAt=Date.now(),e.fetchPromise=void 0,this.emit(r,e);}),n}setQueryData(r,a){let e=this.ensureState(r),s=e.data;d(e.equalityStrategy,e.equalityFn)(s,a)||(e.data=a,e.updatedAt=Date.now(),e.error=void 0,e.status="success",e.isInvalidated=!1,e.isError=!1,e.isSuccess=!0,this.emit(r,e));}getQueryData(r,a){let e=this.ensureState(r,a);return this.handleMountLogic(r,e),f(e).data}getQueryState(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);let s=f(e),n=e.lastReturnedState;return !n||!l(n,s,"shallow")?(e.lastReturnedState=s,s):n}invalidateQuery(r){let a=this.ensureState(r);a.isInvalidated=!0,this.emit(r,a),this.fetchQuery(r);}subscribeQuery(r,a,e){let s=c(r),n=this.ensureState(r,e);return this.subs.has(s)||this.subs.set(s,new Set),this.subs.get(s).add(a),this.handleMountLogic(r,n),()=>{this.subs.get(s).delete(a);}}handleMountLogic(r,a){let e=a.lastFetchTime&&Date.now()-a.lastFetchTime<this.throttleTime;if(a.status==="fetching"||!a.enabled||e||!a.fetcher)return;let s=Date.now(),n=a.updatedAt==null||s-(a.updatedAt||0)>a.staleTime||a.isInvalidated,u=!1;a.updatedAt==null?u=!0:(a.refetchOnSubscribe==="always"&&(u=!0),a.refetchOnSubscribe==="stale"&&(u=n)),u&&this.fetchQuery(r);}},g=h;var i=new g,D=i.registerFetcher.bind(i),O=i.fetchQuery.bind(i),K=i.setQueryData.bind(i),C=i.getQueryData.bind(i),E=i.getQueryState.bind(i),w=i.invalidateQuery.bind(i),x=i.subscribeQuery.bind(i),A=i.setDefaultConfig.bind(i),q=i.dangerClearCache.bind(i);
3
+ function c(t){return Array.isArray(t)?t.join("-"):String(t)}function l(t,r,a="shallow"){if(t===r)return !0;if(t==null||r==null)return t===r;if(typeof t!="object"||typeof r!="object")return !1;try{let e=t,s=r;if(Array.isArray(e)&&Array.isArray(s)){if(e.length!==s.length)return !1;for(let o=0;o<e.length;o++)if(a==="deep"){if(!l(e[o],s[o],a))return !1}else if(e[o]!==s[o])return !1;return !0}if(Array.isArray(e)||Array.isArray(s))return !1;let n=Object.keys(e),u=Object.keys(s);if(n.length!==u.length)return !1;for(let o=0;o<n.length;o++){let y=n[o];if(a==="deep"){if(!l(e[y],s[y],a))return !1}else if(e[y]!==s[y])return !1}return !0}catch{return !1}}function d(t,r){return r||((a,e)=>l(a,e,t||"shallow"))}function p(t,r){return {status:"idle",updatedAt:void 0,staleTime:t?.staleTime??0,isInvalidated:!1,fetcher:t?.fetcher,equalityFn:d(t?.equalityStrategy,t?.equalityFn),equalityStrategy:t?.equalityStrategy??"shallow",placeholderData:t?.placeholderData,usePreviousDataOnError:t?.usePreviousDataOnError??!1,usePlaceholderOnError:t?.usePlaceholderOnError??!1,refetchOnSubscribe:t?.refetchOnSubscribe??"stale",enabled:t?.enabled!==!1,refetch:r||(()=>Promise.resolve(void 0)),isSuccess:!1,isError:!1,lastReturnedState:void 0}}function f(t){let r=Date.now(),a=t.updatedAt!==void 0&&r-t.updatedAt>t.staleTime||t.isInvalidated,e,s=!1;switch(t.status){case"error":t.usePreviousDataOnError&&t.data!==void 0?e=t.data:t.usePlaceholderOnError&&t.placeholderData!==void 0&&(e=t.placeholderData,s=!0);break;case"fetching":t.data!==void 0?(e=t.data,s=!1):t.placeholderData&&(e=t.placeholderData,s=!0);break;case"success":case"idle":e=t.data??t.placeholderData,s=t.data?!1:!!t.placeholderData;break}return {data:e,error:t.error,status:t.status,updatedAt:t.updatedAt,isStale:a,isPlaceholderData:s,isLoading:t.status==="fetching"&&!t.updatedAt,isFetching:t.status==="fetching",isError:t.isError,isSuccess:t.isSuccess,refetch:t.refetch}}function Q(t){console.warn(`[qortex] No fetcher or data for key "${c(t)}". Register a fetcher or set initial data.`);}var h=class{constructor(){this.cache=new Map;this.subs=new Map;this.defaultConfig={};this.throttleTime=50;this.persister=null;this.hasQueriesBeenUsed=!1;}dangerClearCache(){this.cache.clear(),this.subs.clear(),this.persister?.clear();}setDefaultConfig({throttleTime:r,persister:a,...e}){this.defaultConfig={...this.defaultConfig,...e},r!==void 0&&(this.throttleTime=r),a&&(this.persister=a,this.persister?.load(this.cache,this.hasQueriesBeenUsed,this.defaultConfig));}ensureState(r,a={}){this.hasQueriesBeenUsed=!0;let e=c(r),s=this.cache.get(e);if(s){let n={...this.defaultConfig,...s,...a};Object.assign(s,n),s.enabled=n.enabled!==!1,this.cache.set(e,s);}else {let n={...this.defaultConfig,...a},u=p(n,()=>this.fetchQuery(r));this.cache.set(e,u);}return this.persister?.sync(this.cache,this.defaultConfig),this.cache.get(e)}emit(r,a){let e=c(r);this.cache.set(e,a),this.persister?.sync(this.cache,this.defaultConfig);let s=this.subs.get(e);if(!s)return;let n=f(a);for(let u of Array.from(s))u(n);}registerFetcher(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);}fetchQuery(r,a){let e=this.ensureState(r,a);if(e.fetchPromise)return e.fetchPromise;let s=e.fetcher;if(!s)return e.updatedAt===void 0&&Q(r),Promise.resolve(e.data);let n=s();return e.fetchPromise=n,e.status="fetching",e.lastFetchTime=Date.now(),this.emit(r,e),n.then(u=>{let o=d(e.equalityStrategy,e.equalityFn);e.data=o(e.data,u)?e.data:u,e.status="success",e.isError=!1,e.isSuccess=!0,e.updatedAt=Date.now(),e.fetchPromise=void 0,e.error=void 0,this.emit(r,e);}).catch(u=>{e.error=u,e.status="error",e.isError=!0,e.isSuccess=!1,e.updatedAt=Date.now(),e.fetchPromise=void 0,this.emit(r,e);}),n}setQueryData(r,a){let e=this.ensureState(r),s=e.data;d(e.equalityStrategy,e.equalityFn)(s,a)||(e.data=a,e.updatedAt=Date.now(),e.error=void 0,e.status="success",e.isInvalidated=!1,e.isError=!1,e.isSuccess=!0,this.emit(r,e));}getQueryData(r,a){let e=this.ensureState(r,a);return this.handleMountLogic(r,e),f(e).data}getQueryState(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);let s=f(e),n=e.lastReturnedState;return !n||!l(n,s,"shallow")?(e.lastReturnedState=s,s):n}invalidateQuery(r){let a=this.ensureState(r);a.isInvalidated=!0,this.emit(r,a),this.fetchQuery(r);}subscribeQuery(r,a,e){let s=c(r),n=this.ensureState(r,e);return this.subs.has(s)||this.subs.set(s,new Set),this.subs.get(s).add(a),this.handleMountLogic(r,n),()=>{this.subs.get(s).delete(a);}}handleMountLogic(r,a){let e=a.lastFetchTime&&Date.now()-a.lastFetchTime<this.throttleTime;if(a.status==="fetching"||!a.enabled||e||!a.fetcher)return;let s=Date.now(),n=a.updatedAt==null||s-(a.updatedAt||0)>a.staleTime||a.isInvalidated,u=!1;a.updatedAt==null?u=!0:(a.refetchOnSubscribe==="always"&&(u=!0),a.refetchOnSubscribe==="stale"&&(u=n)),u&&this.fetchQuery(r);}},g=h;var i=new g;var D=i.registerFetcher.bind(i),O=i.fetchQuery.bind(i),K=i.setQueryData.bind(i),x=i.getQueryData.bind(i),E=i.getQueryState.bind(i),w=i.invalidateQuery.bind(i),A=i.subscribeQuery.bind(i),q=i.setDefaultConfig.bind(i),I=i.dangerClearCache.bind(i);
4
4
 
5
5
  exports.QueryManagerCore = h;
6
6
  exports._queryManager = i;
7
- exports.dangerClearCache = q;
7
+ exports.dangerClearCache = I;
8
8
  exports.fetchQuery = O;
9
- exports.getQueryData = C;
9
+ exports.getQueryData = x;
10
10
  exports.getQueryState = E;
11
11
  exports.invalidateQuery = w;
12
12
  exports.registerFetcher = D;
13
13
  exports.serializeKey = c;
14
- exports.setDefaultConfig = A;
14
+ exports.setDefaultConfig = q;
15
15
  exports.setQueryData = K;
16
- exports.subscribeQuery = x;
16
+ exports.subscribeQuery = A;
package/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- function c(t){return Array.isArray(t)?t.join(","):String(t)}function l(t,r,a="shallow"){if(t===r)return !0;if(t==null||r==null)return t===r;if(typeof t!="object"||typeof r!="object")return !1;try{let e=t,s=r;if(Array.isArray(e)&&Array.isArray(s)){if(e.length!==s.length)return !1;for(let o=0;o<e.length;o++)if(a==="deep"){if(!l(e[o],s[o],a))return !1}else if(e[o]!==s[o])return !1;return !0}if(Array.isArray(e)||Array.isArray(s))return !1;let n=Object.keys(e),u=Object.keys(s);if(n.length!==u.length)return !1;for(let o=0;o<n.length;o++){let y=n[o];if(a==="deep"){if(!l(e[y],s[y],a))return !1}else if(e[y]!==s[y])return !1}return !0}catch{return !1}}function d(t,r){return r||((a,e)=>l(a,e,t||"shallow"))}function Q(t,r){return {status:"idle",updatedAt:void 0,staleTime:t?.staleTime??0,isInvalidated:!1,fetcher:t?.fetcher,equalityFn:d(t?.equalityStrategy,t?.equalityFn),equalityStrategy:t?.equalityStrategy??"shallow",placeholderData:t?.placeholderData,usePreviousDataOnError:t?.usePreviousDataOnError??!1,usePlaceholderOnError:t?.usePlaceholderOnError??!1,refetchOnSubscribe:t?.refetchOnSubscribe??"stale",enabled:t?.enabled!==!1,refetch:r||(()=>Promise.resolve(void 0)),isSuccess:!1,isError:!1,lastReturnedState:void 0}}function f(t){let r=Date.now(),a=t.updatedAt!==void 0&&r-t.updatedAt>t.staleTime||t.isInvalidated,e,s=!1;switch(t.status){case"error":t.usePreviousDataOnError&&t.data!==void 0?e=t.data:t.usePlaceholderOnError&&t.placeholderData!==void 0&&(e=t.placeholderData,s=!0);break;case"fetching":t.data!==void 0?(e=t.data,s=!1):t.placeholderData&&(e=t.placeholderData,s=!0);break;case"success":case"idle":e=t.data??t.placeholderData,s=t.data?!1:!!t.placeholderData;break}return {data:e,error:t.error,status:t.status,updatedAt:t.updatedAt,isStale:a,isPlaceholderData:s,isLoading:t.status==="fetching"&&!t.updatedAt,isFetching:t.status==="fetching",isError:t.isError,isSuccess:t.isSuccess,refetch:t.refetch}}function p(t){console.warn(`[qortex] No fetcher or data for key "${c(t)}". Register a fetcher or set initial data.`);}var h=class{constructor(){this.cache=new Map;this.subs=new Map;this.defaultConfig={};this.throttleTime=50;this.persister=null;this.hasQueriesBeenUsed=!1;}dangerClearCache(){this.cache.clear(),this.subs.clear(),this.persister?.clear();}setDefaultConfig({throttleTime:r,persister:a,...e}){this.defaultConfig={...this.defaultConfig,...e},r!==void 0&&(this.throttleTime=r),a&&(this.persister=a,this.persister?.load(this.cache,this.hasQueriesBeenUsed));}ensureState(r,a={}){this.hasQueriesBeenUsed=!0;let e=c(r),s=this.cache.get(e);if(s){let n={...this.defaultConfig,...s,...a};Object.assign(s,n),s.enabled=n.enabled!==!1,this.cache.set(e,s);}else {let n={...this.defaultConfig,...a},u=Q(n,()=>this.fetchQuery(r));this.cache.set(e,u);}return this.cache.get(e)}emit(r,a){let e=c(r);this.cache.set(e,a),this.persister?.sync(this.cache);let s=this.subs.get(e);if(!s)return;let n=f(a);for(let u of Array.from(s))u(n);}registerFetcher(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);}fetchQuery(r,a){let e=this.ensureState(r,a);if(e.fetchPromise)return e.fetchPromise;let s=e.fetcher;if(!s)return e.updatedAt===void 0&&p(r),Promise.resolve(e.data);let n=s();return e.fetchPromise=n,e.status="fetching",e.lastFetchTime=Date.now(),this.emit(r,e),n.then(u=>{let o=d(e.equalityStrategy,e.equalityFn);e.data=o(e.data,u)?e.data:u,e.status="success",e.isError=!1,e.isSuccess=!0,e.updatedAt=Date.now(),e.fetchPromise=void 0,e.error=void 0,this.emit(r,e);}).catch(u=>{e.error=u,e.status="error",e.isError=!0,e.isSuccess=!1,e.updatedAt=Date.now(),e.fetchPromise=void 0,this.emit(r,e);}),n}setQueryData(r,a){let e=this.ensureState(r),s=e.data;d(e.equalityStrategy,e.equalityFn)(s,a)||(e.data=a,e.updatedAt=Date.now(),e.error=void 0,e.status="success",e.isInvalidated=!1,e.isError=!1,e.isSuccess=!0,this.emit(r,e));}getQueryData(r,a){let e=this.ensureState(r,a);return this.handleMountLogic(r,e),f(e).data}getQueryState(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);let s=f(e),n=e.lastReturnedState;return !n||!l(n,s,"shallow")?(e.lastReturnedState=s,s):n}invalidateQuery(r){let a=this.ensureState(r);a.isInvalidated=!0,this.emit(r,a),this.fetchQuery(r);}subscribeQuery(r,a,e){let s=c(r),n=this.ensureState(r,e);return this.subs.has(s)||this.subs.set(s,new Set),this.subs.get(s).add(a),this.handleMountLogic(r,n),()=>{this.subs.get(s).delete(a);}}handleMountLogic(r,a){let e=a.lastFetchTime&&Date.now()-a.lastFetchTime<this.throttleTime;if(a.status==="fetching"||!a.enabled||e||!a.fetcher)return;let s=Date.now(),n=a.updatedAt==null||s-(a.updatedAt||0)>a.staleTime||a.isInvalidated,u=!1;a.updatedAt==null?u=!0:(a.refetchOnSubscribe==="always"&&(u=!0),a.refetchOnSubscribe==="stale"&&(u=n)),u&&this.fetchQuery(r);}},g=h;var i=new g,D=i.registerFetcher.bind(i),O=i.fetchQuery.bind(i),K=i.setQueryData.bind(i),C=i.getQueryData.bind(i),E=i.getQueryState.bind(i),w=i.invalidateQuery.bind(i),x=i.subscribeQuery.bind(i),A=i.setDefaultConfig.bind(i),q=i.dangerClearCache.bind(i);
1
+ function c(t){return Array.isArray(t)?t.join("-"):String(t)}function l(t,r,a="shallow"){if(t===r)return !0;if(t==null||r==null)return t===r;if(typeof t!="object"||typeof r!="object")return !1;try{let e=t,s=r;if(Array.isArray(e)&&Array.isArray(s)){if(e.length!==s.length)return !1;for(let o=0;o<e.length;o++)if(a==="deep"){if(!l(e[o],s[o],a))return !1}else if(e[o]!==s[o])return !1;return !0}if(Array.isArray(e)||Array.isArray(s))return !1;let n=Object.keys(e),u=Object.keys(s);if(n.length!==u.length)return !1;for(let o=0;o<n.length;o++){let y=n[o];if(a==="deep"){if(!l(e[y],s[y],a))return !1}else if(e[y]!==s[y])return !1}return !0}catch{return !1}}function d(t,r){return r||((a,e)=>l(a,e,t||"shallow"))}function p(t,r){return {status:"idle",updatedAt:void 0,staleTime:t?.staleTime??0,isInvalidated:!1,fetcher:t?.fetcher,equalityFn:d(t?.equalityStrategy,t?.equalityFn),equalityStrategy:t?.equalityStrategy??"shallow",placeholderData:t?.placeholderData,usePreviousDataOnError:t?.usePreviousDataOnError??!1,usePlaceholderOnError:t?.usePlaceholderOnError??!1,refetchOnSubscribe:t?.refetchOnSubscribe??"stale",enabled:t?.enabled!==!1,refetch:r||(()=>Promise.resolve(void 0)),isSuccess:!1,isError:!1,lastReturnedState:void 0}}function f(t){let r=Date.now(),a=t.updatedAt!==void 0&&r-t.updatedAt>t.staleTime||t.isInvalidated,e,s=!1;switch(t.status){case"error":t.usePreviousDataOnError&&t.data!==void 0?e=t.data:t.usePlaceholderOnError&&t.placeholderData!==void 0&&(e=t.placeholderData,s=!0);break;case"fetching":t.data!==void 0?(e=t.data,s=!1):t.placeholderData&&(e=t.placeholderData,s=!0);break;case"success":case"idle":e=t.data??t.placeholderData,s=t.data?!1:!!t.placeholderData;break}return {data:e,error:t.error,status:t.status,updatedAt:t.updatedAt,isStale:a,isPlaceholderData:s,isLoading:t.status==="fetching"&&!t.updatedAt,isFetching:t.status==="fetching",isError:t.isError,isSuccess:t.isSuccess,refetch:t.refetch}}function Q(t){console.warn(`[qortex] No fetcher or data for key "${c(t)}". Register a fetcher or set initial data.`);}var h=class{constructor(){this.cache=new Map;this.subs=new Map;this.defaultConfig={};this.throttleTime=50;this.persister=null;this.hasQueriesBeenUsed=!1;}dangerClearCache(){this.cache.clear(),this.subs.clear(),this.persister?.clear();}setDefaultConfig({throttleTime:r,persister:a,...e}){this.defaultConfig={...this.defaultConfig,...e},r!==void 0&&(this.throttleTime=r),a&&(this.persister=a,this.persister?.load(this.cache,this.hasQueriesBeenUsed,this.defaultConfig));}ensureState(r,a={}){this.hasQueriesBeenUsed=!0;let e=c(r),s=this.cache.get(e);if(s){let n={...this.defaultConfig,...s,...a};Object.assign(s,n),s.enabled=n.enabled!==!1,this.cache.set(e,s);}else {let n={...this.defaultConfig,...a},u=p(n,()=>this.fetchQuery(r));this.cache.set(e,u);}return this.persister?.sync(this.cache,this.defaultConfig),this.cache.get(e)}emit(r,a){let e=c(r);this.cache.set(e,a),this.persister?.sync(this.cache,this.defaultConfig);let s=this.subs.get(e);if(!s)return;let n=f(a);for(let u of Array.from(s))u(n);}registerFetcher(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);}fetchQuery(r,a){let e=this.ensureState(r,a);if(e.fetchPromise)return e.fetchPromise;let s=e.fetcher;if(!s)return e.updatedAt===void 0&&Q(r),Promise.resolve(e.data);let n=s();return e.fetchPromise=n,e.status="fetching",e.lastFetchTime=Date.now(),this.emit(r,e),n.then(u=>{let o=d(e.equalityStrategy,e.equalityFn);e.data=o(e.data,u)?e.data:u,e.status="success",e.isError=!1,e.isSuccess=!0,e.updatedAt=Date.now(),e.fetchPromise=void 0,e.error=void 0,this.emit(r,e);}).catch(u=>{e.error=u,e.status="error",e.isError=!0,e.isSuccess=!1,e.updatedAt=Date.now(),e.fetchPromise=void 0,this.emit(r,e);}),n}setQueryData(r,a){let e=this.ensureState(r),s=e.data;d(e.equalityStrategy,e.equalityFn)(s,a)||(e.data=a,e.updatedAt=Date.now(),e.error=void 0,e.status="success",e.isInvalidated=!1,e.isError=!1,e.isSuccess=!0,this.emit(r,e));}getQueryData(r,a){let e=this.ensureState(r,a);return this.handleMountLogic(r,e),f(e).data}getQueryState(r,a){let e=this.ensureState(r,a);this.handleMountLogic(r,e);let s=f(e),n=e.lastReturnedState;return !n||!l(n,s,"shallow")?(e.lastReturnedState=s,s):n}invalidateQuery(r){let a=this.ensureState(r);a.isInvalidated=!0,this.emit(r,a),this.fetchQuery(r);}subscribeQuery(r,a,e){let s=c(r),n=this.ensureState(r,e);return this.subs.has(s)||this.subs.set(s,new Set),this.subs.get(s).add(a),this.handleMountLogic(r,n),()=>{this.subs.get(s).delete(a);}}handleMountLogic(r,a){let e=a.lastFetchTime&&Date.now()-a.lastFetchTime<this.throttleTime;if(a.status==="fetching"||!a.enabled||e||!a.fetcher)return;let s=Date.now(),n=a.updatedAt==null||s-(a.updatedAt||0)>a.staleTime||a.isInvalidated,u=!1;a.updatedAt==null?u=!0:(a.refetchOnSubscribe==="always"&&(u=!0),a.refetchOnSubscribe==="stale"&&(u=n)),u&&this.fetchQuery(r);}},g=h;var i=new g;var D=i.registerFetcher.bind(i),O=i.fetchQuery.bind(i),K=i.setQueryData.bind(i),x=i.getQueryData.bind(i),E=i.getQueryState.bind(i),w=i.invalidateQuery.bind(i),A=i.subscribeQuery.bind(i),q=i.setDefaultConfig.bind(i),I=i.dangerClearCache.bind(i);
2
2
 
3
- export { h as QueryManagerCore, i as _queryManager, q as dangerClearCache, O as fetchQuery, C as getQueryData, E as getQueryState, w as invalidateQuery, D as registerFetcher, c as serializeKey, A as setDefaultConfig, K as setQueryData, x as subscribeQuery };
3
+ export { h as QueryManagerCore, i as _queryManager, I as dangerClearCache, O as fetchQuery, x as getQueryData, E as getQueryState, w as invalidateQuery, D as registerFetcher, c as serializeKey, q as setDefaultConfig, K as setQueryData, A as subscribeQuery };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qortex-core",
3
- "version": "0.3.0-beta.4",
3
+ "version": "0.3.0-beta.6",
4
4
  "description": "Framework-agnostic query cache & fetch registry (MFE friendly).",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -12,10 +12,10 @@
12
12
  "import": "./index.mjs",
13
13
  "require": "./index.js"
14
14
  },
15
- "./persister-export": {
16
- "types": "./persister-export.d.ts",
17
- "import": "./persister-export.mjs",
18
- "require": "./persister-export.js"
15
+ "./persister": {
16
+ "types": "./persister.d.ts",
17
+ "import": "./persister.mjs",
18
+ "require": "./persister.js"
19
19
  }
20
20
  },
21
21
  "publishConfig": {
@@ -25,9 +25,10 @@
25
25
  "index.js",
26
26
  "index.mjs",
27
27
  "index.d.ts",
28
- "persister-export.js",
29
- "persister-export.mjs",
30
- "persister-export.d.ts",
28
+ "persister.js",
29
+ "persister.mjs",
30
+ "persister.d.ts",
31
+ "types-96ae2039.d.ts",
31
32
  "README.md"
32
33
  ],
33
34
  "repository": {
@@ -1,5 +1,5 @@
1
- import { P as PersisterConfig, B as BasePersister } from './types-14ced1fe.js';
2
- export { e as Persister } from './types-14ced1fe.js';
1
+ import { P as PersisterConfig, B as BasePersister } from './types-96ae2039.js';
2
+ export { e as Persister } from './types-96ae2039.js';
3
3
 
4
4
  /**
5
5
  * Creates a persister instance for data persistence.
package/persister.js ADDED
@@ -0,0 +1,5 @@
1
+ 'use strict';
2
+
3
+ function w(e){return typeof e=="string"&&["idle","fetching","success","error"].includes(e)}function x(e){return typeof e=="string"&&["shallow","deep"].includes(e)}function T(e){return e===!1||typeof e=="string"&&["always","stale"].includes(e)}function q(e){return !(!e||typeof e!="object"||!w(e.status)||typeof e.staleTime!="number"||e.staleTime<0||typeof e.isInvalidated!="boolean"||!x(e.equalityStrategy)||!T(e.refetchOnSubscribe))}function c(e){if(!e||typeof e!="object"||!e.queries||typeof e.queries!="object")return !1;for(let[t,r]of Object.entries(e.queries))if(typeof t!="string"||!q(r))return !1;return !(typeof e.burstKey!="string"||typeof e.timestamp!="number"||e.timestamp<0)}function p(e){let{fetcher:t,equalityFn:r,fetchPromise:s,refetch:a,...i}=e;return i}function d(e,t){return {...t??{},...e}}function S(e){try{let t=JSON.parse(e);return c(t)?t:null}catch{return null}}var m=()=>{console.warn("[Qortex] No storage found, persister will not be able to persist data");},g=()=>{console.warn("[Qortex] Persister is being set after queries have been used. This may cause data inconsistency. It is recommended to set the persister before any query usage.");};var o=class{constructor(t,r){this.syncTimeout=null;this.debounceTime=100;this.burstKey="0.3.0";this.storageKey="qortex";this.storage=t,this.burstKey=r?.burstKey??this.burstKey,this.storageKey=r?.prefix??this.storageKey,this.debounceTime=r?.debounceTime??this.debounceTime;}save(t,r){try{let s={queries:{},burstKey:this.burstKey,timestamp:Date.now(),defaultConfig:r};for(let[i,n]of Object.entries(t))s.queries[i]=n;let a=JSON.stringify(s);this.storage.setItem(this.storageKey,a);}catch(s){console.warn("[Qortex] Failed to persist state:",s);}}load(t,r,s){r&&g();try{let a=this.storage.getItem(this.storageKey);if(!a)return;let i=S(a);if(!i){console.warn("[Qortex] Invalid persisted state format, clearing cache"),this.clear();return}if(i.burstKey!==this.burstKey){console.warn("[Qortex] Burst key mismatch, clearing cache"),this.clear();return}let n=i.defaultConfig||{},h=this.hasDefaultConfigChanged(n,s);for(let[u,b]of Object.entries(i.queries)){let Q=b,P=t.get(u),l=d(Q,P);h&&(Object.keys(s).forEach(f=>{let y=s[f];y!==void 0&&(l[f]=y);}),l.enabled=s.enabled!==!1),t.set(u,l);}}catch(a){console.warn("[Qortex] Failed to load persisted state:",a),this.clear();}}hasDefaultConfigChanged(t,r){return !t||Object.keys(t).length===0?!0:Object.keys(r).some(s=>t[s]!==r[s])}clear(){try{this.storage.removeItem(this.storageKey);}catch(t){console.warn("[Qortex] Failed to clear persisted data:",t);}}sync(t,r){this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>{let s={};for(let[a,i]of t.entries())s[a]=p(i);this.save(s,r);},this.debounceTime);}};var C=e=>{switch(e){case"local":if(typeof localStorage<"u")return window.localStorage;break;case"session":if(typeof sessionStorage<"u")return window.sessionStorage;break;default:throw new Error(`Invalid storage type: ${e}`)}},v=(e,t)=>{let r=C(e);if(!r){m();return}return new o(r,t)};
4
+
5
+ exports.createPersister = v;
package/persister.mjs ADDED
@@ -0,0 +1,3 @@
1
+ function w(e){return typeof e=="string"&&["idle","fetching","success","error"].includes(e)}function x(e){return typeof e=="string"&&["shallow","deep"].includes(e)}function T(e){return e===!1||typeof e=="string"&&["always","stale"].includes(e)}function q(e){return !(!e||typeof e!="object"||!w(e.status)||typeof e.staleTime!="number"||e.staleTime<0||typeof e.isInvalidated!="boolean"||!x(e.equalityStrategy)||!T(e.refetchOnSubscribe))}function c(e){if(!e||typeof e!="object"||!e.queries||typeof e.queries!="object")return !1;for(let[t,r]of Object.entries(e.queries))if(typeof t!="string"||!q(r))return !1;return !(typeof e.burstKey!="string"||typeof e.timestamp!="number"||e.timestamp<0)}function p(e){let{fetcher:t,equalityFn:r,fetchPromise:s,refetch:a,...i}=e;return i}function d(e,t){return {...t??{},...e}}function S(e){try{let t=JSON.parse(e);return c(t)?t:null}catch{return null}}var m=()=>{console.warn("[Qortex] No storage found, persister will not be able to persist data");},g=()=>{console.warn("[Qortex] Persister is being set after queries have been used. This may cause data inconsistency. It is recommended to set the persister before any query usage.");};var o=class{constructor(t,r){this.syncTimeout=null;this.debounceTime=100;this.burstKey="0.3.0";this.storageKey="qortex";this.storage=t,this.burstKey=r?.burstKey??this.burstKey,this.storageKey=r?.prefix??this.storageKey,this.debounceTime=r?.debounceTime??this.debounceTime;}save(t,r){try{let s={queries:{},burstKey:this.burstKey,timestamp:Date.now(),defaultConfig:r};for(let[i,n]of Object.entries(t))s.queries[i]=n;let a=JSON.stringify(s);this.storage.setItem(this.storageKey,a);}catch(s){console.warn("[Qortex] Failed to persist state:",s);}}load(t,r,s){r&&g();try{let a=this.storage.getItem(this.storageKey);if(!a)return;let i=S(a);if(!i){console.warn("[Qortex] Invalid persisted state format, clearing cache"),this.clear();return}if(i.burstKey!==this.burstKey){console.warn("[Qortex] Burst key mismatch, clearing cache"),this.clear();return}let n=i.defaultConfig||{},h=this.hasDefaultConfigChanged(n,s);for(let[u,b]of Object.entries(i.queries)){let Q=b,P=t.get(u),l=d(Q,P);h&&(Object.keys(s).forEach(f=>{let y=s[f];y!==void 0&&(l[f]=y);}),l.enabled=s.enabled!==!1),t.set(u,l);}}catch(a){console.warn("[Qortex] Failed to load persisted state:",a),this.clear();}}hasDefaultConfigChanged(t,r){return !t||Object.keys(t).length===0?!0:Object.keys(r).some(s=>t[s]!==r[s])}clear(){try{this.storage.removeItem(this.storageKey);}catch(t){console.warn("[Qortex] Failed to clear persisted data:",t);}}sync(t,r){this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>{let s={};for(let[a,i]of t.entries())s[a]=p(i);this.save(s,r);},this.debounceTime);}};var C=e=>{switch(e){case"local":if(typeof localStorage<"u")return window.localStorage;break;case"session":if(typeof sessionStorage<"u")return window.sessionStorage;break;default:throw new Error(`Invalid storage type: ${e}`)}},v=(e,t)=>{let r=C(e);if(!r){m();return}return new o(r,t)};
2
+
3
+ export { v as createPersister };
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Internal query state that tracks all aspects of a query's lifecycle
3
+ * Used internally by QueryManager for state management
4
+ * NOT EXPORTED - internal implementation detail
5
+ */
6
+ type QueryStateInternal<T = any, E = unknown> = {
7
+ data?: T;
8
+ error?: E;
9
+ status: QueryStatus;
10
+ updatedAt?: number;
11
+ staleTime: number;
12
+ isInvalidated: boolean;
13
+ fetcher?: Fetcher<T> | null;
14
+ equalityFn?: EqualityFn<T>;
15
+ equalityStrategy: EqualityStrategy;
16
+ placeholderData?: T;
17
+ usePreviousDataOnError?: boolean;
18
+ usePlaceholderOnError?: boolean;
19
+ refetchOnSubscribe: "always" | "stale" | false;
20
+ enabled: boolean;
21
+ lastFetchTime?: number;
22
+ fetchPromise?: Promise<T> | T;
23
+ refetch?: () => Promise<T>;
24
+ isSuccess: boolean;
25
+ isError: boolean;
26
+ lastReturnedState?: QueryState<T>;
27
+ };
28
+
29
+ type SerializedQueryState = Omit<QueryStateInternal, 'fetcher' | 'fetchPromise' | 'refetch' | 'equalityFn'>;
30
+ /**
31
+ * Persister configuration
32
+ */
33
+ interface PersisterConfig {
34
+ burstKey?: string;
35
+ prefix?: string;
36
+ debounceTime?: number;
37
+ }
38
+
39
+ /**
40
+ * Base persister implementation
41
+ */
42
+ declare class BasePersister {
43
+ protected readonly storage: Storage;
44
+ private syncTimeout;
45
+ private debounceTime;
46
+ private burstKey;
47
+ private storageKey;
48
+ constructor(storage: Storage, config?: PersisterConfig);
49
+ /**
50
+ * Save state to storage
51
+ */
52
+ save(state: Record<string, SerializedQueryState>, defaultConfig?: DefaultConfig): void;
53
+ /**
54
+ * Load state from storage and hydrate cache
55
+ */
56
+ load(cache: Map<string, QueryStateInternal>, hasQueriesBeenUsed: boolean, currentDefaultConfig: DefaultConfig): void;
57
+ /**
58
+ * Checks if the default config has changed by comparing stored and current configs
59
+ */
60
+ private hasDefaultConfigChanged;
61
+ /**
62
+ * Clear all persisted data
63
+ */
64
+ clear(): void;
65
+ /**
66
+ * Sync with debounced save (100ms delay)
67
+ * Handles serialization internally
68
+ */
69
+ sync(cache: Map<string, QueryStateInternal>, defaultConfig?: DefaultConfig): void;
70
+ }
71
+ type Persister = BasePersister;
72
+
73
+ /**
74
+ * Query key can be a string or readonly array of strings/numbers
75
+ * Using readonly to prevent accidental mutations
76
+ */
77
+ type QueryKey = string | readonly (string | number)[];
78
+ /** Function that fetches data, must be async */
79
+ type Fetcher<T = any> = () => Promise<T>;
80
+ /** Function that compares two values for equality */
81
+ type EqualityFn<T = any> = (a: T | undefined, b: T | undefined) => boolean;
82
+ /** Strategy for equality comparison */
83
+ type EqualityStrategy = 'shallow' | 'deep';
84
+ /**
85
+ * Infers the return type of a fetcher function
86
+ *
87
+ * This utility type extracts the return type from a fetcher function,
88
+ * handling both synchronous and asynchronous fetchers.
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const fetchUser = async (id: string): Promise<User> => { ... };
93
+ * type UserType = InferFetcherResult<typeof fetchUser>; // Promise<User>
94
+ *
95
+ * const fetchConfig = (): Config => { ... };
96
+ * type ConfigType = InferFetcherResult<typeof fetchConfig>; // Config
97
+ * ```
98
+ *
99
+ * @template F - The fetcher function type
100
+ * @returns The inferred return type of the fetcher, or `any` if inference fails
101
+ */
102
+ type InferFetcherResult<F> = F extends Fetcher<infer R> ? R : any;
103
+ /**
104
+ * Query status types for better type safety
105
+ */
106
+ type QueryStatus = "idle" | "fetching" | "success" | "error";
107
+ type RefetchOnSubscribeOptions = "always" | "stale" | false;
108
+ /**
109
+ * Comprehensive options for all query operations
110
+ * Improved with better type constraints
111
+ */
112
+ type QueryOptions<T = any> = {
113
+ enabled?: boolean;
114
+ refetchOnSubscribe?: RefetchOnSubscribeOptions;
115
+ fetcher?: Fetcher<T>;
116
+ equalityFn?: EqualityFn<T>;
117
+ equalityStrategy?: EqualityStrategy;
118
+ staleTime?: number;
119
+ signal?: AbortSignal;
120
+ placeholderData?: T;
121
+ usePreviousDataOnError?: boolean;
122
+ usePlaceholderOnError?: boolean;
123
+ };
124
+ /**
125
+ * Default configuration options that can be set globally
126
+ * Includes throttleTime which is not part of regular QueryOptions
127
+ */
128
+ type DefaultConfig = {
129
+ enabled?: boolean;
130
+ refetchOnSubscribe?: RefetchOnSubscribeOptions;
131
+ staleTime?: number;
132
+ usePreviousDataOnError?: boolean;
133
+ usePlaceholderOnError?: boolean;
134
+ equalityFn?: EqualityFn<any>;
135
+ equalityStrategy?: EqualityStrategy;
136
+ throttleTime?: number;
137
+ persister?: Persister;
138
+ };
139
+ /**
140
+ * Public query state returned by getQueryState
141
+ * Improved with stricter error typing and better generic constraints
142
+ */
143
+ type QueryState<T = any, E = unknown> = {
144
+ data?: T;
145
+ error?: E;
146
+ status: QueryStatus;
147
+ updatedAt?: number;
148
+ isStale: boolean;
149
+ isPlaceholderData: boolean;
150
+ isLoading: boolean;
151
+ isFetching: boolean;
152
+ isError: boolean;
153
+ isSuccess: boolean;
154
+ refetch: () => Promise<T>;
155
+ };
156
+
157
+ export { BasePersister as B, DefaultConfig as D, EqualityFn as E, Fetcher as F, InferFetcherResult as I, PersisterConfig as P, QueryKey as Q, RefetchOnSubscribeOptions as R, QueryOptions as a, QueryState as b, EqualityStrategy as c, QueryStatus as d, Persister as e };
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- function g(e){return typeof e=="string"&&["idle","fetching","success","error"].includes(e)}function h(e){return typeof e=="string"&&["shallow","deep"].includes(e)}function b(e){return e===!1||typeof e=="string"&&["always","stale"].includes(e)}function Q(e){return !(!e||typeof e!="object"||!g(e.status)||typeof e.staleTime!="number"||e.staleTime<0||typeof e.isInvalidated!="boolean"||!h(e.equalityStrategy)||!b(e.refetchOnSubscribe))}function n(e){if(!e||typeof e!="object"||!e.entries||typeof e.entries!="object")return !1;for(let[t,r]of Object.entries(e.entries))if(typeof t!="string"||!Q(r))return !1;return !(typeof e.burstKey!="string"||typeof e.timestamp!="number"||e.timestamp<0)}function l(e){let{fetcher:t,equalityFn:r,fetchPromise:s,refetch:i,...a}=e;return a}function u(e,t){return {...t??{},...e}}function y(e){try{let t=JSON.parse(e);return n(t)?t:null}catch{return null}}var f=()=>{console.warn("[Qortex] No storage found, persister will not be able to persist data");},c=()=>{console.warn("[Qortex] Persister is being set after queries have been used. This may cause data inconsistency. It is recommended to set the persister before any query usage.");};var o=class{constructor(t,r){this.syncTimeout=null;this.debounceTime=100;this.burstKey="0.3.0";this.storageKey="qortex";this.storage=t,this.burstKey=r?.burstKey??this.burstKey,this.storageKey=r?.prefix??this.storageKey,this.debounceTime=r?.debounceTime??this.debounceTime;}save(t){try{let r={entries:{},burstKey:this.burstKey,timestamp:Date.now()};for(let[i,a]of Object.entries(t))r.entries[i]=a;let s=JSON.stringify(r);this.storage.setItem(this.storageKey,s);}catch(r){console.warn("[Qortex] Failed to persist state:",r);}}load(t,r){r&&c();try{let s=this.storage.getItem(this.storageKey);if(!s)return;let i=y(s);if(!i){console.warn("[Qortex] Invalid persisted state format, clearing cache"),this.clear();return}if(i.burstKey!==this.burstKey){console.warn("[Qortex] Burst key mismatch, clearing cache"),this.clear();return}for(let[a,p]of Object.entries(i.entries)){let S=p,d=t.get(a),m=u(S,d);t.set(a,m);}}catch(s){console.warn("[Qortex] Failed to load persisted state:",s),this.clear();}}clear(){try{this.storage.removeItem(this.storageKey);}catch(t){console.warn("[Qortex] Failed to clear persisted data:",t);}}sync(t){this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>{let r={};for(let[s,i]of t.entries())r[s]=l(i);this.save(r);},this.debounceTime);}};var P=e=>{switch(e){case"local":if(typeof localStorage<"u")return window.localStorage;break;case"session":if(typeof sessionStorage<"u")return window.sessionStorage;break;default:throw new Error(`Invalid storage type: ${e}`)}},w=(e,t)=>{let r=P(e);if(!r){f();return}return new o(r,t)};
4
-
5
- exports.createPersister = w;
@@ -1,3 +0,0 @@
1
- function g(e){return typeof e=="string"&&["idle","fetching","success","error"].includes(e)}function h(e){return typeof e=="string"&&["shallow","deep"].includes(e)}function b(e){return e===!1||typeof e=="string"&&["always","stale"].includes(e)}function Q(e){return !(!e||typeof e!="object"||!g(e.status)||typeof e.staleTime!="number"||e.staleTime<0||typeof e.isInvalidated!="boolean"||!h(e.equalityStrategy)||!b(e.refetchOnSubscribe))}function n(e){if(!e||typeof e!="object"||!e.entries||typeof e.entries!="object")return !1;for(let[t,r]of Object.entries(e.entries))if(typeof t!="string"||!Q(r))return !1;return !(typeof e.burstKey!="string"||typeof e.timestamp!="number"||e.timestamp<0)}function l(e){let{fetcher:t,equalityFn:r,fetchPromise:s,refetch:i,...a}=e;return a}function u(e,t){return {...t??{},...e}}function y(e){try{let t=JSON.parse(e);return n(t)?t:null}catch{return null}}var f=()=>{console.warn("[Qortex] No storage found, persister will not be able to persist data");},c=()=>{console.warn("[Qortex] Persister is being set after queries have been used. This may cause data inconsistency. It is recommended to set the persister before any query usage.");};var o=class{constructor(t,r){this.syncTimeout=null;this.debounceTime=100;this.burstKey="0.3.0";this.storageKey="qortex";this.storage=t,this.burstKey=r?.burstKey??this.burstKey,this.storageKey=r?.prefix??this.storageKey,this.debounceTime=r?.debounceTime??this.debounceTime;}save(t){try{let r={entries:{},burstKey:this.burstKey,timestamp:Date.now()};for(let[i,a]of Object.entries(t))r.entries[i]=a;let s=JSON.stringify(r);this.storage.setItem(this.storageKey,s);}catch(r){console.warn("[Qortex] Failed to persist state:",r);}}load(t,r){r&&c();try{let s=this.storage.getItem(this.storageKey);if(!s)return;let i=y(s);if(!i){console.warn("[Qortex] Invalid persisted state format, clearing cache"),this.clear();return}if(i.burstKey!==this.burstKey){console.warn("[Qortex] Burst key mismatch, clearing cache"),this.clear();return}for(let[a,p]of Object.entries(i.entries)){let S=p,d=t.get(a),m=u(S,d);t.set(a,m);}}catch(s){console.warn("[Qortex] Failed to load persisted state:",s),this.clear();}}clear(){try{this.storage.removeItem(this.storageKey);}catch(t){console.warn("[Qortex] Failed to clear persisted data:",t);}}sync(t){this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>{let r={};for(let[s,i]of t.entries())r[s]=l(i);this.save(r);},this.debounceTime);}};var P=e=>{switch(e){case"local":if(typeof localStorage<"u")return window.localStorage;break;case"session":if(typeof sessionStorage<"u")return window.sessionStorage;break;default:throw new Error(`Invalid storage type: ${e}`)}},w=(e,t)=>{let r=P(e);if(!r){f();return}return new o(r,t)};
2
-
3
- export { w as createPersister };