qortex-core 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/index.d.ts +51 -12
- package/index.js +87 -56
- package/index.mjs +87 -56
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://badge.fury.io/js/qortex-core)
|
|
6
6
|
[](https://bundlephobia.com/package/qortex-core)
|
|
7
|
+
[](https://bundlephobia.com/package/qortex-core)
|
|
7
8
|
[](https://www.typescriptlang.org/)
|
|
8
9
|
|
|
9
10
|
## ✨ What makes this special?
|
|
@@ -92,6 +93,7 @@ function useAuth() {
|
|
|
92
93
|
|
|
93
94
|
queryManager.subscribeQuery(["auth", "user"], (state) => {
|
|
94
95
|
user.value = state.data;
|
|
96
|
+
console.log("Auth state:", state.isSuccess, state.isLoading);
|
|
95
97
|
});
|
|
96
98
|
|
|
97
99
|
return { user, isAuthenticated };
|
|
@@ -159,12 +161,23 @@ const { data, isLoading, error, refetch } = useQuery(["todos"]);
|
|
|
159
161
|
const todos = useQueryData(["todos"]);
|
|
160
162
|
```
|
|
161
163
|
|
|
162
|
-
### `queryManager.subscribeQuery(key, callback)`
|
|
164
|
+
### `queryManager.subscribeQuery(key, callback, options?)`
|
|
165
|
+
|
|
166
|
+
Subscribe to query state changes with flexible callback signatures.
|
|
163
167
|
|
|
164
168
|
```ts
|
|
169
|
+
// Callback receives the current state
|
|
165
170
|
const unsubscribe = queryManager.subscribeQuery(["todos"], (state) => {
|
|
166
171
|
console.log("State changed:", state);
|
|
172
|
+
console.log("Data:", state.data);
|
|
173
|
+
console.log("Loading:", state.isLoading);
|
|
174
|
+
console.log("Success:", state.isSuccess);
|
|
167
175
|
});
|
|
176
|
+
|
|
177
|
+
// With fetcher for automatic type inference
|
|
178
|
+
const unsubscribe = queryManager.subscribeQuery(["todos"], (state) => {
|
|
179
|
+
console.log("Todos:", state.data); // Automatically typed
|
|
180
|
+
}, { fetcher: fetchTodos });
|
|
168
181
|
```
|
|
169
182
|
|
|
170
183
|
### `queryManager.setDefaultConfig(config)`
|
package/index.d.ts
CHANGED
|
@@ -3,22 +3,29 @@
|
|
|
3
3
|
* Using readonly to prevent accidental mutations
|
|
4
4
|
*/
|
|
5
5
|
type QueryKey = string | readonly (string | number)[];
|
|
6
|
-
/** Valid query key values - only strings and numbers are allowed */
|
|
7
|
-
type QueryKeyValue = string | number;
|
|
8
6
|
/** Function that fetches data, can be async or sync */
|
|
9
7
|
type Fetcher<T = any> = () => Promise<T> | T;
|
|
10
8
|
/** Function that compares two values for equality */
|
|
11
9
|
type EqualityFn<T = any> = (a: T | undefined, b: T | undefined) => boolean;
|
|
12
10
|
/**
|
|
13
|
-
* Infers the
|
|
14
|
-
*
|
|
11
|
+
* Infers the return type of a fetcher function
|
|
12
|
+
*
|
|
13
|
+
* This utility type extracts the return type from a fetcher function,
|
|
14
|
+
* handling both synchronous and asynchronous fetchers.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const fetchUser = async (id: string): Promise<User> => { ... };
|
|
19
|
+
* type UserType = InferFetcherResult<typeof fetchUser>; // Promise<User>
|
|
20
|
+
*
|
|
21
|
+
* const fetchConfig = (): Config => { ... };
|
|
22
|
+
* type ConfigType = InferFetcherResult<typeof fetchConfig>; // Config
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @template F - The fetcher function type
|
|
26
|
+
* @returns The inferred return type of the fetcher, or `any` if inference fails
|
|
15
27
|
*/
|
|
16
|
-
type InferFetcherResult<F> = F extends
|
|
17
|
-
/**
|
|
18
|
-
* Infers the return type of a fetcher, handling both sync and async cases
|
|
19
|
-
* Falls back to any for user-friendly experience
|
|
20
|
-
*/
|
|
21
|
-
type InferFetcherReturnType<T> = T extends Fetcher<infer R> ? R : any;
|
|
28
|
+
type InferFetcherResult<F> = F extends Fetcher<infer R> ? R : any;
|
|
22
29
|
/**
|
|
23
30
|
* Query status types for better type safety
|
|
24
31
|
*/
|
|
@@ -79,6 +86,28 @@ declare class QueryManager {
|
|
|
79
86
|
private lastReturnedState;
|
|
80
87
|
private defaultConfig;
|
|
81
88
|
private throttleTime;
|
|
89
|
+
/**
|
|
90
|
+
* ⚠️ DANGER: Clear all cached data and subscriptions
|
|
91
|
+
*
|
|
92
|
+
* This method completely wipes all internal state including:
|
|
93
|
+
* - All cached query data
|
|
94
|
+
* - All active subscriptions
|
|
95
|
+
* - All state references
|
|
96
|
+
*
|
|
97
|
+
* @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.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* // ✅ Safe usage in tests
|
|
102
|
+
* beforeEach(() => {
|
|
103
|
+
* queryManager.dangerClearCache();
|
|
104
|
+
* });
|
|
105
|
+
*
|
|
106
|
+
* // ❌ Dangerous usage in production
|
|
107
|
+
* // queryManager.dangerClearCache(); // Don't do this!
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
dangerClearCache(): void;
|
|
82
111
|
/**
|
|
83
112
|
* Set default configuration for all queries
|
|
84
113
|
*/
|
|
@@ -120,12 +149,18 @@ declare class QueryManager {
|
|
|
120
149
|
* Handles mount logic to potentially start fetching
|
|
121
150
|
*/
|
|
122
151
|
getQueryData<T = any>(key: QueryKey, opts?: QueryOptions<T>): T | undefined;
|
|
152
|
+
getQueryData<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
|
|
153
|
+
fetcher: F;
|
|
154
|
+
}): InferFetcherResult<F> | undefined;
|
|
123
155
|
/**
|
|
124
156
|
* Gets comprehensive query state including computed flags
|
|
125
157
|
* Handles placeholder data and error states appropriately
|
|
126
158
|
* Handles mount logic to potentially start fetching
|
|
127
159
|
*/
|
|
128
160
|
getQueryState<T = unknown>(key: QueryKey, opts?: QueryOptions<T>): QueryState<T>;
|
|
161
|
+
getQueryState<F extends Fetcher>(key: QueryKey, opts: QueryOptions<InferFetcherResult<F>> & {
|
|
162
|
+
fetcher: F;
|
|
163
|
+
}): QueryState<InferFetcherResult<F>>;
|
|
129
164
|
/**
|
|
130
165
|
* Marks a query as invalidated, triggering refetch
|
|
131
166
|
*/
|
|
@@ -134,7 +169,11 @@ declare class QueryManager {
|
|
|
134
169
|
* Subscribes to query state changes with automatic subscription management
|
|
135
170
|
* Handles mount logic to potentially start fetching
|
|
136
171
|
*/
|
|
137
|
-
subscribeQuery
|
|
172
|
+
subscribeQuery(key: QueryKey, cb: (state: QueryState<any>) => void): () => void;
|
|
173
|
+
subscribeQuery<F extends Fetcher>(key: QueryKey, cb: (state: QueryState<InferFetcherResult<F>>) => void, opts: QueryOptions<InferFetcherResult<F>> & {
|
|
174
|
+
fetcher: F;
|
|
175
|
+
}): () => void;
|
|
176
|
+
subscribeQuery<T = any>(key: QueryKey, cb: (state: QueryState<T>) => void, opts?: QueryOptions<T>): () => void;
|
|
138
177
|
/**
|
|
139
178
|
* Core mount logic that determines when to fetch
|
|
140
179
|
* Implements robust throttling and race condition prevention
|
|
@@ -149,4 +188,4 @@ declare const queryManager: QueryManager;
|
|
|
149
188
|
*/
|
|
150
189
|
declare function serializeKey(key: QueryKey): string;
|
|
151
190
|
|
|
152
|
-
export { DefaultConfig, EqualityFn, Fetcher, InferFetcherResult,
|
|
191
|
+
export { DefaultConfig, EqualityFn, Fetcher, InferFetcherResult, QueryKey, QueryManager, QueryOptions, QueryState, QueryStatus, queryManager, serializeKey };
|
package/index.js
CHANGED
|
@@ -71,9 +71,54 @@ function createDefaultState(opts, refetch) {
|
|
|
71
71
|
usePlaceholderOnError: opts?.usePlaceholderOnError ?? false,
|
|
72
72
|
refetchOnSubscribe: opts?.refetchOnSubscribe ?? "stale",
|
|
73
73
|
enabled: opts?.enabled === false ? false : true,
|
|
74
|
-
refetch: refetch || (() => Promise.resolve(void 0))
|
|
74
|
+
refetch: refetch || (() => Promise.resolve(void 0)),
|
|
75
|
+
isSuccess: false,
|
|
76
|
+
isError: false
|
|
75
77
|
};
|
|
76
78
|
}
|
|
79
|
+
function createPublicState(state) {
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
const isStale = state.updatedAt == null || now - (state.updatedAt || 0) > state.staleTime || state.isInvalidated;
|
|
82
|
+
let returnedData = state.data;
|
|
83
|
+
let isPlaceholderData = false;
|
|
84
|
+
switch (state.status) {
|
|
85
|
+
case "error":
|
|
86
|
+
if (state.usePlaceholderOnError && state.placeholderData !== void 0) {
|
|
87
|
+
returnedData = state.placeholderData;
|
|
88
|
+
isPlaceholderData = true;
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case "fetching":
|
|
92
|
+
if (!state.data && state.placeholderData) {
|
|
93
|
+
returnedData = state.placeholderData;
|
|
94
|
+
isPlaceholderData = true;
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
case "success":
|
|
98
|
+
case "idle":
|
|
99
|
+
returnedData = state.data ?? state.placeholderData;
|
|
100
|
+
isPlaceholderData = state.data ? false : Boolean(state.placeholderData);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
data: returnedData,
|
|
105
|
+
error: state.error,
|
|
106
|
+
status: state.status,
|
|
107
|
+
updatedAt: state.updatedAt,
|
|
108
|
+
isStale,
|
|
109
|
+
isPlaceholderData,
|
|
110
|
+
isLoading: state.status === "fetching" && !state.updatedAt,
|
|
111
|
+
isFetching: state.status === "fetching",
|
|
112
|
+
isError: state.isError,
|
|
113
|
+
isSuccess: state.isSuccess,
|
|
114
|
+
refetch: state.refetch
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function warnNoFetcherOrData(key) {
|
|
118
|
+
console.warn(
|
|
119
|
+
`[qortex] No fetcher or data for key "${serializeKey(key)}". Register a fetcher or set initial data.`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
77
122
|
|
|
78
123
|
// src/queryManager.ts
|
|
79
124
|
var QueryManager = class {
|
|
@@ -84,6 +129,32 @@ var QueryManager = class {
|
|
|
84
129
|
this.defaultConfig = {};
|
|
85
130
|
this.throttleTime = THROTTLE_TIME;
|
|
86
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* ⚠️ DANGER: Clear all cached data and subscriptions
|
|
134
|
+
*
|
|
135
|
+
* This method completely wipes all internal state including:
|
|
136
|
+
* - All cached query data
|
|
137
|
+
* - All active subscriptions
|
|
138
|
+
* - All state references
|
|
139
|
+
*
|
|
140
|
+
* @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.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* // ✅ Safe usage in tests
|
|
145
|
+
* beforeEach(() => {
|
|
146
|
+
* queryManager.dangerClearCache();
|
|
147
|
+
* });
|
|
148
|
+
*
|
|
149
|
+
* // ❌ Dangerous usage in production
|
|
150
|
+
* // queryManager.dangerClearCache(); // Don't do this!
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
dangerClearCache() {
|
|
154
|
+
this.cache.clear();
|
|
155
|
+
this.subs.clear();
|
|
156
|
+
this.lastReturnedState.clear();
|
|
157
|
+
}
|
|
87
158
|
/**
|
|
88
159
|
* Set default configuration for all queries
|
|
89
160
|
*/
|
|
@@ -115,12 +186,14 @@ var QueryManager = class {
|
|
|
115
186
|
* Notifies all subscribers of a query state change
|
|
116
187
|
*/
|
|
117
188
|
emit(key, state) {
|
|
118
|
-
|
|
119
|
-
|
|
189
|
+
const stateKey = serializeKey(key);
|
|
190
|
+
this.cache.set(stateKey, state);
|
|
191
|
+
const set = this.subs.get(stateKey);
|
|
120
192
|
if (!set)
|
|
121
193
|
return;
|
|
194
|
+
const publicState = createPublicState(state);
|
|
122
195
|
for (const cb of Array.from(set))
|
|
123
|
-
cb();
|
|
196
|
+
cb(publicState);
|
|
124
197
|
}
|
|
125
198
|
registerFetcher(key, opts) {
|
|
126
199
|
this.ensureState(key, opts);
|
|
@@ -137,7 +210,9 @@ var QueryManager = class {
|
|
|
137
210
|
return state.fetchPromise;
|
|
138
211
|
const fetcher = state.fetcher;
|
|
139
212
|
if (!fetcher) {
|
|
140
|
-
|
|
213
|
+
if (state.updatedAt === void 0) {
|
|
214
|
+
warnNoFetcherOrData(key);
|
|
215
|
+
}
|
|
141
216
|
return Promise.resolve(state.data);
|
|
142
217
|
}
|
|
143
218
|
;
|
|
@@ -151,9 +226,13 @@ var QueryManager = class {
|
|
|
151
226
|
state.data = result2;
|
|
152
227
|
state.status = "success";
|
|
153
228
|
state.updatedAt = Date.now();
|
|
229
|
+
state.isError = false;
|
|
230
|
+
state.isSuccess = true;
|
|
154
231
|
}).catch((error) => {
|
|
155
232
|
state.error = error;
|
|
156
233
|
state.status = "error";
|
|
234
|
+
state.isError = true;
|
|
235
|
+
state.isSuccess = false;
|
|
157
236
|
}).finally(() => {
|
|
158
237
|
state.fetchPromise = void 0;
|
|
159
238
|
this.emit(key, state);
|
|
@@ -174,63 +253,19 @@ var QueryManager = class {
|
|
|
174
253
|
state.error = void 0;
|
|
175
254
|
state.status = "success";
|
|
176
255
|
state.isInvalidated = false;
|
|
256
|
+
state.isError = false;
|
|
257
|
+
state.isSuccess = true;
|
|
177
258
|
this.emit(key, state);
|
|
178
259
|
}
|
|
179
|
-
/**
|
|
180
|
-
* Gets query data
|
|
181
|
-
* Handles mount logic to potentially start fetching
|
|
182
|
-
*/
|
|
183
260
|
getQueryData(key, opts) {
|
|
184
261
|
const state = this.ensureState(key, opts);
|
|
185
262
|
this.handleMountLogic(key, state);
|
|
186
263
|
return state.data ?? state.placeholderData;
|
|
187
264
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Gets comprehensive query state including computed flags
|
|
190
|
-
* Handles placeholder data and error states appropriately
|
|
191
|
-
* Handles mount logic to potentially start fetching
|
|
192
|
-
*/
|
|
193
265
|
getQueryState(key, opts) {
|
|
194
266
|
let state = this.ensureState(key, opts);
|
|
195
|
-
const now = Date.now();
|
|
196
|
-
const isStale = state.updatedAt == null || now - (state.updatedAt || 0) > state.staleTime || state.isInvalidated;
|
|
197
|
-
let returnedData = state.data;
|
|
198
|
-
let isPlaceholderData = false;
|
|
199
|
-
const status = state.status;
|
|
200
|
-
switch (status) {
|
|
201
|
-
case "error":
|
|
202
|
-
if (state.usePlaceholderOnError && state.placeholderData !== void 0) {
|
|
203
|
-
returnedData = state.placeholderData;
|
|
204
|
-
isPlaceholderData = true;
|
|
205
|
-
}
|
|
206
|
-
break;
|
|
207
|
-
case "fetching":
|
|
208
|
-
if (!state.data && state.placeholderData) {
|
|
209
|
-
returnedData = state.placeholderData;
|
|
210
|
-
isPlaceholderData = true;
|
|
211
|
-
}
|
|
212
|
-
break;
|
|
213
|
-
case "success":
|
|
214
|
-
case "idle":
|
|
215
|
-
returnedData = state.data ?? state.placeholderData;
|
|
216
|
-
isPlaceholderData = state.data ? false : Boolean(state.placeholderData);
|
|
217
|
-
break;
|
|
218
|
-
}
|
|
219
267
|
this.handleMountLogic(key, state);
|
|
220
|
-
const currentState =
|
|
221
|
-
data: returnedData,
|
|
222
|
-
error: state.error,
|
|
223
|
-
status: state.status,
|
|
224
|
-
updatedAt: state.updatedAt,
|
|
225
|
-
isStale,
|
|
226
|
-
isPlaceholderData,
|
|
227
|
-
isLoading: state.status === "fetching" && !state.updatedAt,
|
|
228
|
-
// true only for first fetch
|
|
229
|
-
isFetching: state.status === "fetching",
|
|
230
|
-
isError: state.status === "error",
|
|
231
|
-
isSuccess: state.status === "success",
|
|
232
|
-
refetch: state.refetch
|
|
233
|
-
};
|
|
268
|
+
const currentState = createPublicState(state);
|
|
234
269
|
const stateKey = serializeKey(key);
|
|
235
270
|
const lastState = this.lastReturnedState?.get(stateKey);
|
|
236
271
|
if (!lastState || !shallowEqual(lastState, currentState)) {
|
|
@@ -250,10 +285,6 @@ var QueryManager = class {
|
|
|
250
285
|
this.emit(key, state);
|
|
251
286
|
this.fetchQuery(key);
|
|
252
287
|
}
|
|
253
|
-
/**
|
|
254
|
-
* Subscribes to query state changes with automatic subscription management
|
|
255
|
-
* Handles mount logic to potentially start fetching
|
|
256
|
-
*/
|
|
257
288
|
subscribeQuery(key, cb, opts) {
|
|
258
289
|
const sk = serializeKey(key);
|
|
259
290
|
const state = this.ensureState(key, opts);
|
package/index.mjs
CHANGED
|
@@ -43,9 +43,54 @@ function createDefaultState(opts, refetch) {
|
|
|
43
43
|
usePlaceholderOnError: opts?.usePlaceholderOnError ?? false,
|
|
44
44
|
refetchOnSubscribe: opts?.refetchOnSubscribe ?? "stale",
|
|
45
45
|
enabled: opts?.enabled === false ? false : true,
|
|
46
|
-
refetch: refetch || (() => Promise.resolve(void 0))
|
|
46
|
+
refetch: refetch || (() => Promise.resolve(void 0)),
|
|
47
|
+
isSuccess: false,
|
|
48
|
+
isError: false
|
|
47
49
|
};
|
|
48
50
|
}
|
|
51
|
+
function createPublicState(state) {
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
const isStale = state.updatedAt == null || now - (state.updatedAt || 0) > state.staleTime || state.isInvalidated;
|
|
54
|
+
let returnedData = state.data;
|
|
55
|
+
let isPlaceholderData = false;
|
|
56
|
+
switch (state.status) {
|
|
57
|
+
case "error":
|
|
58
|
+
if (state.usePlaceholderOnError && state.placeholderData !== void 0) {
|
|
59
|
+
returnedData = state.placeholderData;
|
|
60
|
+
isPlaceholderData = true;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case "fetching":
|
|
64
|
+
if (!state.data && state.placeholderData) {
|
|
65
|
+
returnedData = state.placeholderData;
|
|
66
|
+
isPlaceholderData = true;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
case "success":
|
|
70
|
+
case "idle":
|
|
71
|
+
returnedData = state.data ?? state.placeholderData;
|
|
72
|
+
isPlaceholderData = state.data ? false : Boolean(state.placeholderData);
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
data: returnedData,
|
|
77
|
+
error: state.error,
|
|
78
|
+
status: state.status,
|
|
79
|
+
updatedAt: state.updatedAt,
|
|
80
|
+
isStale,
|
|
81
|
+
isPlaceholderData,
|
|
82
|
+
isLoading: state.status === "fetching" && !state.updatedAt,
|
|
83
|
+
isFetching: state.status === "fetching",
|
|
84
|
+
isError: state.isError,
|
|
85
|
+
isSuccess: state.isSuccess,
|
|
86
|
+
refetch: state.refetch
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function warnNoFetcherOrData(key) {
|
|
90
|
+
console.warn(
|
|
91
|
+
`[qortex] No fetcher or data for key "${serializeKey(key)}". Register a fetcher or set initial data.`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
49
94
|
|
|
50
95
|
// src/queryManager.ts
|
|
51
96
|
var QueryManager = class {
|
|
@@ -56,6 +101,32 @@ var QueryManager = class {
|
|
|
56
101
|
this.defaultConfig = {};
|
|
57
102
|
this.throttleTime = THROTTLE_TIME;
|
|
58
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* ⚠️ DANGER: Clear all cached data and subscriptions
|
|
106
|
+
*
|
|
107
|
+
* This method completely wipes all internal state including:
|
|
108
|
+
* - All cached query data
|
|
109
|
+
* - All active subscriptions
|
|
110
|
+
* - All state references
|
|
111
|
+
*
|
|
112
|
+
* @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.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* // ✅ Safe usage in tests
|
|
117
|
+
* beforeEach(() => {
|
|
118
|
+
* queryManager.dangerClearCache();
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* // ❌ Dangerous usage in production
|
|
122
|
+
* // queryManager.dangerClearCache(); // Don't do this!
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
dangerClearCache() {
|
|
126
|
+
this.cache.clear();
|
|
127
|
+
this.subs.clear();
|
|
128
|
+
this.lastReturnedState.clear();
|
|
129
|
+
}
|
|
59
130
|
/**
|
|
60
131
|
* Set default configuration for all queries
|
|
61
132
|
*/
|
|
@@ -87,12 +158,14 @@ var QueryManager = class {
|
|
|
87
158
|
* Notifies all subscribers of a query state change
|
|
88
159
|
*/
|
|
89
160
|
emit(key, state) {
|
|
90
|
-
|
|
91
|
-
|
|
161
|
+
const stateKey = serializeKey(key);
|
|
162
|
+
this.cache.set(stateKey, state);
|
|
163
|
+
const set = this.subs.get(stateKey);
|
|
92
164
|
if (!set)
|
|
93
165
|
return;
|
|
166
|
+
const publicState = createPublicState(state);
|
|
94
167
|
for (const cb of Array.from(set))
|
|
95
|
-
cb();
|
|
168
|
+
cb(publicState);
|
|
96
169
|
}
|
|
97
170
|
registerFetcher(key, opts) {
|
|
98
171
|
this.ensureState(key, opts);
|
|
@@ -109,7 +182,9 @@ var QueryManager = class {
|
|
|
109
182
|
return state.fetchPromise;
|
|
110
183
|
const fetcher = state.fetcher;
|
|
111
184
|
if (!fetcher) {
|
|
112
|
-
|
|
185
|
+
if (state.updatedAt === void 0) {
|
|
186
|
+
warnNoFetcherOrData(key);
|
|
187
|
+
}
|
|
113
188
|
return Promise.resolve(state.data);
|
|
114
189
|
}
|
|
115
190
|
;
|
|
@@ -123,9 +198,13 @@ var QueryManager = class {
|
|
|
123
198
|
state.data = result2;
|
|
124
199
|
state.status = "success";
|
|
125
200
|
state.updatedAt = Date.now();
|
|
201
|
+
state.isError = false;
|
|
202
|
+
state.isSuccess = true;
|
|
126
203
|
}).catch((error) => {
|
|
127
204
|
state.error = error;
|
|
128
205
|
state.status = "error";
|
|
206
|
+
state.isError = true;
|
|
207
|
+
state.isSuccess = false;
|
|
129
208
|
}).finally(() => {
|
|
130
209
|
state.fetchPromise = void 0;
|
|
131
210
|
this.emit(key, state);
|
|
@@ -146,63 +225,19 @@ var QueryManager = class {
|
|
|
146
225
|
state.error = void 0;
|
|
147
226
|
state.status = "success";
|
|
148
227
|
state.isInvalidated = false;
|
|
228
|
+
state.isError = false;
|
|
229
|
+
state.isSuccess = true;
|
|
149
230
|
this.emit(key, state);
|
|
150
231
|
}
|
|
151
|
-
/**
|
|
152
|
-
* Gets query data
|
|
153
|
-
* Handles mount logic to potentially start fetching
|
|
154
|
-
*/
|
|
155
232
|
getQueryData(key, opts) {
|
|
156
233
|
const state = this.ensureState(key, opts);
|
|
157
234
|
this.handleMountLogic(key, state);
|
|
158
235
|
return state.data ?? state.placeholderData;
|
|
159
236
|
}
|
|
160
|
-
/**
|
|
161
|
-
* Gets comprehensive query state including computed flags
|
|
162
|
-
* Handles placeholder data and error states appropriately
|
|
163
|
-
* Handles mount logic to potentially start fetching
|
|
164
|
-
*/
|
|
165
237
|
getQueryState(key, opts) {
|
|
166
238
|
let state = this.ensureState(key, opts);
|
|
167
|
-
const now = Date.now();
|
|
168
|
-
const isStale = state.updatedAt == null || now - (state.updatedAt || 0) > state.staleTime || state.isInvalidated;
|
|
169
|
-
let returnedData = state.data;
|
|
170
|
-
let isPlaceholderData = false;
|
|
171
|
-
const status = state.status;
|
|
172
|
-
switch (status) {
|
|
173
|
-
case "error":
|
|
174
|
-
if (state.usePlaceholderOnError && state.placeholderData !== void 0) {
|
|
175
|
-
returnedData = state.placeholderData;
|
|
176
|
-
isPlaceholderData = true;
|
|
177
|
-
}
|
|
178
|
-
break;
|
|
179
|
-
case "fetching":
|
|
180
|
-
if (!state.data && state.placeholderData) {
|
|
181
|
-
returnedData = state.placeholderData;
|
|
182
|
-
isPlaceholderData = true;
|
|
183
|
-
}
|
|
184
|
-
break;
|
|
185
|
-
case "success":
|
|
186
|
-
case "idle":
|
|
187
|
-
returnedData = state.data ?? state.placeholderData;
|
|
188
|
-
isPlaceholderData = state.data ? false : Boolean(state.placeholderData);
|
|
189
|
-
break;
|
|
190
|
-
}
|
|
191
239
|
this.handleMountLogic(key, state);
|
|
192
|
-
const currentState =
|
|
193
|
-
data: returnedData,
|
|
194
|
-
error: state.error,
|
|
195
|
-
status: state.status,
|
|
196
|
-
updatedAt: state.updatedAt,
|
|
197
|
-
isStale,
|
|
198
|
-
isPlaceholderData,
|
|
199
|
-
isLoading: state.status === "fetching" && !state.updatedAt,
|
|
200
|
-
// true only for first fetch
|
|
201
|
-
isFetching: state.status === "fetching",
|
|
202
|
-
isError: state.status === "error",
|
|
203
|
-
isSuccess: state.status === "success",
|
|
204
|
-
refetch: state.refetch
|
|
205
|
-
};
|
|
240
|
+
const currentState = createPublicState(state);
|
|
206
241
|
const stateKey = serializeKey(key);
|
|
207
242
|
const lastState = this.lastReturnedState?.get(stateKey);
|
|
208
243
|
if (!lastState || !shallowEqual(lastState, currentState)) {
|
|
@@ -222,10 +257,6 @@ var QueryManager = class {
|
|
|
222
257
|
this.emit(key, state);
|
|
223
258
|
this.fetchQuery(key);
|
|
224
259
|
}
|
|
225
|
-
/**
|
|
226
|
-
* Subscribes to query state changes with automatic subscription management
|
|
227
|
-
* Handles mount logic to potentially start fetching
|
|
228
|
-
*/
|
|
229
260
|
subscribeQuery(key, cb, opts) {
|
|
230
261
|
const sk = serializeKey(key);
|
|
231
262
|
const state = this.ensureState(key, opts);
|