floppy-disk 3.6.1 → 3.7.0-beta.2
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-mutation.d.mts +1 -11
- package/esm/react/create-query.d.mts +154 -19
- package/esm/react/create-stores.d.mts +32 -14
- package/esm/react/create-stream.d.mts +88 -0
- package/esm/react.d.mts +1 -0
- package/esm/react.mjs +313 -96
- package/package.json +4 -1
- package/react/create-mutation.d.ts +1 -11
- package/react/create-query.d.ts +154 -19
- package/react/create-stores.d.ts +32 -14
- package/react/create-stream.d.ts +88 -0
- package/react.d.ts +1 -0
- package/react.js +313 -95
package/react/create-query.d.ts
CHANGED
|
@@ -56,22 +56,156 @@ export type QueryState<TData, TError> = {
|
|
|
56
56
|
} | {
|
|
57
57
|
state: "SUCCESS_BUT_REVALIDATION_ERROR";
|
|
58
58
|
isSuccess: true;
|
|
59
|
-
isError:
|
|
59
|
+
isError: true;
|
|
60
60
|
data: TData;
|
|
61
61
|
dataUpdatedAt: number;
|
|
62
62
|
dataStaleAt: undefined | number;
|
|
63
63
|
error: TError;
|
|
64
64
|
errorUpdatedAt: number;
|
|
65
65
|
});
|
|
66
|
+
type Internal<TData, TError> = {
|
|
67
|
+
isInvalidated?: boolean;
|
|
68
|
+
promise?: Promise<QueryState<TData, TError>> | undefined;
|
|
69
|
+
promiseResolver?: ((value: QueryState<TData, TError> | PromiseLike<QueryState<TData, TError>>) => void) | undefined;
|
|
70
|
+
retryTimeoutId?: number;
|
|
71
|
+
retryResolver?: ((value: QueryState<TData, TError> | PromiseLike<QueryState<TData, TError>>) => void) | undefined;
|
|
72
|
+
garbageCollectionTimeoutId?: number;
|
|
73
|
+
rollbackData?: TData | undefined;
|
|
74
|
+
};
|
|
75
|
+
type AdditionalStoreApi<TData, TError> = {
|
|
76
|
+
/**
|
|
77
|
+
* A deterministic hash string derived from the query variable.
|
|
78
|
+
*
|
|
79
|
+
* Used as the unique identifier for this query instance in the internal cache.
|
|
80
|
+
*
|
|
81
|
+
* @remarks
|
|
82
|
+
* - Structurally identical variables will produce the same hash.
|
|
83
|
+
*/
|
|
84
|
+
variableHash: string;
|
|
85
|
+
/**
|
|
86
|
+
* Sets initial data for the query if it has not been initialized.
|
|
87
|
+
*
|
|
88
|
+
* @param data - Initial data
|
|
89
|
+
* @param revalidate - Whether to mark the data as invalidated (will trigger revalidation)
|
|
90
|
+
*
|
|
91
|
+
* @returns `true` if the data was set, `false` otherwise
|
|
92
|
+
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* - Only applies when the query is in the `INITIAL` state.
|
|
95
|
+
* - Useful for hydration or preloaded data.
|
|
96
|
+
*/
|
|
97
|
+
setInitialData: (data: TData, revalidate?: boolean) => boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Executes the query function.
|
|
100
|
+
*
|
|
101
|
+
* @param options - Execution options
|
|
102
|
+
* @param options.overwriteOngoingExecution - Whether to start a new execution instead of reusing an ongoing one (default: `true`)
|
|
103
|
+
*
|
|
104
|
+
* @returns A promise resolving to the latest query state
|
|
105
|
+
*
|
|
106
|
+
* @remarks
|
|
107
|
+
* - By default, each call **starts a new execution** even if one is already in progress.
|
|
108
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
109
|
+
* - Handles:
|
|
110
|
+
* - Pending state
|
|
111
|
+
* - Success state
|
|
112
|
+
* - Error state
|
|
113
|
+
* - Retry logic
|
|
114
|
+
*/
|
|
115
|
+
execute: (options?: {
|
|
116
|
+
overwriteOngoingExecution?: boolean;
|
|
117
|
+
}) => Promise<QueryState<TData, TError>>;
|
|
118
|
+
/**
|
|
119
|
+
* Re-executes the query if needed based on freshness or invalidation.
|
|
120
|
+
*
|
|
121
|
+
* @param options - Revalidation options
|
|
122
|
+
* @param options.overwriteOngoingExecution - Whether to overwrite an ongoing execution (default: `true`)
|
|
123
|
+
*
|
|
124
|
+
* @returns The current state if still fresh, otherwise a promise of the new state
|
|
125
|
+
*
|
|
126
|
+
* @remarks
|
|
127
|
+
* - Skips execution if data is still fresh (`staleTime`) **AND** the query has not been invalidated.
|
|
128
|
+
* - If execution is not skipped, by default it will start a new execution even if one is already in progress.
|
|
129
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
130
|
+
*/
|
|
131
|
+
revalidate: (options?: {
|
|
132
|
+
overwriteOngoingExecution?: boolean;
|
|
133
|
+
}) => Promise<QueryState<TData, TError>>;
|
|
134
|
+
/**
|
|
135
|
+
* Marks the query as invalidated and optionally triggers re-execution.
|
|
136
|
+
*
|
|
137
|
+
* @param options - Invalidation options
|
|
138
|
+
* @param options.overwriteOngoingExecution - Whether to overwrite an ongoing execution (default: `true`)
|
|
139
|
+
*
|
|
140
|
+
* @returns `true` if execution was triggered, `false` otherwise
|
|
141
|
+
*
|
|
142
|
+
* @remarks
|
|
143
|
+
* - Invalidated queries are treated as stale regardless of `staleTime`.
|
|
144
|
+
* - The next `revalidate` will always execute until a successful result clears the invalidation.
|
|
145
|
+
* - If there are active subscribers: Execution is triggered immediately.
|
|
146
|
+
* - Otherwise: The query remains invalidated and will execute on the next revalidation.
|
|
147
|
+
* - By default, starts a new execution even if one is already in progress.
|
|
148
|
+
* - Set `overwriteOngoingExecution: false` to reuse an ongoing execution (deduplication).
|
|
149
|
+
*/
|
|
150
|
+
invalidate: (options?: {
|
|
151
|
+
overwriteOngoingExecution?: boolean;
|
|
152
|
+
}) => boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Resets the query state to its initial state.
|
|
155
|
+
*
|
|
156
|
+
* @remarks
|
|
157
|
+
* - Cancels retry logic and ignores any ongoing execution results.
|
|
158
|
+
*/
|
|
159
|
+
reset: () => void;
|
|
160
|
+
/**
|
|
161
|
+
* Deletes the query store for the current variable.
|
|
162
|
+
*
|
|
163
|
+
* @returns `true` if deleted, `false` otherwise
|
|
164
|
+
*
|
|
165
|
+
* @remarks
|
|
166
|
+
* - Cannot delete while there are active subscribers.
|
|
167
|
+
*/
|
|
168
|
+
delete: () => boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Performs an optimistic update on the query data.
|
|
171
|
+
*
|
|
172
|
+
* @param data - Optimistic data to set
|
|
173
|
+
*
|
|
174
|
+
* @returns Controls for managing the optimistic update
|
|
175
|
+
*
|
|
176
|
+
* @remarks
|
|
177
|
+
* - Temporarily replaces the current data.
|
|
178
|
+
* - Stores previous data for rollback.
|
|
179
|
+
* - Commonly used with mutations for instant UI updates.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* const { rollback, revalidate } = query.optimisticUpdate(newData);
|
|
183
|
+
*/
|
|
184
|
+
optimisticUpdate: (data: TData) => {
|
|
185
|
+
revalidate: () => Promise<QueryState<TData, TError>>;
|
|
186
|
+
rollback: () => TData;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Restores the data before the last optimistic update.
|
|
190
|
+
*
|
|
191
|
+
* @returns The restored data
|
|
192
|
+
*
|
|
193
|
+
* @remarks
|
|
194
|
+
* - Should be used if an optimistic update fails.
|
|
195
|
+
*/
|
|
196
|
+
rollbackOptimisticUpdate: () => TData;
|
|
197
|
+
/**
|
|
198
|
+
* Internal data, do not mutate!
|
|
199
|
+
*/
|
|
200
|
+
internal: Readonly<Internal<TData, TError>>;
|
|
201
|
+
};
|
|
66
202
|
/**
|
|
67
203
|
* Configuration options for a query.
|
|
68
204
|
*
|
|
69
205
|
* @remarks
|
|
70
206
|
* Controls caching, retry behavior, lifecycle, and side effects of an async operation.
|
|
71
207
|
*/
|
|
72
|
-
export type QueryOptions<TData, TVariable extends StoreKey, TError = Error> = InitStoreOptions<QueryState<TData, TError>, {
|
|
73
|
-
variableHash: string;
|
|
74
|
-
}> & {
|
|
208
|
+
export type QueryOptions<TData, TVariable extends StoreKey, TError = Error> = InitStoreOptions<QueryState<TData, TError>, AdditionalStoreApi<TData, TError>> & {
|
|
75
209
|
/**
|
|
76
210
|
* Time (in milliseconds) that data is considered fresh.
|
|
77
211
|
*
|
|
@@ -219,19 +353,19 @@ export declare const createQuery: <TData, TVariable extends StoreKey = never, TE
|
|
|
219
353
|
initialData?: never;
|
|
220
354
|
initialDataIsStale?: never;
|
|
221
355
|
})) => QueryState<TData, TError>) & {
|
|
222
|
-
|
|
356
|
+
setState: (value: SetStateInput<QueryState<TData, TError>>) => void;
|
|
357
|
+
getState: () => QueryState<TData, TError>;
|
|
358
|
+
subscribe: (subscriber: import("../vanilla.ts").Subscriber<QueryState<TData, TError>>) => () => void;
|
|
359
|
+
getSubscriberCount: () => number;
|
|
223
360
|
/**
|
|
224
|
-
*
|
|
361
|
+
* A deterministic hash string derived from the query variable.
|
|
362
|
+
*
|
|
363
|
+
* Used as the unique identifier for this query instance in the internal cache.
|
|
364
|
+
*
|
|
365
|
+
* @remarks
|
|
366
|
+
* - Structurally identical variables will produce the same hash.
|
|
225
367
|
*/
|
|
226
|
-
|
|
227
|
-
isInvalidated?: boolean;
|
|
228
|
-
promise?: Promise<QueryState<TData, TError>> | undefined;
|
|
229
|
-
promiseResolver?: ((value: QueryState<TData, TError> | PromiseLike<QueryState<TData, TError>>) => void) | undefined;
|
|
230
|
-
retryTimeoutId?: number;
|
|
231
|
-
retryResolver?: ((value: QueryState<TData, TError> | PromiseLike<QueryState<TData, TError>>) => void) | undefined;
|
|
232
|
-
garbageCollectionTimeoutId?: number;
|
|
233
|
-
rollbackData?: TData | undefined;
|
|
234
|
-
};
|
|
368
|
+
variableHash: string;
|
|
235
369
|
/**
|
|
236
370
|
* Sets initial data for the query if it has not been initialized.
|
|
237
371
|
*
|
|
@@ -344,10 +478,10 @@ export declare const createQuery: <TData, TVariable extends StoreKey = never, TE
|
|
|
344
478
|
* - Should be used if an optimistic update fails.
|
|
345
479
|
*/
|
|
346
480
|
rollbackOptimisticUpdate: () => TData;
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
481
|
+
/**
|
|
482
|
+
* Internal data, do not mutate!
|
|
483
|
+
*/
|
|
484
|
+
internal: Readonly<Internal<TData, TError>>;
|
|
351
485
|
}) & {
|
|
352
486
|
/**
|
|
353
487
|
* Executes all query instances.
|
|
@@ -382,3 +516,4 @@ export declare const createQuery: <TData, TVariable extends StoreKey = never, TE
|
|
|
382
516
|
*/
|
|
383
517
|
resetAll: () => void;
|
|
384
518
|
};
|
|
519
|
+
export {};
|
package/react/create-stores.d.ts
CHANGED
|
@@ -1,8 +1,37 @@
|
|
|
1
|
-
import { type InitStoreOptions } from "../vanilla.ts";
|
|
1
|
+
import { type InitStoreOptions, type StoreApi } from "../vanilla.ts";
|
|
2
2
|
type GoodInputForHash = string | number | boolean | null | Date;
|
|
3
3
|
export type StoreKey = GoodInputForHash | {
|
|
4
4
|
[key: string | number]: StoreKey | StoreKey[];
|
|
5
5
|
};
|
|
6
|
+
type AdditionalStoreApi<TKey> = {
|
|
7
|
+
/**
|
|
8
|
+
* The original key used to identify this store instance.\
|
|
9
|
+
* This value is not hashed and is preserved as-is.
|
|
10
|
+
*/
|
|
11
|
+
key: TKey;
|
|
12
|
+
/**
|
|
13
|
+
* A deterministic hash string derived from {@link key}.
|
|
14
|
+
*
|
|
15
|
+
* Used internally as the unique identifier for caching and retrieving store instances.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* - Guarantees that structurally identical keys produce the same hash.
|
|
19
|
+
*/
|
|
20
|
+
keyHash: string;
|
|
21
|
+
/**
|
|
22
|
+
* Deletes this store instance from the internal cache.
|
|
23
|
+
*
|
|
24
|
+
* @returns `true` if the store was successfully deleted, otherwise `false`.
|
|
25
|
+
*
|
|
26
|
+
* @remarks
|
|
27
|
+
* - If there are active subscribers, the deletion is ignored and `false` is returned.
|
|
28
|
+
* - When deletion succeeds:
|
|
29
|
+
* - The store is removed from the cache.
|
|
30
|
+
* - Its state is reset to the initial state.
|
|
31
|
+
* - Intended for manual cleanup of unused or ephemeral stores.
|
|
32
|
+
*/
|
|
33
|
+
delete: () => boolean;
|
|
34
|
+
};
|
|
6
35
|
/**
|
|
7
36
|
* Creates a factory for multiple stores identified by a key.
|
|
8
37
|
*
|
|
@@ -36,23 +65,12 @@ export type StoreKey = GoodInputForHash | {
|
|
|
36
65
|
*
|
|
37
66
|
* @see https://floppy-disk.vercel.app/docs/stores
|
|
38
67
|
*/
|
|
39
|
-
export declare const createStores: <TState extends Record<string, any>, TKey extends StoreKey>(initialState: TState, options?: InitStoreOptions<TState, {
|
|
40
|
-
key: TKey;
|
|
41
|
-
keyHash: string;
|
|
42
|
-
}>) => (key?: TKey) => ((options?: {
|
|
68
|
+
export declare const createStores: <TState extends Record<string, any>, TKey extends StoreKey>(initialState: TState, options?: InitStoreOptions<TState, AdditionalStoreApi<TKey>>) => (key?: TKey) => ((options?: {
|
|
43
69
|
/**
|
|
44
70
|
* Initial state used on first render (and will also update the store state right after that)
|
|
45
71
|
*
|
|
46
72
|
* If provided, `initialState` will be applied **once per store instance**
|
|
47
73
|
*/
|
|
48
74
|
initialState?: Partial<TState>;
|
|
49
|
-
}) => TState) &
|
|
50
|
-
delete: () => boolean;
|
|
51
|
-
setState: (value: import("../vanilla.ts").SetStateInput<TState>) => void;
|
|
52
|
-
getState: () => TState;
|
|
53
|
-
subscribe: (subscriber: import("../vanilla.ts").Subscriber<TState>) => () => void;
|
|
54
|
-
getSubscriberCount: () => number;
|
|
55
|
-
key: TKey;
|
|
56
|
-
keyHash: string;
|
|
57
|
-
};
|
|
75
|
+
}) => TState) & StoreApi<TState> & AdditionalStoreApi<TKey>;
|
|
58
76
|
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type InitStoreOptions, type StoreApi } from "../vanilla.ts";
|
|
2
|
+
import type { StoreKey } from "./create-stores.ts";
|
|
3
|
+
type StreamDataState<TData, TError> = {
|
|
4
|
+
state: "INITIAL";
|
|
5
|
+
isSuccess: false;
|
|
6
|
+
isError: false;
|
|
7
|
+
data: undefined;
|
|
8
|
+
dataUpdatedAt: undefined;
|
|
9
|
+
error: undefined;
|
|
10
|
+
errorUpdatedAt: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
state: "SUCCESS";
|
|
13
|
+
isSuccess: true;
|
|
14
|
+
isError: false;
|
|
15
|
+
data: TData;
|
|
16
|
+
dataUpdatedAt: number;
|
|
17
|
+
error: undefined;
|
|
18
|
+
errorUpdatedAt: undefined;
|
|
19
|
+
} | {
|
|
20
|
+
state: "ERROR";
|
|
21
|
+
isSuccess: false;
|
|
22
|
+
isError: true;
|
|
23
|
+
data: undefined;
|
|
24
|
+
dataUpdatedAt: undefined;
|
|
25
|
+
error: TError;
|
|
26
|
+
errorUpdatedAt: number;
|
|
27
|
+
} | {
|
|
28
|
+
state: "SUCCESS_BUT_THEN_ERROR";
|
|
29
|
+
isSuccess: true;
|
|
30
|
+
isError: true;
|
|
31
|
+
data: TData;
|
|
32
|
+
dataUpdatedAt: number;
|
|
33
|
+
error: TError;
|
|
34
|
+
errorUpdatedAt: number;
|
|
35
|
+
};
|
|
36
|
+
export type StreamState<TData, TError> = ({
|
|
37
|
+
connectionState: "INITIAL";
|
|
38
|
+
connectingAt: undefined;
|
|
39
|
+
connectedAt: undefined;
|
|
40
|
+
disconnectedAt: undefined;
|
|
41
|
+
} & Extract<StreamDataState<TData, TError>, {
|
|
42
|
+
state: "INITIAL";
|
|
43
|
+
}>) | ({
|
|
44
|
+
connectionState: "CONNECTING";
|
|
45
|
+
connectingAt: number;
|
|
46
|
+
connectedAt: number | undefined;
|
|
47
|
+
disconnectedAt: number | undefined;
|
|
48
|
+
} & StreamDataState<TData, TError>) | ({
|
|
49
|
+
connectionState: "CONNECTED";
|
|
50
|
+
connectingAt: number;
|
|
51
|
+
connectedAt: number;
|
|
52
|
+
disconnectedAt: undefined;
|
|
53
|
+
} & StreamDataState<TData, TError>) | ({
|
|
54
|
+
connectionState: "DISCONNECTED";
|
|
55
|
+
connectingAt: number;
|
|
56
|
+
connectedAt: number | undefined;
|
|
57
|
+
disconnectedAt: number;
|
|
58
|
+
} & StreamDataState<TData, TError>);
|
|
59
|
+
type DisconnectTrigger = "last-unsubscribe" | "document-hidden" | "offline";
|
|
60
|
+
type ReconnectTrigger = "first-subscribe" | "document-visible" | "online";
|
|
61
|
+
type AdditionalStoreApi<TConnection> = {
|
|
62
|
+
variableHash: string;
|
|
63
|
+
connection: {
|
|
64
|
+
get: () => Readonly<TConnection> | undefined;
|
|
65
|
+
reconnect: () => void;
|
|
66
|
+
disconnect: () => void;
|
|
67
|
+
};
|
|
68
|
+
data: {
|
|
69
|
+
reset: () => void;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export type StreamOptions<TConnection, TData, TError = Error> = InitStoreOptions<StreamState<TData, TError>, AdditionalStoreApi<TConnection>> & {
|
|
73
|
+
connection?: {
|
|
74
|
+
disconnectOn?: (trigger: DisconnectTrigger, state: StreamState<TData, TError>) => false | number;
|
|
75
|
+
reconnectOn?: (trigger: ReconnectTrigger, state: StreamState<TData, TError>) => boolean;
|
|
76
|
+
};
|
|
77
|
+
data?: {
|
|
78
|
+
gcTime?: number;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export declare const experimental_createStream: <TConnection, TData, TVariable extends StoreKey, TError = Error>(connect: (variable: TVariable, emit: {
|
|
82
|
+
connected: () => void;
|
|
83
|
+
data: (reducer: (data: TData | undefined) => TData) => void;
|
|
84
|
+
error: (error: TError) => void;
|
|
85
|
+
}) => TConnection, disconnect: (connection: TConnection) => void, options?: StreamOptions<TConnection, TData, TError>) => (variable?: TVariable) => ((options?: {
|
|
86
|
+
initialData?: TData;
|
|
87
|
+
}) => StreamState<TData, TError>) & StoreApi<StreamState<TData, TError>> & AdditionalStoreApi<TConnection>;
|
|
88
|
+
export {};
|
package/react.d.ts
CHANGED
|
@@ -5,3 +5,4 @@ export * from "./react/create-stores.ts";
|
|
|
5
5
|
export * from "./react/create-query.ts";
|
|
6
6
|
export { createMutation, type MutationOptions, type MutationState, } from "./react/create-mutation.ts";
|
|
7
7
|
export * from "./react/use-mutation.ts";
|
|
8
|
+
export * from "./react/create-stream.ts";
|