@sweidos/eidos 2.2.0 → 2.3.0
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 +254 -15
- package/dist/action.d.ts +22 -0
- package/dist/async-storage-adapter.d.ts +25 -0
- package/dist/debug.d.ts +46 -0
- package/dist/debug.js +43 -0
- package/dist/debug.js.map +1 -0
- package/dist/devtools.js +185 -5
- package/dist/eidos-sw.js +60 -19
- package/dist/eidos.cjs +5 -5
- package/dist/eidos.cjs.map +1 -1
- package/dist/idb.d.ts +10 -0
- package/dist/index.d.ts +20 -647
- package/dist/index.js +37 -34
- package/dist/internal/url-base64.d.ts +2 -0
- package/dist/query.d.ts +1 -2
- package/dist/queue-storage.d.ts +12 -0
- package/dist/queue-sync.d.ts +32 -0
- package/dist/react/Provider.d.ts +16 -0
- package/dist/react/ProviderRN.d.ts +0 -1
- package/dist/react/hooks.d.ts +51 -0
- package/dist/replay.d.ts +15 -0
- package/dist/resource.d.ts +32 -0
- package/dist/resource.js +80 -78
- package/dist/resource.js.map +1 -1
- package/dist/runtime-rn.d.ts +0 -1
- package/dist/runtime.d.ts +39 -0
- package/dist/runtime.js +24 -21
- package/dist/runtime.js.map +1 -1
- package/dist/store-slices.d.ts +26 -0
- package/dist/store.d.ts +15 -0
- package/dist/stores.d.ts +64 -0
- package/dist/sveltekit.d.ts +0 -1
- package/dist/sw-bridge.d.ts +24 -0
- package/dist/sw-bridge.js +69 -54
- package/dist/sw-bridge.js.map +1 -1
- package/dist/testing.d.ts +1 -2
- package/dist/types.d.ts +305 -0
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/vite.d.ts +0 -1
- package/package.json +7 -5
package/dist/idb.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ActionQueueItem } from './types';
|
|
2
|
+
import { QueueStorage } from './queue-storage';
|
|
3
|
+
export declare function idbAddToQueue(item: ActionQueueItem): Promise<void>;
|
|
4
|
+
export declare function idbGetQueue(): Promise<ActionQueueItem[]>;
|
|
5
|
+
export declare function idbUpdateQueueItem(id: string, update: Partial<ActionQueueItem>): Promise<void>;
|
|
6
|
+
export declare function idbRemoveFromQueue(id: string): Promise<void>;
|
|
7
|
+
export declare function idbGetPendingItems(): Promise<ActionQueueItem[]>;
|
|
8
|
+
export declare function idbClearQueue(): Promise<void>;
|
|
9
|
+
/** IndexedDB-backed QueueStorage implementation (default for browser environments). */
|
|
10
|
+
export declare const idbQueueStorage: QueueStorage;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,647 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
/** Max retry attempts before marking as failed. Default: 3. */
|
|
22
|
-
maxRetries?: number;
|
|
23
|
-
/** Human-readable name for the action (used in devtools). */
|
|
24
|
-
name?: string;
|
|
25
|
-
/**
|
|
26
|
-
* Prefixes the registered action id (`namespace::name`). Use to avoid
|
|
27
|
-
* collisions when two actions share a name (e.g. across micro-frontends,
|
|
28
|
-
* or two `createOrder` actions in different modules) — without a
|
|
29
|
-
* namespace, the second registration silently overwrites the first.
|
|
30
|
-
*/
|
|
31
|
-
namespace?: string;
|
|
32
|
-
/**
|
|
33
|
-
* Replay order when multiple queued actions are pending.
|
|
34
|
-
* `'high'` items replay before `'normal'`, which replay before `'low'`.
|
|
35
|
-
* Each tier completes fully before the next tier begins.
|
|
36
|
-
* Default: `'normal'`.
|
|
37
|
-
*/
|
|
38
|
-
priority?: 'high' | 'normal' | 'low';
|
|
39
|
-
/**
|
|
40
|
-
* Called immediately before the async function executes, with the same args
|
|
41
|
-
* plus a trailing `ActionContext`. Use to apply an optimistic UI update (add
|
|
42
|
-
* item, mark as pending, etc.) and to capture `idempotencyKey` for later
|
|
43
|
-
* `handle.cancel(idempotencyKey)` calls. Called on every invocation —
|
|
44
|
-
* online, offline, and during queue replay.
|
|
45
|
-
*/
|
|
46
|
-
onOptimistic?: (...args: [...TArgs, ActionContext]) => void;
|
|
47
|
-
/**
|
|
48
|
-
* Called when the action permanently fails and will not be retried.
|
|
49
|
-
* - `best-effort`: called on first throw.
|
|
50
|
-
* - `neverLose`: called when `maxRetries` is exhausted (status → `'failed'`).
|
|
51
|
-
* Use to revert the optimistic update.
|
|
52
|
-
*/
|
|
53
|
-
onRollback?: (...args: [...TArgs, ActionContext]) => void;
|
|
54
|
-
/**
|
|
55
|
-
* Declarative conflict-resolution strategy used during queue replay when
|
|
56
|
-
* the server responds with a 4xx status (conflict, gone, unprocessable,
|
|
57
|
-
* etc.). If not provided, 4xx errors are treated identically to other
|
|
58
|
-
* errors (retried until `maxRetries` is exhausted, then `onRollback` is
|
|
59
|
-
* called). See `ConflictConfig`.
|
|
60
|
-
*/
|
|
61
|
-
conflict?: ConflictConfig;
|
|
62
|
-
/**
|
|
63
|
-
* When `true`, each invocation gets an `AbortController` whose `signal` is
|
|
64
|
-
* passed via `ActionContext.signal`. Forward it to `fetch`/etc. so
|
|
65
|
-
* `handle.cancel(idempotencyKey)` can abort an in-flight call, or remove a
|
|
66
|
-
* not-yet-replayed queued item.
|
|
67
|
-
*/
|
|
68
|
-
cancellable?: boolean;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Passed as an extra argument after the declared params to `neverLose` actions,
|
|
73
|
-
* on every invocation (initial call, offline queue, and replay). The same
|
|
74
|
-
* `idempotencyKey` is reused across all retries of one logical invocation —
|
|
75
|
-
* forward it to your server (e.g. as an `Idempotency-Key` header) so a retry
|
|
76
|
-
* that reaches the server after a dropped response doesn't double-execute.
|
|
77
|
-
*/
|
|
78
|
-
export declare interface ActionContext {
|
|
79
|
-
idempotencyKey: string;
|
|
80
|
-
/** 0 on the first attempt, incremented on each replay retry. */
|
|
81
|
-
attempt: number;
|
|
82
|
-
/** Set when `config.cancellable` is true. Forward to `fetch`/etc. for cancellation support. */
|
|
83
|
-
signal?: AbortSignal;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Every action function receives its declared args plus a trailing
|
|
88
|
-
* `ActionContext` — on every invocation (online, offline, and replay).
|
|
89
|
-
*/
|
|
90
|
-
export declare type ActionFn<TArgs extends unknown[], TReturn> = (...args: [...TArgs, ActionContext]) => Promise<TReturn>;
|
|
91
|
-
|
|
92
|
-
export declare interface ActionHandle<TArgs extends any[], TReturn> {
|
|
93
|
-
(...args: TArgs): Promise<TReturn | QueuedResult>;
|
|
94
|
-
readonly id: string;
|
|
95
|
-
readonly config: ActionConfig;
|
|
96
|
-
/**
|
|
97
|
-
* Cancel an invocation by its `idempotencyKey` (from `ActionContext` /
|
|
98
|
-
* `onOptimistic`). Aborts the in-flight call if `cancellable: true` and
|
|
99
|
-
* still running, otherwise removes a not-yet-replayed queued item.
|
|
100
|
-
* Returns `true` if something was cancelled/removed.
|
|
101
|
-
*/
|
|
102
|
-
cancel: (idempotencyKey: string) => Promise<boolean>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export declare interface ActionQueueItem {
|
|
106
|
-
/** Shape version this item was persisted with. Items from before v2 are migrated on load. */
|
|
107
|
-
schemaVersion: number;
|
|
108
|
-
id: string;
|
|
109
|
-
/** ID of the registered action (maps to the function in the registry). */
|
|
110
|
-
actionId: string;
|
|
111
|
-
actionName: string;
|
|
112
|
-
/**
|
|
113
|
-
* Stable per-invocation key, generated once and reused across every retry/replay
|
|
114
|
-
* of this item. Pass to your server as an idempotency key so retries that reach
|
|
115
|
-
* the server after a dropped response don't double-execute.
|
|
116
|
-
*/
|
|
117
|
-
idempotencyKey: string;
|
|
118
|
-
args: unknown[];
|
|
119
|
-
queuedAt: number;
|
|
120
|
-
retryCount: number;
|
|
121
|
-
maxRetries: number;
|
|
122
|
-
status: 'pending' | 'replaying' | 'succeeded' | 'failed';
|
|
123
|
-
/** Replay priority. High items replay before normal, normal before low. Default: 'normal'. */
|
|
124
|
-
priority?: 'high' | 'normal' | 'low';
|
|
125
|
-
error?: string;
|
|
126
|
-
completedAt?: number;
|
|
127
|
-
/** Earliest timestamp at which this item should be retried (exponential backoff). */
|
|
128
|
-
nextRetryAt?: number;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** A handle returned by either `resource()` or `resourcePattern()`. */
|
|
132
|
-
export declare type AnyResourceHandle = ResourceHandle<any> | PatternResourceHandle;
|
|
133
|
-
|
|
134
|
-
/** Minimal subset of @react-native-async-storage/async-storage (or any compatible key-value store). */
|
|
135
|
-
export declare interface AsyncStorageLike {
|
|
136
|
-
getItem(key: string): Promise<string | null>;
|
|
137
|
-
setItem(key: string, value: string): Promise<void>;
|
|
138
|
-
removeItem(key: string): Promise<void>;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* QueueStorage implementation backed by any AsyncStorage-compatible API.
|
|
143
|
-
* Pass the AsyncStorage singleton from @react-native-async-storage/async-storage
|
|
144
|
-
* (or MMKV, SQLite, or any store that satisfies AsyncStorageLike).
|
|
145
|
-
*/
|
|
146
|
-
export declare class AsyncStorageQueueStorage implements QueueStorage {
|
|
147
|
-
private readonly storage;
|
|
148
|
-
constructor(storage: AsyncStorageLike);
|
|
149
|
-
private readAll;
|
|
150
|
-
private writeAll;
|
|
151
|
-
add(item: ActionQueueItem): Promise<void>;
|
|
152
|
-
getAll(): Promise<ActionQueueItem[]>;
|
|
153
|
-
getPending(): Promise<ActionQueueItem[]>;
|
|
154
|
-
update(id: string, patch: Partial<ActionQueueItem>): Promise<void>;
|
|
155
|
-
remove(id: string): Promise<void>;
|
|
156
|
-
clear(): Promise<void>;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export declare type CacheStrategy = 'cache-first' | 'stale-while-revalidate' | 'network-first';
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Cancel an invocation by its `idempotencyKey` (from `ActionContext` /
|
|
163
|
-
* `onOptimistic`). Aborts the in-flight call if `cancellable: true` and
|
|
164
|
-
* still running, otherwise removes a not-yet-replayed queued item.
|
|
165
|
-
* Returns `true` if something was cancelled/removed.
|
|
166
|
-
*
|
|
167
|
-
* Shared by every `ActionHandle.cancel()` and by devtools, which can't
|
|
168
|
-
* address a specific handle from a queue item alone.
|
|
169
|
-
*/
|
|
170
|
-
export declare function cancelByIdempotencyKey(idempotencyKey: string): Promise<boolean>;
|
|
171
|
-
|
|
172
|
-
/** Remove all items from the action queue (storage + in-memory store). */
|
|
173
|
-
export declare function clearQueue(): Promise<void>;
|
|
174
|
-
|
|
175
|
-
export declare interface ConflictConfig {
|
|
176
|
-
/**
|
|
177
|
-
* - `'serverWins'`: drop the queued item, keeping the server's state.
|
|
178
|
-
* - `'clientWins'`: keep retrying — the client's write should eventually
|
|
179
|
-
* be accepted (e.g. once the server-side conflict is cleared).
|
|
180
|
-
* - `'merge'` / `'custom'`: call `resolve` to decide.
|
|
181
|
-
*/
|
|
182
|
-
strategy: 'serverWins' | 'clientWins' | 'merge' | 'custom';
|
|
183
|
-
/** Required for `'merge'` and `'custom'`. */
|
|
184
|
-
resolve?: (ctx: ConflictContext) => ConflictResolution;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Passed to `ConflictConfig.resolve` (for `'merge'`/`'custom'` strategies)
|
|
189
|
-
* when a queued action's replay receives a 4xx response.
|
|
190
|
-
*/
|
|
191
|
-
export declare interface ConflictContext {
|
|
192
|
-
/** Whatever `fn` threw — typically a `Response` or an error with `.status`. */
|
|
193
|
-
error: unknown;
|
|
194
|
-
/** The original arguments the action was queued with. */
|
|
195
|
-
args: any[];
|
|
196
|
-
/** Number of replay attempts so far (0 on first replay). */
|
|
197
|
-
attempt: number;
|
|
198
|
-
idempotencyKey: string;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Outcome of `ConflictConfig.resolve`:
|
|
203
|
-
* - `'retry'`: keep the item queued, retry per normal backoff.
|
|
204
|
-
* - `'skip'`: silently remove the item (no `onRollback`).
|
|
205
|
-
* - `{ resolved: args }`: replace the queued args and retry immediately
|
|
206
|
-
* on the next replay pass.
|
|
207
|
-
*/
|
|
208
|
-
export declare type ConflictResolution = 'retry' | 'skip' | {
|
|
209
|
-
resolved: any[];
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Live state for a single queue item by ID. Returns `undefined` once the item
|
|
214
|
-
* is removed from the queue (after a successful replay or `clearQueue()`).
|
|
215
|
-
* @example
|
|
216
|
-
* // Svelte
|
|
217
|
-
* const item = eidosAction(queuedResult.id)
|
|
218
|
-
* $: status = $item?.status // 'pending' | 'replaying' | 'succeeded' | 'failed' | undefined
|
|
219
|
-
*/
|
|
220
|
-
export declare function eidosAction(id: string): EidosReadable<ActionQueueItem | undefined>;
|
|
221
|
-
|
|
222
|
-
export declare interface EidosConfig {
|
|
223
|
-
/** Path to the eidos service worker. Defaults to '/eidos-sw.js'. */
|
|
224
|
-
swPath?: string;
|
|
225
|
-
/** Automatically replay the action queue on reconnect. Default: true. */
|
|
226
|
-
autoReplay?: boolean;
|
|
227
|
-
/**
|
|
228
|
-
* Opt-in reliability telemetry. Called with a snapshot of cumulative
|
|
229
|
-
* `neverLose` queue outcome counters (`ReliabilityStats`) every
|
|
230
|
-
* `reliabilityReportInterval` ms — wire this up to your analytics backend.
|
|
231
|
-
* Not called if omitted.
|
|
232
|
-
*/
|
|
233
|
-
onReliabilityReport?: (stats: ReliabilityStats) => void;
|
|
234
|
-
/** Interval (ms) between `onReliabilityReport` calls. Default: 60000. */
|
|
235
|
-
reliabilityReportInterval?: number;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Mount once at the root of your application.
|
|
240
|
-
* Registers the service worker and initialises the Eidos runtime.
|
|
241
|
-
*
|
|
242
|
-
* @example
|
|
243
|
-
* <EidosProvider swPath="/eidos-sw.js">
|
|
244
|
-
* <App />
|
|
245
|
-
* </EidosProvider>
|
|
246
|
-
*/
|
|
247
|
-
export declare function EidosProvider({ children, swPath, autoReplay }: EidosProviderProps): JSX.Element;
|
|
248
|
-
|
|
249
|
-
declare interface EidosProviderProps extends EidosConfig {
|
|
250
|
-
children: ReactNode;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/** The action queue. Re-notifies on every queue mutation. */
|
|
254
|
-
export declare const eidosQueue: EidosReadable<ActionQueueItem[]>;
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Queue counts. Re-emits only when a count actually changes, not on every
|
|
258
|
-
* queue mutation (e.g. a status transition that doesn't change counts is skipped).
|
|
259
|
-
*/
|
|
260
|
-
export declare const eidosQueueStats: EidosReadable<{
|
|
261
|
-
pending: number;
|
|
262
|
-
failed: number;
|
|
263
|
-
replaying: number;
|
|
264
|
-
total: number;
|
|
265
|
-
}>;
|
|
266
|
-
|
|
267
|
-
export declare interface EidosReadable<T> {
|
|
268
|
-
/** Subscribe to value changes. Returns an unsubscribe function. */
|
|
269
|
-
subscribe(run: (value: T) => void): () => void;
|
|
270
|
-
/** Read the current value synchronously without subscribing. */
|
|
271
|
-
getState(): T;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Cumulative, session-scoped `neverLose` queue outcome counters — opt-in
|
|
276
|
-
* reliability telemetry. Re-emits only when a counter changes. See
|
|
277
|
-
* `EidosConfig.onReliabilityReport` to forward these to an analytics backend.
|
|
278
|
-
*/
|
|
279
|
-
export declare const eidosReliabilityStats: EidosReadable<ReliabilityStats>;
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Live cache state for a single registered resource URL.
|
|
283
|
-
* @example
|
|
284
|
-
* // Svelte
|
|
285
|
-
* const entry = eidosResource('/api/products')
|
|
286
|
-
* $: hits = $entry?.cacheHits ?? 0
|
|
287
|
-
*/
|
|
288
|
-
export declare function eidosResource(url: string): EidosReadable<ResourceEntry | undefined>;
|
|
289
|
-
|
|
290
|
-
export declare interface EidosState {
|
|
291
|
-
isOnline: boolean;
|
|
292
|
-
swStatus: 'idle' | 'registering' | 'active' | 'error' | 'unsupported';
|
|
293
|
-
swError?: string;
|
|
294
|
-
resources: Record<string, ResourceEntry>;
|
|
295
|
-
queue: ActionQueueItem[];
|
|
296
|
-
reliability: ReliabilityStats;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Online status + SW lifecycle.
|
|
301
|
-
* Only re-emits when isOnline, swStatus, or swError actually changes.
|
|
302
|
-
*/
|
|
303
|
-
export declare const eidosStatus: EidosReadable<{
|
|
304
|
-
isOnline: boolean;
|
|
305
|
-
swStatus: EidosStore['swStatus'];
|
|
306
|
-
swError: string | undefined;
|
|
307
|
-
}>;
|
|
308
|
-
|
|
309
|
-
export declare interface EidosStore extends EidosState, ResourceActions, QueueActions, ReliabilityActions {
|
|
310
|
-
setOnline: (online: boolean) => void;
|
|
311
|
-
setSwStatus: (status: EidosState['swStatus'], error?: string) => void;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/** Full Eidos state snapshot. Prefer the narrower stores below. */
|
|
315
|
-
export declare const eidosStore: EidosReadable<EidosStore>;
|
|
316
|
-
|
|
317
|
-
export declare interface GeneratedStrategy {
|
|
318
|
-
name: string;
|
|
319
|
-
swStrategy: CacheStrategy;
|
|
320
|
-
cacheName: string;
|
|
321
|
-
/** One-line rationale for why this strategy was chosen. */
|
|
322
|
-
reasoning: string;
|
|
323
|
-
/** Human-readable description of each behavioral step. */
|
|
324
|
-
behavior: string[];
|
|
325
|
-
/** Pseudocode showing the equivalent Workbox config. */
|
|
326
|
-
equivalentCode: string;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
export declare function _getQueueStorage(): QueueStorage | null;
|
|
330
|
-
|
|
331
|
-
declare function _getState(): EidosStore;
|
|
332
|
-
|
|
333
|
-
export declare function getSwRegistration(): ServiceWorkerRegistration | null;
|
|
334
|
-
|
|
335
|
-
export declare function initEidos(config?: EidosConfig): Promise<void>;
|
|
336
|
-
|
|
337
|
-
export declare function isBgSyncSupported(): boolean;
|
|
338
|
-
|
|
339
|
-
declare type Listener = () => void;
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Calls `callback` once each time the action queue drains from non-empty → 0.
|
|
343
|
-
* Framework-agnostic equivalent of `useEidosOnDrain` for Svelte/Vue/vanilla.
|
|
344
|
-
* Returns an unsubscribe function.
|
|
345
|
-
*
|
|
346
|
-
* @example
|
|
347
|
-
* // Svelte
|
|
348
|
-
* onMount(() => onQueueDrain(() => toast.success('All offline actions synced!')))
|
|
349
|
-
*/
|
|
350
|
-
export declare function onQueueDrain(callback: () => void): () => void;
|
|
351
|
-
|
|
352
|
-
/**
|
|
353
|
-
* Handle for a URL pattern (`/api/products/*`, `/api/users/:id`, `**`).
|
|
354
|
-
* The SW intercepts all matching requests automatically — there is no single
|
|
355
|
-
* URL to fetch/cache directly, so only cache-management methods are exposed.
|
|
356
|
-
* Returned by `resourcePattern()`.
|
|
357
|
-
*/
|
|
358
|
-
export declare interface PatternResourceHandle {
|
|
359
|
-
readonly url: string;
|
|
360
|
-
readonly config: ResourceConfig;
|
|
361
|
-
readonly strategy: GeneratedStrategy;
|
|
362
|
-
/** Clears all cache entries matching this pattern. */
|
|
363
|
-
invalidate: () => Promise<void>;
|
|
364
|
-
/** Remove from registry and SW. Required before re-registering the same pattern with different config. */
|
|
365
|
-
unregister: () => void;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
declare interface PushHandlers {
|
|
369
|
-
onNotificationClick?: (data: unknown) => void;
|
|
370
|
-
onSubscriptionExpired?: (sub: PushSubscriptionJSON) => void;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
declare type QueryInvalidator = (queryKey: [string, string]) => void;
|
|
374
|
-
|
|
375
|
-
declare interface QueueActions {
|
|
376
|
-
addQueueItem: (item: ActionQueueItem) => void;
|
|
377
|
-
updateQueueItem: (id: string, update: Partial<ActionQueueItem>) => void;
|
|
378
|
-
batchUpdateQueueItems: (updates: Array<{
|
|
379
|
-
id: string;
|
|
380
|
-
update: Partial<ActionQueueItem>;
|
|
381
|
-
}>) => void;
|
|
382
|
-
removeQueueItem: (id: string) => void;
|
|
383
|
-
hydrateQueue: (items: ActionQueueItem[]) => void;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
export declare interface QueuedResult {
|
|
387
|
-
readonly queued: true;
|
|
388
|
-
readonly id: string;
|
|
389
|
-
readonly message: string;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
export declare interface QueueStorage {
|
|
393
|
-
add(item: ActionQueueItem): Promise<void>;
|
|
394
|
-
getAll(): Promise<ActionQueueItem[]>;
|
|
395
|
-
getPending(): Promise<ActionQueueItem[]>;
|
|
396
|
-
update(id: string, patch: Partial<ActionQueueItem>): Promise<void>;
|
|
397
|
-
remove(id: string): Promise<void>;
|
|
398
|
-
clear(): Promise<void>;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
export declare function registerPushCallbacks(handlers: PushHandlers): void;
|
|
402
|
-
|
|
403
|
-
declare interface ReliabilityActions {
|
|
404
|
-
recordReliabilityEvent: (event: keyof ReliabilityStats) => void;
|
|
405
|
-
resetReliabilityStats: () => void;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Cumulative, session-scoped counters for `neverLose` queue outcomes — opt-in
|
|
410
|
-
* telemetry surfaced via `eidosReliabilityStats` / `useEidosReliabilityStats()`
|
|
411
|
-
* and `EidosConfig.onReliabilityReport`. Reset on page reload (not persisted).
|
|
412
|
-
*/
|
|
413
|
-
export declare interface ReliabilityStats {
|
|
414
|
-
[key: string]: number;
|
|
415
|
-
/** Actions persisted to the queue (offline, or online call that threw). */
|
|
416
|
-
queued: number;
|
|
417
|
-
/** Queue items that executed successfully (first attempt or a retry). */
|
|
418
|
-
succeeded: number;
|
|
419
|
-
/** Queue items that exhausted `maxRetries` and moved to `'failed'`. */
|
|
420
|
-
failed: number;
|
|
421
|
-
/** Replay attempts that failed but will retry (haven't exhausted `maxRetries`). */
|
|
422
|
-
retried: number;
|
|
423
|
-
/** Queue items dropped by a `serverWins`/`merge`/`custom` conflict resolution. */
|
|
424
|
-
conflicted: number;
|
|
425
|
-
/** Queue items removed via `handle.cancel(idempotencyKey)` before replay completed. */
|
|
426
|
-
cancelled: number;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
export declare function replayQueue(): Promise<ReplayResult>;
|
|
430
|
-
|
|
431
|
-
/** Summary returned by replayQueue(). */
|
|
432
|
-
export declare interface ReplayResult {
|
|
433
|
-
/** Items where the registered function was found and called. */
|
|
434
|
-
attempted: number;
|
|
435
|
-
/** Items that resolved successfully. */
|
|
436
|
-
succeeded: number;
|
|
437
|
-
/** Items that failed and have no retries remaining (status: 'failed'). */
|
|
438
|
-
failed: number;
|
|
439
|
-
/** Items that failed but will be retried later (nextRetryAt set). */
|
|
440
|
-
retrying: number;
|
|
441
|
-
/** Items whose actionId had no registered function — likely not yet imported. */
|
|
442
|
-
skipped: number;
|
|
443
|
-
/** Items that received a 4xx response and were dropped via `conflict: { strategy: 'serverWins' }` (or `resolve()` returning `'skip'`). */
|
|
444
|
-
conflicted: number;
|
|
445
|
-
/** Items removed via `handle.cancel(idempotencyKey)` before/during replay. */
|
|
446
|
-
cancelled: number;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Reset a `'failed'` queue item back to `'pending'` so the next
|
|
451
|
-
* `replayQueue()` retries it — clears `error`/`nextRetryAt` and resets
|
|
452
|
-
* `retryCount` to 0. Returns `true` if the item existed and was failed.
|
|
453
|
-
* Used by devtools' per-item "Retry" action.
|
|
454
|
-
*/
|
|
455
|
-
export declare function requeueItem(id: string): Promise<boolean>;
|
|
456
|
-
|
|
457
|
-
export declare function _resetEidos(): void;
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Registers a concrete-URL resource. For URL patterns (`/api/products/*`,
|
|
461
|
-
* `/api/users/:id`, `**`), use `resourcePattern()` instead.
|
|
462
|
-
*/
|
|
463
|
-
export declare function resource<T = unknown>(url: string, config: ResourceConfig): ResourceHandle<T>;
|
|
464
|
-
|
|
465
|
-
declare interface ResourceActions {
|
|
466
|
-
registerResource: (url: string, entry: ResourceEntry) => void;
|
|
467
|
-
updateResource: (url: string, update: Partial<ResourceEntry>) => void;
|
|
468
|
-
unregisterResource: (url: string) => void;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
export declare interface ResourceConfig {
|
|
472
|
-
/** Make this resource available when the device is offline. */
|
|
473
|
-
offline: boolean;
|
|
474
|
-
/** Override the auto-selected caching strategy. */
|
|
475
|
-
strategy?: CacheStrategy;
|
|
476
|
-
/** Custom cache bucket name. Defaults to 'eidos-resources-v1'. */
|
|
477
|
-
cacheName?: string;
|
|
478
|
-
/**
|
|
479
|
-
* Cache schema version. Bump when the response shape changes so old
|
|
480
|
-
* cached entries (a different shape) aren't served from a stale bucket.
|
|
481
|
-
* Appended to `cacheName` as a suffix (e.g. `eidos-resources-v1-v2`).
|
|
482
|
-
* Old-versioned buckets are left in Cache Storage — clear them via
|
|
483
|
-
* `caches.delete()` if needed.
|
|
484
|
-
*/
|
|
485
|
-
version?: string | number;
|
|
486
|
-
/** Max age of cached response in milliseconds. Expired entries trigger a network fetch. */
|
|
487
|
-
maxAge?: number;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
export declare interface ResourceEntry {
|
|
491
|
-
url: string;
|
|
492
|
-
config: ResourceConfig;
|
|
493
|
-
strategy: GeneratedStrategy;
|
|
494
|
-
status: 'idle' | 'fetching' | 'fresh' | 'stale' | 'error' | 'offline';
|
|
495
|
-
cachedAt?: number;
|
|
496
|
-
fetchedAt?: number;
|
|
497
|
-
cacheHits: number;
|
|
498
|
-
cacheMisses: number;
|
|
499
|
-
lastEvent?: 'cache-hit' | 'cache-updated' | 'network-error' | 'cache-cleared';
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
export declare interface ResourceHandle<T = unknown> {
|
|
503
|
-
readonly url: string;
|
|
504
|
-
readonly config: ResourceConfig;
|
|
505
|
-
readonly strategy: GeneratedStrategy;
|
|
506
|
-
fetch: () => Promise<Response>;
|
|
507
|
-
json: () => Promise<T>;
|
|
508
|
-
/** Returns a TanStack Query-compatible options object. */
|
|
509
|
-
query: () => {
|
|
510
|
-
queryKey: [string, string];
|
|
511
|
-
queryFn: () => Promise<T>;
|
|
512
|
-
};
|
|
513
|
-
prefetch: () => Promise<void>;
|
|
514
|
-
invalidate: () => Promise<void>;
|
|
515
|
-
/** Remove from registry and SW. Required before re-registering the same URL with different config. */
|
|
516
|
-
unregister: () => void;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Registers a URL pattern (`/api/products/*`, `/api/users/:id`, `**`). The SW
|
|
521
|
-
* intercepts all matching requests automatically — there is no single URL to
|
|
522
|
-
* fetch/cache directly, so the returned handle only supports cache management
|
|
523
|
-
* (`invalidate`/`unregister`). For a fetchable resource, use `resource()`.
|
|
524
|
-
*/
|
|
525
|
-
export declare function resourcePattern(url: string, config: ResourceConfig): PatternResourceHandle;
|
|
526
|
-
|
|
527
|
-
export declare function sendToWorker(message: Record<string, unknown>): void;
|
|
528
|
-
|
|
529
|
-
export declare function setOfflineSimulation(enabled: boolean): void;
|
|
530
|
-
|
|
531
|
-
/* Excluded from this release type: setQueryInvalidator */
|
|
532
|
-
|
|
533
|
-
/** Override the default IndexedDB queue with a custom storage backend (e.g. AsyncStorage for React Native). */
|
|
534
|
-
export declare function setQueueStorage(s: QueueStorage): void;
|
|
535
|
-
|
|
536
|
-
declare function _subscribe(listener: Listener): () => void;
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Subscribe to online/offline transitions and trigger replayQueue() on
|
|
540
|
-
* reconnect, plus replay any pending items left over from a previous session.
|
|
541
|
-
*
|
|
542
|
-
* Shared by the web (runtime.ts) and React Native (runtime-rn.ts) init paths.
|
|
543
|
-
*
|
|
544
|
-
* WHY subscribe to the store instead of window.addEventListener('online'):
|
|
545
|
-
* setOfflineSimulation() updates the store directly but never fires a real
|
|
546
|
-
* browser `online` event. Watching the store catches both:
|
|
547
|
-
* • Real network reconnects (sw-bridge updates store on window.online)
|
|
548
|
-
* • Simulation toggled off (setOfflineSimulation(false) → store.setOnline(true))
|
|
549
|
-
*
|
|
550
|
-
* Returns an unsubscribe function.
|
|
551
|
-
*/
|
|
552
|
-
export declare function subscribeReplayOnReconnect(): () => void;
|
|
553
|
-
|
|
554
|
-
/** Full Eidos store — prefer the narrower hooks below for performance. */
|
|
555
|
-
export declare function useEidos(): EidosStore;
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Live state for a single queue item by ID. Only re-renders when that specific
|
|
559
|
-
* item changes — cheaper than `useEidosQueue().find(id)` which re-renders on
|
|
560
|
-
* any queue mutation.
|
|
561
|
-
*/
|
|
562
|
-
export declare function useEidosAction(id: string): ActionQueueItem | undefined;
|
|
563
|
-
|
|
564
|
-
export declare function useEidosOnDrain(callback: () => void): void;
|
|
565
|
-
|
|
566
|
-
/** The current action queue. */
|
|
567
|
-
export declare function useEidosQueue(): ActionQueueItem[];
|
|
568
|
-
|
|
569
|
-
/**
|
|
570
|
-
* Queue counts — single subscription, single loop. Re-renders only when a
|
|
571
|
-
* count changes, not on every queue mutation. Use for badges and status bars
|
|
572
|
-
* instead of `useEidosQueue()` when you only need numbers, not full items.
|
|
573
|
-
*/
|
|
574
|
-
export declare function useEidosQueueStats(): {
|
|
575
|
-
pending: number;
|
|
576
|
-
failed: number;
|
|
577
|
-
replaying: number;
|
|
578
|
-
total: number;
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
/**
|
|
582
|
-
* Calls `callback` once each time the action queue drains from non-empty → 0.
|
|
583
|
-
* Stable callback reference not required — always calls the latest version.
|
|
584
|
-
* Use for "all offline actions synced!" toasts.
|
|
585
|
-
*
|
|
586
|
-
* @example
|
|
587
|
-
* useEidosOnDrain(() => toast.success('All offline actions synced!'))
|
|
588
|
-
*/
|
|
589
|
-
/**
|
|
590
|
-
* Cumulative, session-scoped `neverLose` queue outcome counters — opt-in
|
|
591
|
-
* reliability telemetry for dashboards/devtools. Re-renders only when a
|
|
592
|
-
* counter changes.
|
|
593
|
-
*/
|
|
594
|
-
export declare function useEidosReliabilityStats(): ReliabilityStats;
|
|
595
|
-
|
|
596
|
-
/** Live state for a single registered resource URL. */
|
|
597
|
-
export declare function useEidosResource(url: string): ResourceEntry;
|
|
598
|
-
|
|
599
|
-
/** All registered resources — only re-renders when the resources map changes, not on queue mutations. */
|
|
600
|
-
export declare function useEidosResources(): Record<string, ResourceEntry>;
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Online + SW status — cheap subscription, safe to use in header components.
|
|
604
|
-
* Three separate primitive selectors so each only triggers a re-render when
|
|
605
|
-
* its own value changes (no object-reference churn from a combined selector).
|
|
606
|
-
*/
|
|
607
|
-
export declare function useEidosStatus(): {
|
|
608
|
-
isOnline: boolean;
|
|
609
|
-
swStatus: "idle" | "error" | "registering" | "active" | "unsupported";
|
|
610
|
-
swError: string | undefined;
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
export declare const useEidosStore: {
|
|
614
|
-
getState: typeof _getState;
|
|
615
|
-
subscribe: typeof _subscribe;
|
|
616
|
-
setState: (partial: Partial<EidosStore> | ((s: EidosStore) => Partial<EidosStore>)) => void;
|
|
617
|
-
};
|
|
618
|
-
|
|
619
|
-
export declare const VERSION = "2.2.0";
|
|
620
|
-
|
|
621
|
-
/**
|
|
622
|
-
* Bulk-prefetch an array of resource handles concurrently, warming the cache
|
|
623
|
-
* for each one. Useful on login / app init when you know which resources the
|
|
624
|
-
* user will need offline.
|
|
625
|
-
*
|
|
626
|
-
* Pattern handles (containing `*`, `**`, or `:param`) are silently skipped —
|
|
627
|
-
* they match multiple URLs so there is no single URL to prefetch.
|
|
628
|
-
*
|
|
629
|
-
* @example
|
|
630
|
-
* import { warmCache } from '@sweidos/eidos'
|
|
631
|
-
*
|
|
632
|
-
* // In EidosProvider's onReady, or after login:
|
|
633
|
-
* const { warmed, failed } = await warmCache([products, userProfile, settings])
|
|
634
|
-
*/
|
|
635
|
-
export declare function warmCache(handles: ResourceHandle[]): Promise<WarmCacheResult>;
|
|
636
|
-
|
|
637
|
-
/** Summary returned by warmCache(). */
|
|
638
|
-
export declare interface WarmCacheResult {
|
|
639
|
-
/** Resources that were prefetched successfully. */
|
|
640
|
-
warmed: number;
|
|
641
|
-
/** Resources whose prefetch threw (network error, offline, etc.). */
|
|
642
|
-
failed: number;
|
|
643
|
-
/** The raw errors, in input order, for failed handles. */
|
|
644
|
-
errors: unknown[];
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
export { }
|
|
1
|
+
export { resource, resourcePattern, warmCache, setQueryInvalidator } from './resource';
|
|
2
|
+
export { action, replayQueue, clearQueue, cancelByIdempotencyKey, requeueItem } from './action';
|
|
3
|
+
export { initEidos, _resetEidos } from './runtime';
|
|
4
|
+
export type { EidosConfig } from './runtime';
|
|
5
|
+
export { subscribeReplayOnReconnect } from './replay';
|
|
6
|
+
export { setQueueStorage, _getQueueStorage } from './queue-storage';
|
|
7
|
+
export type { QueueStorage } from './queue-storage';
|
|
8
|
+
export { AsyncStorageQueueStorage } from './async-storage-adapter';
|
|
9
|
+
export type { AsyncStorageLike } from './async-storage-adapter';
|
|
10
|
+
export { EidosProvider } from './react/Provider';
|
|
11
|
+
export { useEidos, useEidosResources, useEidosResource, useEidosQueue, useEidosAction, useEidosQueueStats, useEidosStatus, useEidosOnDrain, useEidosReliabilityStats, } from './react/hooks';
|
|
12
|
+
export { VERSION } from './version';
|
|
13
|
+
export { setOfflineSimulation, isBgSyncSupported, getSwRegistration, sendToWorker, registerPushCallbacks, triggerSwUpdate, } from './sw-bridge';
|
|
14
|
+
export { eidosDebug } from './debug';
|
|
15
|
+
export type { EidosDebugSnapshot } from './debug';
|
|
16
|
+
export { useEidosStore } from './store';
|
|
17
|
+
export type { EidosStore } from './store';
|
|
18
|
+
export { eidosStore, eidosQueue, eidosStatus, eidosQueueStats, eidosResource, eidosAction, onQueueDrain, eidosReliabilityStats, } from './stores';
|
|
19
|
+
export type { EidosReadable } from './stores';
|
|
20
|
+
export type { ResourceConfig, ResourceHandle, PatternResourceHandle, AnyResourceHandle, ResourceEntry, GeneratedStrategy, WarmCacheResult, ActionConfig, ActionContext, ActionFn, ActionHandle, ActionQueueItem, QueuedResult, ReplayResult, EidosState, ReliabilityStats, ConflictContext, ConflictResolution, ConflictConfig, CacheStrategy, } from './types';
|