@sweidos/eidos 2.1.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 +290 -22
- package/dist/action.d.ts +22 -0
- package/dist/action.js +47 -47
- package/dist/action.js.map +1 -1
- 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 +350 -21
- 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 -586
- package/dist/index.js +47 -41
- 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/react/hooks.js +30 -27
- package/dist/react/hooks.js.map +1 -1
- 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 +32 -24
- package/dist/runtime.js.map +1 -1
- package/dist/store-slices.d.ts +26 -0
- package/dist/store-slices.js +31 -20
- package/dist/store-slices.js.map +1 -1
- package/dist/store.d.ts +15 -0
- package/dist/store.js +22 -19
- package/dist/store.js.map +1 -1
- package/dist/stores.d.ts +64 -0
- package/dist/stores.js +31 -22
- package/dist/stores.js.map +1 -1
- 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.cjs +3 -2
- package/dist/testing.d.ts +1 -2
- package/dist/testing.js +3 -2
- package/dist/types.d.ts +305 -0
- package/dist/types.js +19 -8
- 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 +9 -7
package/dist/index.js
CHANGED
|
@@ -1,51 +1,57 @@
|
|
|
1
1
|
import { useEidosStore as o } from "./store.js";
|
|
2
|
-
import { getSwRegistration as
|
|
3
|
-
import { resource as
|
|
4
|
-
import { _getQueueStorage as
|
|
5
|
-
import { action as
|
|
6
|
-
import { subscribeReplayOnReconnect as
|
|
7
|
-
import { _resetEidos as
|
|
8
|
-
import { AsyncStorageQueueStorage as
|
|
2
|
+
import { getSwRegistration as i, isBgSyncSupported as t, registerPushCallbacks as s, sendToWorker as u, setOfflineSimulation as m, triggerSwUpdate as a } from "./sw-bridge.js";
|
|
3
|
+
import { resource as n, resourcePattern as p, setQueryInvalidator as c, warmCache as S } from "./resource.js";
|
|
4
|
+
import { _getQueueStorage as E, setQueueStorage as l } from "./queue-storage.js";
|
|
5
|
+
import { action as Q, cancelByIdempotencyKey as y, clearQueue as R, replayQueue as b, requeueItem as I } from "./action.js";
|
|
6
|
+
import { subscribeReplayOnReconnect as w } from "./replay.js";
|
|
7
|
+
import { _resetEidos as D, initEidos as P } from "./runtime.js";
|
|
8
|
+
import { AsyncStorageQueueStorage as k } from "./async-storage-adapter.js";
|
|
9
9
|
import { EidosProvider as B } from "./react/Provider.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { eidosAction as _, eidosQueue as q, eidosQueueStats as x, eidosReliabilityStats as K, eidosResource as N, eidosStatus as T, eidosStore as U, onQueueDrain as V } from "./stores.js";
|
|
11
|
+
import { useEidos as j, useEidosAction as z, useEidosOnDrain as F, useEidosQueue as G, useEidosQueueStats as H, useEidosReliabilityStats as J, useEidosResource as L, useEidosResources as M, useEidosStatus as X } from "./react/hooks.js";
|
|
12
|
+
import { VERSION as Z } from "./version.js";
|
|
13
|
+
import { eidosDebug as ee } from "./debug.js";
|
|
13
14
|
export {
|
|
14
|
-
|
|
15
|
+
k as AsyncStorageQueueStorage,
|
|
15
16
|
B as EidosProvider,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
Z as VERSION,
|
|
18
|
+
E as _getQueueStorage,
|
|
19
|
+
D as _resetEidos,
|
|
20
|
+
Q as action,
|
|
21
|
+
y as cancelByIdempotencyKey,
|
|
22
|
+
R as clearQueue,
|
|
23
|
+
_ as eidosAction,
|
|
24
|
+
ee as eidosDebug,
|
|
25
|
+
q as eidosQueue,
|
|
26
|
+
x as eidosQueueStats,
|
|
27
|
+
K as eidosReliabilityStats,
|
|
28
|
+
N as eidosResource,
|
|
29
|
+
T as eidosStatus,
|
|
30
|
+
U as eidosStore,
|
|
31
|
+
i as getSwRegistration,
|
|
32
|
+
P as initEidos,
|
|
30
33
|
t as isBgSyncSupported,
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
V as onQueueDrain,
|
|
35
|
+
s as registerPushCallbacks,
|
|
36
|
+
b as replayQueue,
|
|
33
37
|
I as requeueItem,
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
n as resource,
|
|
39
|
+
p as resourcePattern,
|
|
36
40
|
u as sendToWorker,
|
|
37
41
|
m as setOfflineSimulation,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
c as setQueryInvalidator,
|
|
43
|
+
l as setQueueStorage,
|
|
44
|
+
w as subscribeReplayOnReconnect,
|
|
45
|
+
a as triggerSwUpdate,
|
|
46
|
+
j as useEidos,
|
|
47
|
+
z as useEidosAction,
|
|
48
|
+
F as useEidosOnDrain,
|
|
49
|
+
G as useEidosQueue,
|
|
50
|
+
H as useEidosQueueStats,
|
|
51
|
+
J as useEidosReliabilityStats,
|
|
52
|
+
L as useEidosResource,
|
|
53
|
+
M as useEidosResources,
|
|
54
|
+
X as useEidosStatus,
|
|
49
55
|
o as useEidosStore,
|
|
50
|
-
|
|
56
|
+
S as warmCache
|
|
51
57
|
};
|
package/dist/query.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { UseQueryOptions, UseQueryResult, UseMutationOptions, UseMutationResult, QueryClient } from '@tanstack/react-query';
|
|
2
|
-
import { ResourceHandle, AnyResourceHandle, ActionHandle, QueuedResult } from '
|
|
3
|
-
|
|
2
|
+
import { ResourceHandle, AnyResourceHandle, ActionHandle, QueuedResult } from './index.ts';
|
|
4
3
|
/**
|
|
5
4
|
* Register a QueryClient with Eidos.
|
|
6
5
|
*
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ActionQueueItem } from './types';
|
|
2
|
+
export interface QueueStorage {
|
|
3
|
+
add(item: ActionQueueItem): Promise<void>;
|
|
4
|
+
getAll(): Promise<ActionQueueItem[]>;
|
|
5
|
+
getPending(): Promise<ActionQueueItem[]>;
|
|
6
|
+
update(id: string, patch: Partial<ActionQueueItem>): Promise<void>;
|
|
7
|
+
remove(id: string): Promise<void>;
|
|
8
|
+
clear(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/** Override the default IndexedDB queue with a custom storage backend (e.g. AsyncStorage for React Native). */
|
|
11
|
+
export declare function setQueueStorage(s: QueueStorage): void;
|
|
12
|
+
export declare function _getQueueStorage(): QueueStorage | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ActionQueueItem } from './types';
|
|
2
|
+
type QueueSyncMessage = {
|
|
3
|
+
type: 'update';
|
|
4
|
+
id: string;
|
|
5
|
+
update: Partial<ActionQueueItem>;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'batchUpdate';
|
|
8
|
+
updates: Array<{
|
|
9
|
+
id: string;
|
|
10
|
+
update: Partial<ActionQueueItem>;
|
|
11
|
+
}>;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'remove';
|
|
14
|
+
id: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Broadcasts a queue-item status change to other tabs sharing the same
|
|
18
|
+
* IndexedDB queue. The replay-lock holder (see `replayQueue` in action.ts)
|
|
19
|
+
* is the only tab that mutates queue-item status, so non-leader tabs would
|
|
20
|
+
* otherwise show stale status until their own store re-hydrates.
|
|
21
|
+
*
|
|
22
|
+
* No-ops in environments without BroadcastChannel (React Native, old Safari).
|
|
23
|
+
*/
|
|
24
|
+
export declare function broadcastQueueSync(message: QueueSyncMessage): void;
|
|
25
|
+
/**
|
|
26
|
+
* Applies queue-item status updates broadcast by the replay-lock holder to
|
|
27
|
+
* this tab's store. Returns an unsubscribe function.
|
|
28
|
+
*/
|
|
29
|
+
export declare function subscribeQueueSync(): () => void;
|
|
30
|
+
/** Test-only: reset the cached channel so each test gets a fresh instance. */
|
|
31
|
+
export declare function _resetQueueSyncChannel(): void;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { EidosConfig } from '../runtime';
|
|
3
|
+
interface EidosProviderProps extends EidosConfig {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Mount once at the root of your application.
|
|
8
|
+
* Registers the service worker and initialises the Eidos runtime.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* <EidosProvider swPath="/eidos-sw.js">
|
|
12
|
+
* <App />
|
|
13
|
+
* </EidosProvider>
|
|
14
|
+
*/
|
|
15
|
+
export declare function EidosProvider({ children, swPath, autoReplay }: EidosProviderProps): import("react").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { EidosStore } from '../store';
|
|
2
|
+
/** Full Eidos store — prefer the narrower hooks below for performance. */
|
|
3
|
+
export declare function useEidos(): EidosStore;
|
|
4
|
+
/** All registered resources — only re-renders when the resources map changes, not on queue mutations. */
|
|
5
|
+
export declare function useEidosResources(): Record<string, import('..').ResourceEntry>;
|
|
6
|
+
/** Live state for a single registered resource URL. */
|
|
7
|
+
export declare function useEidosResource(url: string): import('..').ResourceEntry;
|
|
8
|
+
/** The current action queue. */
|
|
9
|
+
export declare function useEidosQueue(): import('..').ActionQueueItem[];
|
|
10
|
+
/**
|
|
11
|
+
* Live state for a single queue item by ID. Only re-renders when that specific
|
|
12
|
+
* item changes — cheaper than `useEidosQueue().find(id)` which re-renders on
|
|
13
|
+
* any queue mutation.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useEidosAction(id: string): import('..').ActionQueueItem | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Online + SW status — cheap subscription, safe to use in header components.
|
|
18
|
+
* Three separate primitive selectors so each only triggers a re-render when
|
|
19
|
+
* its own value changes (no object-reference churn from a combined selector).
|
|
20
|
+
*/
|
|
21
|
+
export declare function useEidosStatus(): {
|
|
22
|
+
isOnline: boolean;
|
|
23
|
+
swStatus: "idle" | "error" | "registering" | "active" | "unsupported";
|
|
24
|
+
swError: string | undefined;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Queue counts — single subscription, single loop. Re-renders only when a
|
|
28
|
+
* count changes, not on every queue mutation. Use for badges and status bars
|
|
29
|
+
* instead of `useEidosQueue()` when you only need numbers, not full items.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useEidosQueueStats(): {
|
|
32
|
+
pending: number;
|
|
33
|
+
failed: number;
|
|
34
|
+
replaying: number;
|
|
35
|
+
total: number;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Calls `callback` once each time the action queue drains from non-empty → 0.
|
|
39
|
+
* Stable callback reference not required — always calls the latest version.
|
|
40
|
+
* Use for "all offline actions synced!" toasts.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* useEidosOnDrain(() => toast.success('All offline actions synced!'))
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* Cumulative, session-scoped `neverLose` queue outcome counters — opt-in
|
|
47
|
+
* reliability telemetry for dashboards/devtools. Re-renders only when a
|
|
48
|
+
* counter changes.
|
|
49
|
+
*/
|
|
50
|
+
export declare function useEidosReliabilityStats(): import('..').ReliabilityStats;
|
|
51
|
+
export declare function useEidosOnDrain(callback: () => void): void;
|
package/dist/react/hooks.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import { useEidosStore as o } from "../store.js";
|
|
2
1
|
import { countQueueByStatus as l } from "../types.js";
|
|
3
|
-
import {
|
|
2
|
+
import { useEidosStore as r } from "../store.js";
|
|
3
|
+
import { onQueueDrain as E } from "../stores.js";
|
|
4
|
+
import { useEffect as s, useRef as p, useSyncExternalStore as S } from "react";
|
|
4
5
|
function u(e) {
|
|
5
6
|
const t = e ?? ((n) => n);
|
|
6
|
-
return
|
|
7
|
+
return S(r.subscribe, () => t(r.getState()));
|
|
7
8
|
}
|
|
8
|
-
function
|
|
9
|
+
function b() {
|
|
9
10
|
return u();
|
|
10
11
|
}
|
|
11
|
-
function
|
|
12
|
+
function w() {
|
|
12
13
|
return u((e) => e.resources);
|
|
13
14
|
}
|
|
14
|
-
function
|
|
15
|
+
function Q(e) {
|
|
15
16
|
return u((t) => t.resources[e]);
|
|
16
17
|
}
|
|
17
|
-
function
|
|
18
|
+
function $() {
|
|
18
19
|
return u((e) => e.queue);
|
|
19
20
|
}
|
|
20
|
-
function
|
|
21
|
+
function q(e) {
|
|
21
22
|
return u((t) => t.queue.find((n) => n.id === e));
|
|
22
23
|
}
|
|
23
24
|
function O() {
|
|
@@ -27,34 +28,36 @@ function O() {
|
|
|
27
28
|
swError: u((e) => e.swError)
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
function
|
|
31
|
-
const [e, t, n,
|
|
32
|
-
const { pending:
|
|
33
|
-
return `${f},${a},${d}
|
|
31
|
+
function x() {
|
|
32
|
+
const [e, t, n, i] = u((o) => {
|
|
33
|
+
const { pending: c, failed: f, replaying: a, total: d } = l(o.queue);
|
|
34
|
+
return `${c},${f},${a},${d}`;
|
|
34
35
|
}).split(",");
|
|
35
36
|
return {
|
|
36
37
|
pending: +e,
|
|
37
38
|
failed: +t,
|
|
38
39
|
replaying: +n,
|
|
39
|
-
total: +
|
|
40
|
+
total: +i
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
function D() {
|
|
44
|
+
return u((e) => e.reliability);
|
|
45
|
+
}
|
|
46
|
+
function A(e) {
|
|
47
|
+
const t = p(e);
|
|
48
|
+
s(() => {
|
|
49
|
+
t.current = e;
|
|
50
|
+
}), s(() => E(() => t.current()), []);
|
|
49
51
|
}
|
|
50
52
|
export {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
b as useEidos,
|
|
54
|
+
q as useEidosAction,
|
|
55
|
+
A as useEidosOnDrain,
|
|
56
|
+
$ as useEidosQueue,
|
|
57
|
+
x as useEidosQueueStats,
|
|
58
|
+
D as useEidosReliabilityStats,
|
|
59
|
+
Q as useEidosResource,
|
|
60
|
+
w as useEidosResources,
|
|
58
61
|
O as useEidosStatus
|
|
59
62
|
};
|
|
60
63
|
|
package/dist/react/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","names":[],"sources":["../../src/react/hooks.ts"],"sourcesContent":["import { useEffect, useRef, useSyncExternalStore } from 'react';\nimport { useEidosStore } from '../store';\nimport type { EidosStore } from '../store';\nimport { countQueueByStatus } from '../types';\n\nfunction useStore(): EidosStore;\nfunction useStore<T>(selector: (state: EidosStore) => T): T;\nfunction useStore<T = EidosStore>(selector?: (state: EidosStore) => T): T {\n const fn = selector ?? ((s: EidosStore) => s as unknown as T);\n return useSyncExternalStore(useEidosStore.subscribe, () => fn(useEidosStore.getState()));\n}\n\n/** Full Eidos store — prefer the narrower hooks below for performance. */\nexport function useEidos() {\n return useStore();\n}\n\n/** All registered resources — only re-renders when the resources map changes, not on queue mutations. */\nexport function useEidosResources() {\n return useStore((s) => s.resources);\n}\n\n/** Live state for a single registered resource URL. */\nexport function useEidosResource(url: string) {\n return useStore((s) => s.resources[url]);\n}\n\n/** The current action queue. */\nexport function useEidosQueue() {\n return useStore((s) => s.queue);\n}\n\n/**\n * Live state for a single queue item by ID. Only re-renders when that specific\n * item changes — cheaper than `useEidosQueue().find(id)` which re-renders on\n * any queue mutation.\n */\nexport function useEidosAction(id: string) {\n return useStore((s) => s.queue.find((item) => item.id === id));\n}\n\n/**\n * Online + SW status — cheap subscription, safe to use in header components.\n * Three separate primitive selectors so each only triggers a re-render when\n * its own value changes (no object-reference churn from a combined selector).\n */\nexport function useEidosStatus() {\n const isOnline = useStore((s) => s.isOnline);\n const swStatus = useStore((s) => s.swStatus);\n const swError = useStore((s) => s.swError);\n return { isOnline, swStatus, swError };\n}\n\n/**\n * Queue counts — single subscription, single loop. Re-renders only when a\n * count changes, not on every queue mutation. Use for badges and status bars\n * instead of `useEidosQueue()` when you only need numbers, not full items.\n */\nexport function useEidosQueueStats() {\n // Encode as a comma-separated string so useSyncExternalStore's Object.is\n // comparison bails out correctly when counts haven't changed. One loop,\n // one subscription — cheaper than four separate filter() passes.\n const encoded = useStore((s) => {\n const { pending, failed, replaying, total } = countQueueByStatus(s.queue);\n return `${pending},${failed},${replaying},${total}`;\n });\n const [p, f, r, t] = encoded.split(',');\n return { pending: +p, failed: +f, replaying: +r, total: +t };\n}\n\n/**\n * Calls `callback` once each time the action queue drains from non-empty → 0.\n * Stable callback reference not required — always calls the latest version.\n * Use for \"all offline actions synced!\" toasts.\n *\n * @example\n * useEidosOnDrain(() => toast.success('All offline actions synced!'))\n */\nexport function
|
|
1
|
+
{"version":3,"file":"hooks.js","names":[],"sources":["../../src/react/hooks.ts"],"sourcesContent":["import { useEffect, useRef, useSyncExternalStore } from 'react';\nimport { useEidosStore } from '../store';\nimport type { EidosStore } from '../store';\nimport { countQueueByStatus } from '../types';\nimport { onQueueDrain } from '../stores';\n\nfunction useStore(): EidosStore;\nfunction useStore<T>(selector: (state: EidosStore) => T): T;\nfunction useStore<T = EidosStore>(selector?: (state: EidosStore) => T): T {\n const fn = selector ?? ((s: EidosStore) => s as unknown as T);\n return useSyncExternalStore(useEidosStore.subscribe, () => fn(useEidosStore.getState()));\n}\n\n/** Full Eidos store — prefer the narrower hooks below for performance. */\nexport function useEidos() {\n return useStore();\n}\n\n/** All registered resources — only re-renders when the resources map changes, not on queue mutations. */\nexport function useEidosResources() {\n return useStore((s) => s.resources);\n}\n\n/** Live state for a single registered resource URL. */\nexport function useEidosResource(url: string) {\n return useStore((s) => s.resources[url]);\n}\n\n/** The current action queue. */\nexport function useEidosQueue() {\n return useStore((s) => s.queue);\n}\n\n/**\n * Live state for a single queue item by ID. Only re-renders when that specific\n * item changes — cheaper than `useEidosQueue().find(id)` which re-renders on\n * any queue mutation.\n */\nexport function useEidosAction(id: string) {\n return useStore((s) => s.queue.find((item) => item.id === id));\n}\n\n/**\n * Online + SW status — cheap subscription, safe to use in header components.\n * Three separate primitive selectors so each only triggers a re-render when\n * its own value changes (no object-reference churn from a combined selector).\n */\nexport function useEidosStatus() {\n const isOnline = useStore((s) => s.isOnline);\n const swStatus = useStore((s) => s.swStatus);\n const swError = useStore((s) => s.swError);\n return { isOnline, swStatus, swError };\n}\n\n/**\n * Queue counts — single subscription, single loop. Re-renders only when a\n * count changes, not on every queue mutation. Use for badges and status bars\n * instead of `useEidosQueue()` when you only need numbers, not full items.\n */\nexport function useEidosQueueStats() {\n // Encode as a comma-separated string so useSyncExternalStore's Object.is\n // comparison bails out correctly when counts haven't changed. One loop,\n // one subscription — cheaper than four separate filter() passes.\n const encoded = useStore((s) => {\n const { pending, failed, replaying, total } = countQueueByStatus(s.queue);\n return `${pending},${failed},${replaying},${total}`;\n });\n const [p, f, r, t] = encoded.split(',');\n return { pending: +p, failed: +f, replaying: +r, total: +t };\n}\n\n/**\n * Calls `callback` once each time the action queue drains from non-empty → 0.\n * Stable callback reference not required — always calls the latest version.\n * Use for \"all offline actions synced!\" toasts.\n *\n * @example\n * useEidosOnDrain(() => toast.success('All offline actions synced!'))\n */\n/**\n * Cumulative, session-scoped `neverLose` queue outcome counters — opt-in\n * reliability telemetry for dashboards/devtools. Re-renders only when a\n * counter changes.\n */\nexport function useEidosReliabilityStats() {\n return useStore((s) => s.reliability);\n}\n\nexport function useEidosOnDrain(callback: () => void) {\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n });\n\n useEffect(() => onQueueDrain(() => callbackRef.current()), []);\n}\n"],"mappings":";;;;AAQA,SAAS,EAAyB,GAAwC;AACxE,QAAM,IAAK,MAAA,CAAc,MAAkB;AAC3C,SAAO,EAAqB,EAAc,WAAA,MAAiB,EAAG,EAAc,SAAS,CAAC,CAAC;AACzF;AAGA,SAAgB,IAAW;AACzB,SAAO,EAAS;AAClB;AAGA,SAAgB,IAAoB;AAClC,SAAO,EAAA,CAAU,MAAM,EAAE,SAAS;AACpC;AAGA,SAAgB,EAAiB,GAAa;AAC5C,SAAO,EAAA,CAAU,MAAM,EAAE,UAAU,CAAA,CAAI;AACzC;AAGA,SAAgB,IAAgB;AAC9B,SAAO,EAAA,CAAU,MAAM,EAAE,KAAK;AAChC;AAOA,SAAgB,EAAe,GAAY;AACzC,SAAO,EAAA,CAAU,MAAM,EAAE,MAAM,KAAA,CAAM,MAAS,EAAK,OAAO,CAAE,CAAC;AAC/D;AAOA,SAAgB,IAAiB;AAI/B,SAAO;AAAA,IAAE,UAHQ,EAAA,CAAU,MAAM,EAAE,QAG1B;AAAA,IAAU,UAFF,EAAA,CAAU,MAAM,EAAE,QAEhB;AAAA,IAAU,SADb,EAAA,CAAU,MAAM,EAAE,OACL;AAAA,EAAQ;AACvC;AAOA,SAAgB,IAAqB;AAQnC,QAAM,CAAC,GAAG,GAAG,GAAG,CAAA,IAJA,EAAA,CAAU,MAAM;AAC9B,UAAM,EAAE,SAAA,GAAS,QAAA,GAAQ,WAAA,GAAW,OAAA,EAAA,IAAU,EAAmB,EAAE,KAAK;AACxE,WAAO,GAAG,CAAA,IAAW,CAAA,IAAU,CAAA,IAAa,CAAA;AAAA,EAC9C,CACqB,EAAQ,MAAM,GAAG;AACtC,SAAO;AAAA,IAAE,SAAS,CAAC;AAAA,IAAG,QAAQ,CAAC;AAAA,IAAG,WAAW,CAAC;AAAA,IAAG,OAAO,CAAC;AAAA,EAAE;AAC7D;AAeA,SAAgB,IAA2B;AACzC,SAAO,EAAA,CAAU,MAAM,EAAE,WAAW;AACtC;AAEA,SAAgB,EAAgB,GAAsB;AACpD,QAAM,IAAc,EAAO,CAAQ;AAEnC,EAAA,EAAA,MAAgB;AACd,IAAA,EAAY,UAAU;AAAA,EACxB,CAAC,GAED,EAAA,MAAgB,EAAA,MAAmB,EAAY,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC/D"}
|
package/dist/replay.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribe to online/offline transitions and trigger replayQueue() on
|
|
3
|
+
* reconnect, plus replay any pending items left over from a previous session.
|
|
4
|
+
*
|
|
5
|
+
* Shared by the web (runtime.ts) and React Native (runtime-rn.ts) init paths.
|
|
6
|
+
*
|
|
7
|
+
* WHY subscribe to the store instead of window.addEventListener('online'):
|
|
8
|
+
* setOfflineSimulation() updates the store directly but never fires a real
|
|
9
|
+
* browser `online` event. Watching the store catches both:
|
|
10
|
+
* • Real network reconnects (sw-bridge updates store on window.online)
|
|
11
|
+
* • Simulation toggled off (setOfflineSimulation(false) → store.setOnline(true))
|
|
12
|
+
*
|
|
13
|
+
* Returns an unsubscribe function.
|
|
14
|
+
*/
|
|
15
|
+
export declare function subscribeReplayOnReconnect(): () => void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ResourceConfig, ResourceHandle, PatternResourceHandle, WarmCacheResult } from './types';
|
|
2
|
+
type QueryInvalidator = (queryKey: [string, string]) => void;
|
|
3
|
+
/** @internal Called by @sweidos/eidos/query. */
|
|
4
|
+
export declare function setQueryInvalidator(fn: QueryInvalidator): void;
|
|
5
|
+
/**
|
|
6
|
+
* Registers a concrete-URL resource. For URL patterns (`/api/products/*`,
|
|
7
|
+
* `/api/users/:id`, `**`), use `resourcePattern()` instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resource<T = unknown>(url: string, config: ResourceConfig): ResourceHandle<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Registers a URL pattern (`/api/products/*`, `/api/users/:id`, `**`). The SW
|
|
12
|
+
* intercepts all matching requests automatically — there is no single URL to
|
|
13
|
+
* fetch/cache directly, so the returned handle only supports cache management
|
|
14
|
+
* (`invalidate`/`unregister`). For a fetchable resource, use `resource()`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resourcePattern(url: string, config: ResourceConfig): PatternResourceHandle;
|
|
17
|
+
/**
|
|
18
|
+
* Bulk-prefetch an array of resource handles concurrently, warming the cache
|
|
19
|
+
* for each one. Useful on login / app init when you know which resources the
|
|
20
|
+
* user will need offline.
|
|
21
|
+
*
|
|
22
|
+
* Pattern handles (containing `*`, `**`, or `:param`) are silently skipped —
|
|
23
|
+
* they match multiple URLs so there is no single URL to prefetch.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* import { warmCache } from '@sweidos/eidos'
|
|
27
|
+
*
|
|
28
|
+
* // In EidosProvider's onReady, or after login:
|
|
29
|
+
* const { warmed, failed } = await warmCache([products, userProfile, settings])
|
|
30
|
+
*/
|
|
31
|
+
export declare function warmCache(handles: ResourceHandle[]): Promise<WarmCacheResult>;
|
|
32
|
+
export {};
|