floppy-disk 3.0.0-alpha.2 → 3.0.0-alpha.4
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/esm/react/create-query.d.mts +61 -39
- package/esm/react.mjs +22 -13
- package/esm/vanilla/store.d.mts +5 -0
- package/esm/vanilla.mjs +8 -1
- package/package.json +1 -1
- package/react/create-query.d.ts +61 -39
- package/react.js +22 -13
- package/vanilla/store.d.ts +5 -0
- package/vanilla.js +8 -1
|
@@ -153,30 +153,33 @@ export type QueryOptions<TData, TVariable extends Record<string, any>> = InitSto
|
|
|
153
153
|
* // ...
|
|
154
154
|
* }
|
|
155
155
|
*/
|
|
156
|
-
export declare const createQuery: <TData, TVariable extends Record<string, any> = never>(queryFn: (variable: TVariable, currentState: QueryState<TData>) => Promise<TData>, options?: QueryOptions<TData, TVariable>) => ((variable?: TVariable) =>
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
156
|
+
export declare const createQuery: <TData, TVariable extends Record<string, any> = never>(queryFn: (variable: TVariable, currentState: QueryState<TData>) => Promise<TData>, options?: QueryOptions<TData, TVariable>) => ((variable?: TVariable) => {
|
|
157
|
+
<TStateSlice = QueryState<TData>>(options?: {
|
|
158
|
+
/**
|
|
159
|
+
* Whether the query should execute automatically on mount.
|
|
160
|
+
*
|
|
161
|
+
* @default true
|
|
162
|
+
*/
|
|
163
|
+
enabled?: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Whether to keep previous successful data while a new variable is loading.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* - Only applies when the query is in the `INITIAL` state (no data & no error).
|
|
169
|
+
* - Intended for variable changes:
|
|
170
|
+
* when switching from one variable to another, the previous data is temporarily shown
|
|
171
|
+
* while the new execution is in progress.
|
|
172
|
+
* - Once the new execution resolves (success or error), the previous data is no longer used.
|
|
173
|
+
* - Prevents UI flicker (e.g. empty/loading state) during transitions.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* // Switching from userId=1 → userId=2
|
|
177
|
+
* // While loading userId=2, still show userId=1 data
|
|
178
|
+
* useQuery({ id: userId }, { keepPreviousData: true });
|
|
179
|
+
*/ keepPreviousData?: boolean;
|
|
180
|
+
}, selector?: (state: QueryState<TData>) => TStateSlice): TStateSlice;
|
|
181
|
+
<TStateSlice = QueryState<TData>>(selector?: (state: QueryState<TData>) => TStateSlice): TStateSlice;
|
|
182
|
+
} & {
|
|
180
183
|
metadata: {
|
|
181
184
|
isInvalidated?: boolean;
|
|
182
185
|
promise?: Promise<QueryState<TData>> | undefined;
|
|
@@ -202,45 +205,58 @@ export declare const createQuery: <TData, TVariable extends Record<string, any>
|
|
|
202
205
|
/**
|
|
203
206
|
* Executes the query function.
|
|
204
207
|
*
|
|
205
|
-
* @param
|
|
208
|
+
* @param options - Execution options
|
|
209
|
+
* @param options.overwriteOngoingExecution - Whether to start a new execution instead of reusing an ongoing one (default: `true`)
|
|
206
210
|
*
|
|
207
211
|
* @returns A promise resolving to the latest query state
|
|
208
212
|
*
|
|
209
213
|
* @remarks
|
|
210
|
-
* -
|
|
211
|
-
* -
|
|
214
|
+
* - By default, each call starts a new execution even if one is already in progress.
|
|
215
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
212
216
|
* - Handles:
|
|
213
217
|
* - Pending state
|
|
214
218
|
* - Success state
|
|
215
219
|
* - Error state
|
|
216
220
|
* - Retry logic
|
|
217
221
|
*/
|
|
218
|
-
execute: (
|
|
222
|
+
execute: (options?: {
|
|
223
|
+
overwriteOngoingExecution?: boolean;
|
|
224
|
+
}) => Promise<QueryState<TData>>;
|
|
219
225
|
/**
|
|
220
|
-
* Re-executes the query if
|
|
226
|
+
* Re-executes the query if needed based on freshness or invalidation.
|
|
221
227
|
*
|
|
222
|
-
* @param
|
|
228
|
+
* @param options - Revalidation options
|
|
229
|
+
* @param options.overwriteOngoingExecution - Whether to overwrite an ongoing execution (default: `true`)
|
|
223
230
|
*
|
|
224
231
|
* @returns The current state if still fresh, otherwise a promise of the new state
|
|
225
232
|
*
|
|
226
233
|
* @remarks
|
|
227
|
-
* - Skips execution if data is still fresh (`staleTime`)
|
|
228
|
-
* -
|
|
234
|
+
* - Skips execution if data is still fresh (`staleTime`) **AND** the query has not been invalidated.
|
|
235
|
+
* - If execution is not skipped, by default it will start a new execution even if one is already in progress.
|
|
236
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
229
237
|
*/
|
|
230
|
-
revalidate: (
|
|
238
|
+
revalidate: (options?: {
|
|
239
|
+
overwriteOngoingExecution?: boolean;
|
|
240
|
+
}) => Promise<QueryState<TData>>;
|
|
231
241
|
/**
|
|
232
242
|
* Marks the query as invalidated and optionally triggers re-execution.
|
|
233
243
|
*
|
|
234
|
-
* @param
|
|
244
|
+
* @param options - Invalidation options
|
|
245
|
+
* @param options.overwriteOngoingExecution - Whether to overwrite an ongoing execution (default: `true`)
|
|
235
246
|
*
|
|
236
247
|
* @returns `true` if execution was triggered, `false` otherwise
|
|
237
248
|
*
|
|
238
249
|
* @remarks
|
|
239
250
|
* - Invalidated queries are treated as stale regardless of `staleTime`.
|
|
240
251
|
* - The next `revalidate` will always execute until a successful result clears the invalidation.
|
|
241
|
-
* - If there are active subscribers
|
|
252
|
+
* - If there are active subscribers: Execution is triggered immediately.
|
|
253
|
+
* - Otherwise: The query remains invalidated and will execute on the next revalidation.
|
|
254
|
+
* - By default, starts a new execution even if one is already in progress.
|
|
255
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
242
256
|
*/
|
|
243
|
-
invalidate: (
|
|
257
|
+
invalidate: (options?: {
|
|
258
|
+
overwriteOngoingExecution?: boolean;
|
|
259
|
+
}) => boolean;
|
|
244
260
|
/**
|
|
245
261
|
* Resets the query state to its initial state.
|
|
246
262
|
*
|
|
@@ -296,14 +312,18 @@ export declare const createQuery: <TData, TVariable extends Record<string, any>
|
|
|
296
312
|
* @remarks
|
|
297
313
|
* - Useful for bulk refetching.
|
|
298
314
|
*/
|
|
299
|
-
executeAll: (
|
|
315
|
+
executeAll: (options?: {
|
|
316
|
+
overwriteOngoingExecution?: boolean;
|
|
317
|
+
}) => void;
|
|
300
318
|
/**
|
|
301
319
|
* Revalidates all query instances.
|
|
302
320
|
*
|
|
303
321
|
* @remarks
|
|
304
322
|
* - Only re-fetches stale queries.
|
|
305
323
|
*/
|
|
306
|
-
revalidateAll: (
|
|
324
|
+
revalidateAll: (options?: {
|
|
325
|
+
overwriteOngoingExecution?: boolean;
|
|
326
|
+
}) => void;
|
|
307
327
|
/**
|
|
308
328
|
* Invalidates all query instances.
|
|
309
329
|
*
|
|
@@ -311,7 +331,9 @@ export declare const createQuery: <TData, TVariable extends Record<string, any>
|
|
|
311
331
|
* - Marks all queries as invalidated and triggers revalidation if active.
|
|
312
332
|
* - Invalidated queries bypass `staleTime` until successfully executed again.
|
|
313
333
|
*/
|
|
314
|
-
invalidateAll: (
|
|
334
|
+
invalidateAll: (options?: {
|
|
335
|
+
overwriteOngoingExecution?: boolean;
|
|
336
|
+
}) => void;
|
|
315
337
|
/**
|
|
316
338
|
* Resets all query instances.
|
|
317
339
|
*/
|
package/esm/react.mjs
CHANGED
|
@@ -157,17 +157,17 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
157
157
|
}
|
|
158
158
|
return false;
|
|
159
159
|
},
|
|
160
|
-
execute: (overwriteOngoingExecution =
|
|
160
|
+
execute: ({ overwriteOngoingExecution = true } = {}) => {
|
|
161
161
|
return execute(store, variable, overwriteOngoingExecution);
|
|
162
162
|
},
|
|
163
|
-
revalidate: (overwriteOngoingExecution =
|
|
163
|
+
revalidate: ({ overwriteOngoingExecution = true } = {}) => {
|
|
164
164
|
return revalidate(store, variable, overwriteOngoingExecution);
|
|
165
165
|
},
|
|
166
|
-
invalidate: (
|
|
166
|
+
invalidate: (options2) => {
|
|
167
167
|
const { metadata } = internals.get(store);
|
|
168
168
|
metadata.isInvalidated = true;
|
|
169
169
|
if (store.getSubscribers().size > 0) {
|
|
170
|
-
internals.get(store).execute(
|
|
170
|
+
internals.get(store).execute(options2);
|
|
171
171
|
return true;
|
|
172
172
|
}
|
|
173
173
|
return false;
|
|
@@ -323,10 +323,19 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
323
323
|
stores.set(variableHash, store);
|
|
324
324
|
internals.set(store, configureInternals(store, variable, variableHash));
|
|
325
325
|
}
|
|
326
|
-
|
|
326
|
+
function useStore(optionsOrSelector = {}, maybeSelector) {
|
|
327
|
+
let selector;
|
|
328
|
+
let options2;
|
|
329
|
+
if (typeof optionsOrSelector === "function") {
|
|
330
|
+
options2 = {};
|
|
331
|
+
selector = optionsOrSelector;
|
|
332
|
+
} else {
|
|
333
|
+
options2 = optionsOrSelector;
|
|
334
|
+
selector = maybeSelector || identity;
|
|
335
|
+
}
|
|
327
336
|
useStoreUpdateNotifier(store, selector);
|
|
328
337
|
useIsomorphicLayoutEffect(() => {
|
|
329
|
-
if (options2.enabled !== false) revalidate(store, variable);
|
|
338
|
+
if (options2.enabled !== false) revalidate(store, variable, false);
|
|
330
339
|
}, [store, options2.enabled]);
|
|
331
340
|
const storeState = store.getState();
|
|
332
341
|
let storeStateToBeUsed = storeState;
|
|
@@ -337,7 +346,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
337
346
|
storeStateToBeUsed = { ...storeState, ...prevState.current };
|
|
338
347
|
}
|
|
339
348
|
return selector(storeStateToBeUsed);
|
|
340
|
-
}
|
|
349
|
+
}
|
|
341
350
|
return Object.assign(useStore, {
|
|
342
351
|
subscribe: store.subscribe,
|
|
343
352
|
getSubscribers: store.getSubscribers,
|
|
@@ -356,8 +365,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
356
365
|
* @remarks
|
|
357
366
|
* - Useful for bulk refetching.
|
|
358
367
|
*/
|
|
359
|
-
executeAll: (
|
|
360
|
-
stores.forEach((store) => internals.get(store).execute(
|
|
368
|
+
executeAll: (options2) => {
|
|
369
|
+
stores.forEach((store) => internals.get(store).execute(options2));
|
|
361
370
|
},
|
|
362
371
|
/**
|
|
363
372
|
* Revalidates all query instances.
|
|
@@ -365,8 +374,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
365
374
|
* @remarks
|
|
366
375
|
* - Only re-fetches stale queries.
|
|
367
376
|
*/
|
|
368
|
-
revalidateAll: (
|
|
369
|
-
stores.forEach((store) => internals.get(store).revalidate(
|
|
377
|
+
revalidateAll: (options2) => {
|
|
378
|
+
stores.forEach((store) => internals.get(store).revalidate(options2));
|
|
370
379
|
},
|
|
371
380
|
/**
|
|
372
381
|
* Invalidates all query instances.
|
|
@@ -375,8 +384,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
375
384
|
* - Marks all queries as invalidated and triggers revalidation if active.
|
|
376
385
|
* - Invalidated queries bypass `staleTime` until successfully executed again.
|
|
377
386
|
*/
|
|
378
|
-
invalidateAll: (
|
|
379
|
-
stores.forEach((store) => internals.get(store).invalidate(
|
|
387
|
+
invalidateAll: (options2) => {
|
|
388
|
+
stores.forEach((store) => internals.get(store).invalidate(options2));
|
|
380
389
|
},
|
|
381
390
|
/**
|
|
382
391
|
* Resets all query instances.
|
package/esm/vanilla/store.d.mts
CHANGED
|
@@ -24,6 +24,7 @@ export type Subscriber<TState> = (state: TState, prevState: TState) => void;
|
|
|
24
24
|
* - The store performs **shallow change detection per key** before notifying subscribers.
|
|
25
25
|
* - Subscribers are only notified when at least one field changes.
|
|
26
26
|
* - Designed to be framework-agnostic (React bindings are built separately).
|
|
27
|
+
* - By default, `setState` is **disabled on the server** to prevent accidental shared state between requests.
|
|
27
28
|
*/
|
|
28
29
|
export type StoreApi<TState extends Record<string, any>> = {
|
|
29
30
|
setState: (value: SetState<TState>) => void;
|
|
@@ -47,6 +48,7 @@ export type InitStoreOptions<TState extends Record<string, any>> = {
|
|
|
47
48
|
onSubscribe?: (state: TState, store: StoreApi<TState>) => void;
|
|
48
49
|
onUnsubscribe?: (state: TState, store: StoreApi<TState>) => void;
|
|
49
50
|
onLastUnsubscribe?: (state: TState, store: StoreApi<TState>) => void;
|
|
51
|
+
allowSetStateServerSide?: boolean;
|
|
50
52
|
};
|
|
51
53
|
/**
|
|
52
54
|
* Creates a vanilla store with pub-sub capabilities.
|
|
@@ -64,6 +66,9 @@ export type InitStoreOptions<TState extends Record<string, any>> = {
|
|
|
64
66
|
* - Subscribers are only notified when at least one updated field changes (using `Object.is` comparison).
|
|
65
67
|
* - Subscribers receive both the new state and the previous state.
|
|
66
68
|
* - Lifecycle hooks allow side-effect management tied to subscription count.
|
|
69
|
+
* - By default, `setState` is **disabled on the server** to prevent accidental shared state between requests.
|
|
70
|
+
* - This avoids leaking data between users in server environments.
|
|
71
|
+
* - You can override this by setting `allowSetStateServerSide: true`.
|
|
67
72
|
*
|
|
68
73
|
* @example
|
|
69
74
|
* const store = initStore({ count: 0 });
|
package/esm/vanilla.mjs
CHANGED
|
@@ -70,7 +70,8 @@ const initStore = (initialState, options = {}) => {
|
|
|
70
70
|
onFirstSubscribe = noop,
|
|
71
71
|
onSubscribe = noop,
|
|
72
72
|
onUnsubscribe = noop,
|
|
73
|
-
onLastUnsubscribe = noop
|
|
73
|
+
onLastUnsubscribe = noop,
|
|
74
|
+
allowSetStateServerSide = false
|
|
74
75
|
} = options;
|
|
75
76
|
const subscribers = /* @__PURE__ */ new Set();
|
|
76
77
|
const getSubscribers = () => subscribers;
|
|
@@ -87,6 +88,12 @@ const initStore = (initialState, options = {}) => {
|
|
|
87
88
|
let state = initialState;
|
|
88
89
|
const getState = () => state;
|
|
89
90
|
const setState = (value) => {
|
|
91
|
+
if (!isClient && !allowSetStateServerSide) {
|
|
92
|
+
console.error(
|
|
93
|
+
"setState on the server is not allowed by default. Set `allowSetStateServerSide: true` to allow it."
|
|
94
|
+
);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
90
97
|
const prevState = state;
|
|
91
98
|
const newValue = getValue(value, state);
|
|
92
99
|
for (const key in newValue) {
|
package/package.json
CHANGED
package/react/create-query.d.ts
CHANGED
|
@@ -153,30 +153,33 @@ export type QueryOptions<TData, TVariable extends Record<string, any>> = InitSto
|
|
|
153
153
|
* // ...
|
|
154
154
|
* }
|
|
155
155
|
*/
|
|
156
|
-
export declare const createQuery: <TData, TVariable extends Record<string, any> = never>(queryFn: (variable: TVariable, currentState: QueryState<TData>) => Promise<TData>, options?: QueryOptions<TData, TVariable>) => ((variable?: TVariable) =>
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
156
|
+
export declare const createQuery: <TData, TVariable extends Record<string, any> = never>(queryFn: (variable: TVariable, currentState: QueryState<TData>) => Promise<TData>, options?: QueryOptions<TData, TVariable>) => ((variable?: TVariable) => {
|
|
157
|
+
<TStateSlice = QueryState<TData>>(options?: {
|
|
158
|
+
/**
|
|
159
|
+
* Whether the query should execute automatically on mount.
|
|
160
|
+
*
|
|
161
|
+
* @default true
|
|
162
|
+
*/
|
|
163
|
+
enabled?: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* Whether to keep previous successful data while a new variable is loading.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* - Only applies when the query is in the `INITIAL` state (no data & no error).
|
|
169
|
+
* - Intended for variable changes:
|
|
170
|
+
* when switching from one variable to another, the previous data is temporarily shown
|
|
171
|
+
* while the new execution is in progress.
|
|
172
|
+
* - Once the new execution resolves (success or error), the previous data is no longer used.
|
|
173
|
+
* - Prevents UI flicker (e.g. empty/loading state) during transitions.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* // Switching from userId=1 → userId=2
|
|
177
|
+
* // While loading userId=2, still show userId=1 data
|
|
178
|
+
* useQuery({ id: userId }, { keepPreviousData: true });
|
|
179
|
+
*/ keepPreviousData?: boolean;
|
|
180
|
+
}, selector?: (state: QueryState<TData>) => TStateSlice): TStateSlice;
|
|
181
|
+
<TStateSlice = QueryState<TData>>(selector?: (state: QueryState<TData>) => TStateSlice): TStateSlice;
|
|
182
|
+
} & {
|
|
180
183
|
metadata: {
|
|
181
184
|
isInvalidated?: boolean;
|
|
182
185
|
promise?: Promise<QueryState<TData>> | undefined;
|
|
@@ -202,45 +205,58 @@ export declare const createQuery: <TData, TVariable extends Record<string, any>
|
|
|
202
205
|
/**
|
|
203
206
|
* Executes the query function.
|
|
204
207
|
*
|
|
205
|
-
* @param
|
|
208
|
+
* @param options - Execution options
|
|
209
|
+
* @param options.overwriteOngoingExecution - Whether to start a new execution instead of reusing an ongoing one (default: `true`)
|
|
206
210
|
*
|
|
207
211
|
* @returns A promise resolving to the latest query state
|
|
208
212
|
*
|
|
209
213
|
* @remarks
|
|
210
|
-
* -
|
|
211
|
-
* -
|
|
214
|
+
* - By default, each call starts a new execution even if one is already in progress.
|
|
215
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
212
216
|
* - Handles:
|
|
213
217
|
* - Pending state
|
|
214
218
|
* - Success state
|
|
215
219
|
* - Error state
|
|
216
220
|
* - Retry logic
|
|
217
221
|
*/
|
|
218
|
-
execute: (
|
|
222
|
+
execute: (options?: {
|
|
223
|
+
overwriteOngoingExecution?: boolean;
|
|
224
|
+
}) => Promise<QueryState<TData>>;
|
|
219
225
|
/**
|
|
220
|
-
* Re-executes the query if
|
|
226
|
+
* Re-executes the query if needed based on freshness or invalidation.
|
|
221
227
|
*
|
|
222
|
-
* @param
|
|
228
|
+
* @param options - Revalidation options
|
|
229
|
+
* @param options.overwriteOngoingExecution - Whether to overwrite an ongoing execution (default: `true`)
|
|
223
230
|
*
|
|
224
231
|
* @returns The current state if still fresh, otherwise a promise of the new state
|
|
225
232
|
*
|
|
226
233
|
* @remarks
|
|
227
|
-
* - Skips execution if data is still fresh (`staleTime`)
|
|
228
|
-
* -
|
|
234
|
+
* - Skips execution if data is still fresh (`staleTime`) **AND** the query has not been invalidated.
|
|
235
|
+
* - If execution is not skipped, by default it will start a new execution even if one is already in progress.
|
|
236
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
229
237
|
*/
|
|
230
|
-
revalidate: (
|
|
238
|
+
revalidate: (options?: {
|
|
239
|
+
overwriteOngoingExecution?: boolean;
|
|
240
|
+
}) => Promise<QueryState<TData>>;
|
|
231
241
|
/**
|
|
232
242
|
* Marks the query as invalidated and optionally triggers re-execution.
|
|
233
243
|
*
|
|
234
|
-
* @param
|
|
244
|
+
* @param options - Invalidation options
|
|
245
|
+
* @param options.overwriteOngoingExecution - Whether to overwrite an ongoing execution (default: `true`)
|
|
235
246
|
*
|
|
236
247
|
* @returns `true` if execution was triggered, `false` otherwise
|
|
237
248
|
*
|
|
238
249
|
* @remarks
|
|
239
250
|
* - Invalidated queries are treated as stale regardless of `staleTime`.
|
|
240
251
|
* - The next `revalidate` will always execute until a successful result clears the invalidation.
|
|
241
|
-
* - If there are active subscribers
|
|
252
|
+
* - If there are active subscribers: Execution is triggered immediately.
|
|
253
|
+
* - Otherwise: The query remains invalidated and will execute on the next revalidation.
|
|
254
|
+
* - By default, starts a new execution even if one is already in progress.
|
|
255
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
242
256
|
*/
|
|
243
|
-
invalidate: (
|
|
257
|
+
invalidate: (options?: {
|
|
258
|
+
overwriteOngoingExecution?: boolean;
|
|
259
|
+
}) => boolean;
|
|
244
260
|
/**
|
|
245
261
|
* Resets the query state to its initial state.
|
|
246
262
|
*
|
|
@@ -296,14 +312,18 @@ export declare const createQuery: <TData, TVariable extends Record<string, any>
|
|
|
296
312
|
* @remarks
|
|
297
313
|
* - Useful for bulk refetching.
|
|
298
314
|
*/
|
|
299
|
-
executeAll: (
|
|
315
|
+
executeAll: (options?: {
|
|
316
|
+
overwriteOngoingExecution?: boolean;
|
|
317
|
+
}) => void;
|
|
300
318
|
/**
|
|
301
319
|
* Revalidates all query instances.
|
|
302
320
|
*
|
|
303
321
|
* @remarks
|
|
304
322
|
* - Only re-fetches stale queries.
|
|
305
323
|
*/
|
|
306
|
-
revalidateAll: (
|
|
324
|
+
revalidateAll: (options?: {
|
|
325
|
+
overwriteOngoingExecution?: boolean;
|
|
326
|
+
}) => void;
|
|
307
327
|
/**
|
|
308
328
|
* Invalidates all query instances.
|
|
309
329
|
*
|
|
@@ -311,7 +331,9 @@ export declare const createQuery: <TData, TVariable extends Record<string, any>
|
|
|
311
331
|
* - Marks all queries as invalidated and triggers revalidation if active.
|
|
312
332
|
* - Invalidated queries bypass `staleTime` until successfully executed again.
|
|
313
333
|
*/
|
|
314
|
-
invalidateAll: (
|
|
334
|
+
invalidateAll: (options?: {
|
|
335
|
+
overwriteOngoingExecution?: boolean;
|
|
336
|
+
}) => void;
|
|
315
337
|
/**
|
|
316
338
|
* Resets all query instances.
|
|
317
339
|
*/
|
package/react.js
CHANGED
|
@@ -159,17 +159,17 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
159
159
|
}
|
|
160
160
|
return false;
|
|
161
161
|
},
|
|
162
|
-
execute: (overwriteOngoingExecution =
|
|
162
|
+
execute: ({ overwriteOngoingExecution = true } = {}) => {
|
|
163
163
|
return execute(store, variable, overwriteOngoingExecution);
|
|
164
164
|
},
|
|
165
|
-
revalidate: (overwriteOngoingExecution =
|
|
165
|
+
revalidate: ({ overwriteOngoingExecution = true } = {}) => {
|
|
166
166
|
return revalidate(store, variable, overwriteOngoingExecution);
|
|
167
167
|
},
|
|
168
|
-
invalidate: (
|
|
168
|
+
invalidate: (options2) => {
|
|
169
169
|
const { metadata } = internals.get(store);
|
|
170
170
|
metadata.isInvalidated = true;
|
|
171
171
|
if (store.getSubscribers().size > 0) {
|
|
172
|
-
internals.get(store).execute(
|
|
172
|
+
internals.get(store).execute(options2);
|
|
173
173
|
return true;
|
|
174
174
|
}
|
|
175
175
|
return false;
|
|
@@ -325,10 +325,19 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
325
325
|
stores.set(variableHash, store);
|
|
326
326
|
internals.set(store, configureInternals(store, variable, variableHash));
|
|
327
327
|
}
|
|
328
|
-
|
|
328
|
+
function useStore(optionsOrSelector = {}, maybeSelector) {
|
|
329
|
+
let selector;
|
|
330
|
+
let options2;
|
|
331
|
+
if (typeof optionsOrSelector === "function") {
|
|
332
|
+
options2 = {};
|
|
333
|
+
selector = optionsOrSelector;
|
|
334
|
+
} else {
|
|
335
|
+
options2 = optionsOrSelector;
|
|
336
|
+
selector = maybeSelector || vanilla.identity;
|
|
337
|
+
}
|
|
329
338
|
useStoreUpdateNotifier(store, selector);
|
|
330
339
|
useIsomorphicLayoutEffect(() => {
|
|
331
|
-
if (options2.enabled !== false) revalidate(store, variable);
|
|
340
|
+
if (options2.enabled !== false) revalidate(store, variable, false);
|
|
332
341
|
}, [store, options2.enabled]);
|
|
333
342
|
const storeState = store.getState();
|
|
334
343
|
let storeStateToBeUsed = storeState;
|
|
@@ -339,7 +348,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
339
348
|
storeStateToBeUsed = { ...storeState, ...prevState.current };
|
|
340
349
|
}
|
|
341
350
|
return selector(storeStateToBeUsed);
|
|
342
|
-
}
|
|
351
|
+
}
|
|
343
352
|
return Object.assign(useStore, {
|
|
344
353
|
subscribe: store.subscribe,
|
|
345
354
|
getSubscribers: store.getSubscribers,
|
|
@@ -358,8 +367,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
358
367
|
* @remarks
|
|
359
368
|
* - Useful for bulk refetching.
|
|
360
369
|
*/
|
|
361
|
-
executeAll: (
|
|
362
|
-
stores.forEach((store) => internals.get(store).execute(
|
|
370
|
+
executeAll: (options2) => {
|
|
371
|
+
stores.forEach((store) => internals.get(store).execute(options2));
|
|
363
372
|
},
|
|
364
373
|
/**
|
|
365
374
|
* Revalidates all query instances.
|
|
@@ -367,8 +376,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
367
376
|
* @remarks
|
|
368
377
|
* - Only re-fetches stale queries.
|
|
369
378
|
*/
|
|
370
|
-
revalidateAll: (
|
|
371
|
-
stores.forEach((store) => internals.get(store).revalidate(
|
|
379
|
+
revalidateAll: (options2) => {
|
|
380
|
+
stores.forEach((store) => internals.get(store).revalidate(options2));
|
|
372
381
|
},
|
|
373
382
|
/**
|
|
374
383
|
* Invalidates all query instances.
|
|
@@ -377,8 +386,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
377
386
|
* - Marks all queries as invalidated and triggers revalidation if active.
|
|
378
387
|
* - Invalidated queries bypass `staleTime` until successfully executed again.
|
|
379
388
|
*/
|
|
380
|
-
invalidateAll: (
|
|
381
|
-
stores.forEach((store) => internals.get(store).invalidate(
|
|
389
|
+
invalidateAll: (options2) => {
|
|
390
|
+
stores.forEach((store) => internals.get(store).invalidate(options2));
|
|
382
391
|
},
|
|
383
392
|
/**
|
|
384
393
|
* Resets all query instances.
|
package/vanilla/store.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type Subscriber<TState> = (state: TState, prevState: TState) => void;
|
|
|
24
24
|
* - The store performs **shallow change detection per key** before notifying subscribers.
|
|
25
25
|
* - Subscribers are only notified when at least one field changes.
|
|
26
26
|
* - Designed to be framework-agnostic (React bindings are built separately).
|
|
27
|
+
* - By default, `setState` is **disabled on the server** to prevent accidental shared state between requests.
|
|
27
28
|
*/
|
|
28
29
|
export type StoreApi<TState extends Record<string, any>> = {
|
|
29
30
|
setState: (value: SetState<TState>) => void;
|
|
@@ -47,6 +48,7 @@ export type InitStoreOptions<TState extends Record<string, any>> = {
|
|
|
47
48
|
onSubscribe?: (state: TState, store: StoreApi<TState>) => void;
|
|
48
49
|
onUnsubscribe?: (state: TState, store: StoreApi<TState>) => void;
|
|
49
50
|
onLastUnsubscribe?: (state: TState, store: StoreApi<TState>) => void;
|
|
51
|
+
allowSetStateServerSide?: boolean;
|
|
50
52
|
};
|
|
51
53
|
/**
|
|
52
54
|
* Creates a vanilla store with pub-sub capabilities.
|
|
@@ -64,6 +66,9 @@ export type InitStoreOptions<TState extends Record<string, any>> = {
|
|
|
64
66
|
* - Subscribers are only notified when at least one updated field changes (using `Object.is` comparison).
|
|
65
67
|
* - Subscribers receive both the new state and the previous state.
|
|
66
68
|
* - Lifecycle hooks allow side-effect management tied to subscription count.
|
|
69
|
+
* - By default, `setState` is **disabled on the server** to prevent accidental shared state between requests.
|
|
70
|
+
* - This avoids leaking data between users in server environments.
|
|
71
|
+
* - You can override this by setting `allowSetStateServerSide: true`.
|
|
67
72
|
*
|
|
68
73
|
* @example
|
|
69
74
|
* const store = initStore({ count: 0 });
|
package/vanilla.js
CHANGED
|
@@ -72,7 +72,8 @@ const initStore = (initialState, options = {}) => {
|
|
|
72
72
|
onFirstSubscribe = noop,
|
|
73
73
|
onSubscribe = noop,
|
|
74
74
|
onUnsubscribe = noop,
|
|
75
|
-
onLastUnsubscribe = noop
|
|
75
|
+
onLastUnsubscribe = noop,
|
|
76
|
+
allowSetStateServerSide = false
|
|
76
77
|
} = options;
|
|
77
78
|
const subscribers = /* @__PURE__ */ new Set();
|
|
78
79
|
const getSubscribers = () => subscribers;
|
|
@@ -89,6 +90,12 @@ const initStore = (initialState, options = {}) => {
|
|
|
89
90
|
let state = initialState;
|
|
90
91
|
const getState = () => state;
|
|
91
92
|
const setState = (value) => {
|
|
93
|
+
if (!isClient && !allowSetStateServerSide) {
|
|
94
|
+
console.error(
|
|
95
|
+
"setState on the server is not allowed by default. Set `allowSetStateServerSide: true` to allow it."
|
|
96
|
+
);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
92
99
|
const prevState = state;
|
|
93
100
|
const newValue = getValue(value, state);
|
|
94
101
|
for (const key in newValue) {
|