qortex-core 0.3.0-beta.1 → 0.3.0-beta.3

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.
Files changed (4) hide show
  1. package/index.d.ts +3 -196
  2. package/index.js +12 -13
  3. package/index.mjs +2 -2
  4. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -1,198 +1,5 @@
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>): void;
53
- /**
54
- * Load state from storage and hydrate cache
55
- */
56
- load(cache: Map<string, QueryStateInternal>, hasQueriesBeenUsed: boolean): void;
57
- /**
58
- * Clear all persisted data
59
- */
60
- clear(): void;
61
- /**
62
- * Sync with debounced save (100ms delay)
63
- * Handles serialization internally
64
- */
65
- sync(cache: Map<string, QueryStateInternal>): void;
66
- }
67
- type Persister = BasePersister;
68
-
69
- /**
70
- * Creates a persister instance for data persistence.
71
- *
72
- * This factory function creates a persister that can save and load query state data
73
- * to/from browser storage (localStorage or sessionStorage). The persister handles
74
- * serialization, validation, burst key management, and debounced syncing automatically.
75
- *
76
- * @param {'local' | 'session'} type - The type of storage to use
77
- * - `'local'`: Uses localStorage for persistent data across browser sessions
78
- * - `'session'`: Uses sessionStorage for data that persists only during the current session
79
- * @param {PersisterConfig} [config] - Optional configuration for the persister
80
- * @returns {Persister | undefined} A persister instance, or undefined if storage is not available
81
- *
82
- * @example
83
- * ```typescript
84
- * // Basic usage with localStorage
85
- * const persister = createPersister('local');
86
- *
87
- * // With custom configuration
88
- * const persister = createPersister('local', {
89
- * burstKey: 'v1.0.0',
90
- * prefix: 'my_app',
91
- * debounceTime: 50
92
- * });
93
- *
94
- * // Use with query manager
95
- * setDefaultConfig({ persister });
96
- * ```
97
- *
98
- * @example
99
- * ```typescript
100
- * // Session storage for temporary data
101
- * const sessionPersister = createPersister('session', {
102
- * prefix: 'temp_data',
103
- * debounceTime: 200
104
- * });
105
- *
106
- * setDefaultConfig({ persister: sessionPersister });
107
- * ```
108
- *
109
- * @throws {Error} If an invalid storage type is provided
110
- */
111
- declare const createPersister: (type: "local" | "session", config?: PersisterConfig) => BasePersister | undefined;
112
-
113
- /**
114
- * Query key can be a string or readonly array of strings/numbers
115
- * Using readonly to prevent accidental mutations
116
- */
117
- type QueryKey = string | readonly (string | number)[];
118
- /** Function that fetches data, must be async */
119
- type Fetcher<T = any> = () => Promise<T>;
120
- /** Function that compares two values for equality */
121
- type EqualityFn<T = any> = (a: T | undefined, b: T | undefined) => boolean;
122
- /** Strategy for equality comparison */
123
- type EqualityStrategy = 'shallow' | 'deep';
124
- /**
125
- * Infers the return type of a fetcher function
126
- *
127
- * This utility type extracts the return type from a fetcher function,
128
- * handling both synchronous and asynchronous fetchers.
129
- *
130
- * @example
131
- * ```typescript
132
- * const fetchUser = async (id: string): Promise<User> => { ... };
133
- * type UserType = InferFetcherResult<typeof fetchUser>; // Promise<User>
134
- *
135
- * const fetchConfig = (): Config => { ... };
136
- * type ConfigType = InferFetcherResult<typeof fetchConfig>; // Config
137
- * ```
138
- *
139
- * @template F - The fetcher function type
140
- * @returns The inferred return type of the fetcher, or `any` if inference fails
141
- */
142
- type InferFetcherResult<F> = F extends Fetcher<infer R> ? R : any;
143
- /**
144
- * Query status types for better type safety
145
- */
146
- type QueryStatus = "idle" | "fetching" | "success" | "error";
147
- type RefetchOnSubscribeOptions = "always" | "stale" | false;
148
- /**
149
- * Comprehensive options for all query operations
150
- * Improved with better type constraints
151
- */
152
- type QueryOptions<T = any> = {
153
- enabled?: boolean;
154
- refetchOnSubscribe?: RefetchOnSubscribeOptions;
155
- fetcher?: Fetcher<T>;
156
- equalityFn?: EqualityFn<T>;
157
- equalityStrategy?: EqualityStrategy;
158
- staleTime?: number;
159
- signal?: AbortSignal;
160
- placeholderData?: T;
161
- usePreviousDataOnError?: boolean;
162
- usePlaceholderOnError?: boolean;
163
- };
164
- /**
165
- * Default configuration options that can be set globally
166
- * Includes throttleTime which is not part of regular QueryOptions
167
- */
168
- type DefaultConfig = {
169
- enabled?: boolean;
170
- refetchOnSubscribe?: RefetchOnSubscribeOptions;
171
- staleTime?: number;
172
- usePreviousDataOnError?: boolean;
173
- usePlaceholderOnError?: boolean;
174
- equalityFn?: EqualityFn<any>;
175
- equalityStrategy?: EqualityStrategy;
176
- throttleTime?: number;
177
- persister?: Persister;
178
- };
179
- /**
180
- * Public query state returned by getQueryState
181
- * Improved with stricter error typing and better generic constraints
182
- */
183
- type QueryState<T = any, E = unknown> = {
184
- data?: T;
185
- error?: E;
186
- status: QueryStatus;
187
- updatedAt?: number;
188
- isStale: boolean;
189
- isPlaceholderData: boolean;
190
- isLoading: boolean;
191
- isFetching: boolean;
192
- isError: boolean;
193
- isSuccess: boolean;
194
- refetch: () => Promise<T>;
195
- };
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';
196
3
 
197
4
  /**
198
5
  * Core query manager that handles caching, fetching, and state management
@@ -318,4 +125,4 @@ declare const dangerClearCache: QueryManagerCore["dangerClearCache"];
318
125
  */
319
126
  declare function serializeKey(key: QueryKey): string;
320
127
 
321
- export { DefaultConfig, EqualityFn, EqualityStrategy, Fetcher, InferFetcherResult, Persister, PersisterConfig, QueryKey, QueryManagerCore, QueryOptions, QueryState, QueryStatus, RefetchOnSubscribeOptions, _queryManager, createPersister, dangerClearCache, fetchQuery, getQueryData, getQueryState, invalidateQuery, registerFetcher, serializeKey, setDefaultConfig, setQueryData, subscribeQuery };
128
+ export { DefaultConfig, Fetcher, InferFetcherResult, QueryKey, QueryManagerCore, QueryOptions, QueryState, _queryManager, dangerClearCache, fetchQuery, getQueryData, getQueryState, invalidateQuery, registerFetcher, serializeKey, setDefaultConfig, setQueryData, subscribeQuery };
package/index.js CHANGED
@@ -1,17 +1,16 @@
1
1
  'use strict';
2
2
 
3
- function c(e){return Array.isArray(e)?e.join(","):String(e)}function y(e,r,s="shallow"){if(e===r)return !0;if(e==null||r==null)return e===r;if(typeof e!="object"||typeof r!="object")return !1;try{let t=e,a=r;if(Array.isArray(t)&&Array.isArray(a)){if(t.length!==a.length)return !1;for(let u=0;u<t.length;u++)if(s==="deep"){if(!y(t[u],a[u],s))return !1}else if(t[u]!==a[u])return !1;return !0}if(Array.isArray(t)||Array.isArray(a))return !1;let i=Object.keys(t),o=Object.keys(a);if(i.length!==o.length)return !1;for(let u=0;u<i.length;u++){let l=i[u];if(s==="deep"){if(!y(t[l],a[l],s))return !1}else if(t[l]!==a[l])return !1}return !0}catch{return !1}}function p(e,r){return r||((s,t)=>y(s,t,e||"shallow"))}function Q(e,r){return {status:"idle",updatedAt:void 0,staleTime:e?.staleTime??0,isInvalidated:!1,fetcher:e?.fetcher,equalityFn:p(e?.equalityStrategy,e?.equalityFn),equalityStrategy:e?.equalityStrategy??"shallow",placeholderData:e?.placeholderData,usePreviousDataOnError:e?.usePreviousDataOnError??!1,usePlaceholderOnError:e?.usePlaceholderOnError??!1,refetchOnSubscribe:e?.refetchOnSubscribe??"stale",enabled:e?.enabled!==!1,refetch:r||(()=>Promise.resolve(void 0)),isSuccess:!1,isError:!1,lastReturnedState:void 0}}function f(e){let r=Date.now(),s=e.updatedAt!==void 0&&r-e.updatedAt>e.staleTime||e.isInvalidated,t,a=!1;switch(e.status){case"error":e.usePreviousDataOnError&&e.data!==void 0?t=e.data:e.usePlaceholderOnError&&e.placeholderData!==void 0&&(t=e.placeholderData,a=!0);break;case"fetching":e.data!==void 0?(t=e.data,a=!1):e.placeholderData&&(t=e.placeholderData,a=!0);break;case"success":case"idle":t=e.data??e.placeholderData,a=e.data?!1:!!e.placeholderData;break}return {data:t,error:e.error,status:e.status,updatedAt:e.updatedAt,isStale:s,isPlaceholderData:a,isLoading:e.status==="fetching"&&!e.updatedAt,isFetching:e.status==="fetching",isError:e.isError,isSuccess:e.isSuccess,refetch:e.refetch}}function S(e){console.warn(`[qortex] No fetcher or data for key "${c(e)}". Register a fetcher or set initial data.`);}var d=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:s,...t}){this.defaultConfig={...this.defaultConfig,...t},r!==void 0&&(this.throttleTime=r),s&&(this.persister=s,this.persister?.load(this.cache,this.hasQueriesBeenUsed));}ensureState(r,s={}){this.hasQueriesBeenUsed=!0;let t=c(r),a=this.cache.get(t);if(a){let i={...this.defaultConfig,...a,...s};Object.assign(a,i),a.enabled=i.enabled!==!1,this.cache.set(t,a);}else {let i={...this.defaultConfig,...s},o=Q(i,()=>this.fetchQuery(r));this.cache.set(t,o);}return this.cache.get(t)}emit(r,s){let t=c(r);this.cache.set(t,s),this.persister?.sync(this.cache);let a=this.subs.get(t);if(!a)return;let i=f(s);for(let o of Array.from(a))o(i);}registerFetcher(r,s){let t=this.ensureState(r,s);this.handleMountLogic(r,t);}fetchQuery(r,s){let t=this.ensureState(r,s);if(t.fetchPromise)return t.fetchPromise;let a=t.fetcher;if(!a)return t.updatedAt===void 0&&S(r),Promise.resolve(t.data);let i=a();return t.fetchPromise=i,t.status="fetching",t.lastFetchTime=Date.now(),this.emit(r,t),i.then(o=>{t.data=t.equalityFn(t.data,o)?t.data:o,t.status="success",t.isError=!1,t.isSuccess=!0,t.updatedAt=Date.now(),t.fetchPromise=void 0,t.error=void 0,this.emit(r,t);}).catch(o=>{t.error=o,t.status="error",t.isError=!0,t.isSuccess=!1,t.updatedAt=Date.now(),t.fetchPromise=void 0,this.emit(r,t);}),i}setQueryData(r,s){let t=this.ensureState(r),a=t.data;t.equalityFn(a,s)||(t.data=s,t.updatedAt=Date.now(),t.error=void 0,t.status="success",t.isInvalidated=!1,t.isError=!1,t.isSuccess=!0,this.emit(r,t));}getQueryData(r,s){let t=this.ensureState(r,s);return this.handleMountLogic(r,t),f(t).data}getQueryState(r,s){let t=this.ensureState(r,s);this.handleMountLogic(r,t);let a=f(t),i=t.lastReturnedState;return !i||!y(i,a,"shallow")?(t.lastReturnedState=a,a):i}invalidateQuery(r){let s=this.ensureState(r);s.isInvalidated=!0,this.emit(r,s),this.fetchQuery(r);}subscribeQuery(r,s,t){let a=c(r),i=this.ensureState(r,t);return this.subs.has(a)||this.subs.set(a,new Set),this.subs.get(a).add(s),this.handleMountLogic(r,i),()=>{this.subs.get(a).delete(s);}}handleMountLogic(r,s){let t=s.lastFetchTime&&Date.now()-s.lastFetchTime<this.throttleTime;if(s.status==="fetching"||!s.enabled||t||!s.fetcher)return;let a=Date.now(),i=s.updatedAt==null||a-(s.updatedAt||0)>s.staleTime||s.isInvalidated,o=!1;s.updatedAt==null?o=!0:(s.refetchOnSubscribe==="always"&&(o=!0),s.refetchOnSubscribe==="stale"&&(o=i)),o&&this.fetchQuery(r);}},g=d;var n=new g,k=n.registerFetcher.bind(n),j=n.fetchQuery.bind(n),N=n.setQueryData.bind(n),L=n.getQueryData.bind(n),B=n.getQueryState.bind(n),U=n.invalidateQuery.bind(n),J=n.subscribeQuery.bind(n),_=n.setDefaultConfig.bind(n),V=n.dangerClearCache.bind(n);function P(e){return typeof e=="string"&&["idle","fetching","success","error"].includes(e)}function K(e){return typeof e=="string"&&["shallow","deep"].includes(e)}function O(e){return e===!1||typeof e=="string"&&["always","stale"].includes(e)}function D(e){return !(!e||typeof e!="object"||!P(e.status)||typeof e.staleTime!="number"||e.staleTime<0||typeof e.isInvalidated!="boolean"||!K(e.equalityStrategy)||!O(e.refetchOnSubscribe))}function m(e){if(!e||typeof e!="object"||!e.entries||typeof e.entries!="object")return !1;for(let[r,s]of Object.entries(e.entries))if(typeof r!="string"||!D(s))return !1;return !(typeof e.burstKey!="string"||typeof e.timestamp!="number"||e.timestamp<0)}function b(e){let{fetcher:r,equalityFn:s,fetchPromise:t,refetch:a,...i}=e;return i}function T(e,r){let s={...r??{},...e};return {...s,equalityFn:r?.equalityFn||p(s.equalityStrategy)}}function F(e){try{let r=JSON.parse(e);return m(r)?r:null}catch{return null}}var v=()=>{console.warn("[Qortex] No storage found, persister will not be able to persist data");},w=()=>{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 h=class{constructor(r,s){this.syncTimeout=null;this.debounceTime=100;this.burstKey="0.3.0";this.storageKey="qortex";this.storage=r,this.burstKey=s?.burstKey??this.burstKey,this.storageKey=s?.prefix??this.storageKey,this.debounceTime=s?.debounceTime??this.debounceTime;}save(r){try{let s={entries:{},burstKey:this.burstKey,timestamp:Date.now()};for(let[a,i]of Object.entries(r))s.entries[a]=i;let t=JSON.stringify(s);this.storage.setItem(this.storageKey,t);}catch(s){console.warn("[Qortex] Failed to persist state:",s);}}load(r,s){s&&w();try{let t=this.storage.getItem(this.storageKey);if(!t)return;let a=F(t);if(!a){console.warn("[Qortex] Invalid persisted state format, clearing cache"),this.clear();return}if(a.burstKey!==this.burstKey){console.warn("[Qortex] Burst key mismatch, clearing cache"),this.clear();return}for(let[i,o]of Object.entries(a.entries)){let u=o,l=r.get(i),x=T(u,l);r.set(i,x);}}catch(t){console.warn("[Qortex] Failed to load persisted state:",t),this.clear();}}clear(){try{this.storage.removeItem(this.storageKey);}catch(r){console.warn("[Qortex] Failed to clear persisted data:",r);}}sync(r){this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>{let s={};for(let[t,a]of r.entries())s[t]=b(a);this.save(s);},this.debounceTime);}};var I=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}`)}},C=(e,r)=>{let s=I(e);if(!s){v();return}return new h(s,r)};
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);
4
4
 
5
- exports.QueryManagerCore = d;
6
- exports._queryManager = n;
7
- exports.createPersister = C;
8
- exports.dangerClearCache = V;
9
- exports.fetchQuery = j;
10
- exports.getQueryData = L;
11
- exports.getQueryState = B;
12
- exports.invalidateQuery = U;
13
- exports.registerFetcher = k;
5
+ exports.QueryManagerCore = h;
6
+ exports._queryManager = i;
7
+ exports.dangerClearCache = q;
8
+ exports.fetchQuery = O;
9
+ exports.getQueryData = C;
10
+ exports.getQueryState = E;
11
+ exports.invalidateQuery = w;
12
+ exports.registerFetcher = D;
14
13
  exports.serializeKey = c;
15
- exports.setDefaultConfig = _;
16
- exports.setQueryData = N;
17
- exports.subscribeQuery = J;
14
+ exports.setDefaultConfig = A;
15
+ exports.setQueryData = K;
16
+ exports.subscribeQuery = x;
package/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- function c(e){return Array.isArray(e)?e.join(","):String(e)}function y(e,r,s="shallow"){if(e===r)return !0;if(e==null||r==null)return e===r;if(typeof e!="object"||typeof r!="object")return !1;try{let t=e,a=r;if(Array.isArray(t)&&Array.isArray(a)){if(t.length!==a.length)return !1;for(let u=0;u<t.length;u++)if(s==="deep"){if(!y(t[u],a[u],s))return !1}else if(t[u]!==a[u])return !1;return !0}if(Array.isArray(t)||Array.isArray(a))return !1;let i=Object.keys(t),o=Object.keys(a);if(i.length!==o.length)return !1;for(let u=0;u<i.length;u++){let l=i[u];if(s==="deep"){if(!y(t[l],a[l],s))return !1}else if(t[l]!==a[l])return !1}return !0}catch{return !1}}function p(e,r){return r||((s,t)=>y(s,t,e||"shallow"))}function Q(e,r){return {status:"idle",updatedAt:void 0,staleTime:e?.staleTime??0,isInvalidated:!1,fetcher:e?.fetcher,equalityFn:p(e?.equalityStrategy,e?.equalityFn),equalityStrategy:e?.equalityStrategy??"shallow",placeholderData:e?.placeholderData,usePreviousDataOnError:e?.usePreviousDataOnError??!1,usePlaceholderOnError:e?.usePlaceholderOnError??!1,refetchOnSubscribe:e?.refetchOnSubscribe??"stale",enabled:e?.enabled!==!1,refetch:r||(()=>Promise.resolve(void 0)),isSuccess:!1,isError:!1,lastReturnedState:void 0}}function f(e){let r=Date.now(),s=e.updatedAt!==void 0&&r-e.updatedAt>e.staleTime||e.isInvalidated,t,a=!1;switch(e.status){case"error":e.usePreviousDataOnError&&e.data!==void 0?t=e.data:e.usePlaceholderOnError&&e.placeholderData!==void 0&&(t=e.placeholderData,a=!0);break;case"fetching":e.data!==void 0?(t=e.data,a=!1):e.placeholderData&&(t=e.placeholderData,a=!0);break;case"success":case"idle":t=e.data??e.placeholderData,a=e.data?!1:!!e.placeholderData;break}return {data:t,error:e.error,status:e.status,updatedAt:e.updatedAt,isStale:s,isPlaceholderData:a,isLoading:e.status==="fetching"&&!e.updatedAt,isFetching:e.status==="fetching",isError:e.isError,isSuccess:e.isSuccess,refetch:e.refetch}}function S(e){console.warn(`[qortex] No fetcher or data for key "${c(e)}". Register a fetcher or set initial data.`);}var d=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:s,...t}){this.defaultConfig={...this.defaultConfig,...t},r!==void 0&&(this.throttleTime=r),s&&(this.persister=s,this.persister?.load(this.cache,this.hasQueriesBeenUsed));}ensureState(r,s={}){this.hasQueriesBeenUsed=!0;let t=c(r),a=this.cache.get(t);if(a){let i={...this.defaultConfig,...a,...s};Object.assign(a,i),a.enabled=i.enabled!==!1,this.cache.set(t,a);}else {let i={...this.defaultConfig,...s},o=Q(i,()=>this.fetchQuery(r));this.cache.set(t,o);}return this.cache.get(t)}emit(r,s){let t=c(r);this.cache.set(t,s),this.persister?.sync(this.cache);let a=this.subs.get(t);if(!a)return;let i=f(s);for(let o of Array.from(a))o(i);}registerFetcher(r,s){let t=this.ensureState(r,s);this.handleMountLogic(r,t);}fetchQuery(r,s){let t=this.ensureState(r,s);if(t.fetchPromise)return t.fetchPromise;let a=t.fetcher;if(!a)return t.updatedAt===void 0&&S(r),Promise.resolve(t.data);let i=a();return t.fetchPromise=i,t.status="fetching",t.lastFetchTime=Date.now(),this.emit(r,t),i.then(o=>{t.data=t.equalityFn(t.data,o)?t.data:o,t.status="success",t.isError=!1,t.isSuccess=!0,t.updatedAt=Date.now(),t.fetchPromise=void 0,t.error=void 0,this.emit(r,t);}).catch(o=>{t.error=o,t.status="error",t.isError=!0,t.isSuccess=!1,t.updatedAt=Date.now(),t.fetchPromise=void 0,this.emit(r,t);}),i}setQueryData(r,s){let t=this.ensureState(r),a=t.data;t.equalityFn(a,s)||(t.data=s,t.updatedAt=Date.now(),t.error=void 0,t.status="success",t.isInvalidated=!1,t.isError=!1,t.isSuccess=!0,this.emit(r,t));}getQueryData(r,s){let t=this.ensureState(r,s);return this.handleMountLogic(r,t),f(t).data}getQueryState(r,s){let t=this.ensureState(r,s);this.handleMountLogic(r,t);let a=f(t),i=t.lastReturnedState;return !i||!y(i,a,"shallow")?(t.lastReturnedState=a,a):i}invalidateQuery(r){let s=this.ensureState(r);s.isInvalidated=!0,this.emit(r,s),this.fetchQuery(r);}subscribeQuery(r,s,t){let a=c(r),i=this.ensureState(r,t);return this.subs.has(a)||this.subs.set(a,new Set),this.subs.get(a).add(s),this.handleMountLogic(r,i),()=>{this.subs.get(a).delete(s);}}handleMountLogic(r,s){let t=s.lastFetchTime&&Date.now()-s.lastFetchTime<this.throttleTime;if(s.status==="fetching"||!s.enabled||t||!s.fetcher)return;let a=Date.now(),i=s.updatedAt==null||a-(s.updatedAt||0)>s.staleTime||s.isInvalidated,o=!1;s.updatedAt==null?o=!0:(s.refetchOnSubscribe==="always"&&(o=!0),s.refetchOnSubscribe==="stale"&&(o=i)),o&&this.fetchQuery(r);}},g=d;var n=new g,k=n.registerFetcher.bind(n),j=n.fetchQuery.bind(n),N=n.setQueryData.bind(n),L=n.getQueryData.bind(n),B=n.getQueryState.bind(n),U=n.invalidateQuery.bind(n),J=n.subscribeQuery.bind(n),_=n.setDefaultConfig.bind(n),V=n.dangerClearCache.bind(n);function P(e){return typeof e=="string"&&["idle","fetching","success","error"].includes(e)}function K(e){return typeof e=="string"&&["shallow","deep"].includes(e)}function O(e){return e===!1||typeof e=="string"&&["always","stale"].includes(e)}function D(e){return !(!e||typeof e!="object"||!P(e.status)||typeof e.staleTime!="number"||e.staleTime<0||typeof e.isInvalidated!="boolean"||!K(e.equalityStrategy)||!O(e.refetchOnSubscribe))}function m(e){if(!e||typeof e!="object"||!e.entries||typeof e.entries!="object")return !1;for(let[r,s]of Object.entries(e.entries))if(typeof r!="string"||!D(s))return !1;return !(typeof e.burstKey!="string"||typeof e.timestamp!="number"||e.timestamp<0)}function b(e){let{fetcher:r,equalityFn:s,fetchPromise:t,refetch:a,...i}=e;return i}function T(e,r){let s={...r??{},...e};return {...s,equalityFn:r?.equalityFn||p(s.equalityStrategy)}}function F(e){try{let r=JSON.parse(e);return m(r)?r:null}catch{return null}}var v=()=>{console.warn("[Qortex] No storage found, persister will not be able to persist data");},w=()=>{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 h=class{constructor(r,s){this.syncTimeout=null;this.debounceTime=100;this.burstKey="0.3.0";this.storageKey="qortex";this.storage=r,this.burstKey=s?.burstKey??this.burstKey,this.storageKey=s?.prefix??this.storageKey,this.debounceTime=s?.debounceTime??this.debounceTime;}save(r){try{let s={entries:{},burstKey:this.burstKey,timestamp:Date.now()};for(let[a,i]of Object.entries(r))s.entries[a]=i;let t=JSON.stringify(s);this.storage.setItem(this.storageKey,t);}catch(s){console.warn("[Qortex] Failed to persist state:",s);}}load(r,s){s&&w();try{let t=this.storage.getItem(this.storageKey);if(!t)return;let a=F(t);if(!a){console.warn("[Qortex] Invalid persisted state format, clearing cache"),this.clear();return}if(a.burstKey!==this.burstKey){console.warn("[Qortex] Burst key mismatch, clearing cache"),this.clear();return}for(let[i,o]of Object.entries(a.entries)){let u=o,l=r.get(i),x=T(u,l);r.set(i,x);}}catch(t){console.warn("[Qortex] Failed to load persisted state:",t),this.clear();}}clear(){try{this.storage.removeItem(this.storageKey);}catch(r){console.warn("[Qortex] Failed to clear persisted data:",r);}}sync(r){this.syncTimeout&&clearTimeout(this.syncTimeout),this.syncTimeout=setTimeout(()=>{let s={};for(let[t,a]of r.entries())s[t]=b(a);this.save(s);},this.debounceTime);}};var I=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}`)}},C=(e,r)=>{let s=I(e);if(!s){v();return}return new h(s,r)};
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);
2
2
 
3
- export { d as QueryManagerCore, n as _queryManager, C as createPersister, V as dangerClearCache, j as fetchQuery, L as getQueryData, B as getQueryState, U as invalidateQuery, k as registerFetcher, c as serializeKey, _ as setDefaultConfig, N as setQueryData, J as subscribeQuery };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qortex-core",
3
- "version": "0.3.0-beta.1",
3
+ "version": "0.3.0-beta.3",
4
4
  "description": "Framework-agnostic query cache & fetch registry (MFE friendly).",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",