@sweidos/eidos 1.0.34 → 1.2.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 +171 -89
- package/dist/action.js +197 -91
- package/dist/async-storage-adapter.js +15 -12
- package/dist/cli.js +102 -0
- package/dist/devtools.js +1009 -551
- package/dist/eidos-sw.js +280 -188
- package/dist/eidos.cjs +15 -0
- package/dist/idb.js +59 -56
- package/dist/index.d.ts +135 -18
- package/dist/index.js +46 -42
- package/dist/nextjs.js +1 -10
- package/dist/push.cjs +120 -0
- package/dist/push.d.ts +28 -0
- package/dist/push.js +113 -0
- package/dist/query.cjs +131 -0
- package/dist/query.js +121 -41
- package/dist/queue-storage.js +5 -4
- package/dist/react/Devtools.d.ts +1 -1
- package/dist/react/Provider.js +11 -7
- package/dist/react/hooks.js +48 -38
- package/dist/react-native.js +47 -53
- package/dist/replay.js +15 -0
- package/dist/resource.js +77 -79
- package/dist/runtime.js +39 -28
- package/dist/store-slices.js +43 -0
- package/dist/store.js +32 -49
- package/dist/stores.js +25 -22
- package/dist/sveltekit.js +22 -6
- package/dist/sw-bridge.js +64 -49
- package/dist/testing.cjs +165 -0
- package/dist/testing.js +140 -70
- package/dist/version.js +4 -3
- package/dist/vite.cjs +48 -0
- package/dist/vite.js +45 -29
- package/package.json +57 -28
- package/dist/action.js.map +0 -1
- package/dist/async-storage-adapter.js.map +0 -1
- package/dist/eidos.cjs.js +0 -14
- package/dist/eidos.cjs.js.map +0 -1
- package/dist/idb.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/query.cjs.js +0 -48
- package/dist/queue-storage.js.map +0 -1
- package/dist/react/Provider.js.map +0 -1
- package/dist/react/hooks.js.map +0 -1
- package/dist/resource.js.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/store.js.map +0 -1
- package/dist/stores.js.map +0 -1
- package/dist/sw-bridge.js.map +0 -1
- package/dist/testing.cjs.js +0 -86
- package/dist/version.js.map +0 -1
- package/dist/vite.cjs.js +0 -31
package/dist/push.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { getSwRegistration, registerPushCallbacks, sendToWorker } from "@sweidos/eidos";
|
|
2
|
+
//#region src/push.ts
|
|
3
|
+
/**
|
|
4
|
+
* @sweidos/eidos/push
|
|
5
|
+
*
|
|
6
|
+
* Web Push integration. Framework-agnostic: register click/expiry handlers
|
|
7
|
+
* once at app init (any tab), and trigger subscription from a user gesture.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { registerPushHandlers, subscribeToPush } from '@sweidos/eidos/push'
|
|
12
|
+
*
|
|
13
|
+
* // App init — every tab, no permission prompt
|
|
14
|
+
* registerPushHandlers({
|
|
15
|
+
* onNotificationClick: (data) => router.push(data.url),
|
|
16
|
+
* onSubscriptionExpired: (sub) => fetch('/api/push-subscribe', { method: 'POST', body: JSON.stringify(sub) }),
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* // User gesture (button click)
|
|
20
|
+
* const result = await subscribeToPush({
|
|
21
|
+
* vapidPublicKey: import.meta.env.VITE_EIDOS_VAPID_PUBLIC_KEY,
|
|
22
|
+
* onSubscribe: (sub) => fetch('/api/push-subscribe', { method: 'POST', body: JSON.stringify(sub) }),
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/** Why push is unavailable on this device, or null if it's supported. */
|
|
27
|
+
function getPushUnsupportedReason() {
|
|
28
|
+
if (typeof window === "undefined") return "no-push-api";
|
|
29
|
+
if (/iPhone|iPad|iPod/.test(navigator.userAgent) && !navigator.standalone) return "ios-not-installed";
|
|
30
|
+
if (!("serviceWorker" in navigator) || !("PushManager" in window) || !("Notification" in window)) return "no-push-api";
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
function isPushSupported() {
|
|
34
|
+
return getPushUnsupportedReason() === null;
|
|
35
|
+
}
|
|
36
|
+
function getPushPermissionState() {
|
|
37
|
+
if (!isPushSupported()) return "unsupported";
|
|
38
|
+
return Notification.permission;
|
|
39
|
+
}
|
|
40
|
+
function registerPushHandlers(handlers) {
|
|
41
|
+
registerPushCallbacks(handlers);
|
|
42
|
+
}
|
|
43
|
+
async function subscribeToPush(config) {
|
|
44
|
+
if (!isPushSupported()) return { status: "unsupported" };
|
|
45
|
+
let permission;
|
|
46
|
+
try {
|
|
47
|
+
permission = await Notification.requestPermission();
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
status: "error",
|
|
51
|
+
error
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (permission !== "granted") return { status: "denied" };
|
|
55
|
+
const registration = getSwRegistration();
|
|
56
|
+
if (!registration) return { status: "sw-not-ready" };
|
|
57
|
+
try {
|
|
58
|
+
const applicationServerKey = urlBase64ToUint8Array(config.vapidPublicKey);
|
|
59
|
+
let subscription = await registration.pushManager.getSubscription();
|
|
60
|
+
if (subscription && !subscriptionKeyMatches(subscription, config.vapidPublicKey)) {
|
|
61
|
+
await subscription.unsubscribe();
|
|
62
|
+
subscription = null;
|
|
63
|
+
}
|
|
64
|
+
if (!subscription) subscription = await registration.pushManager.subscribe({
|
|
65
|
+
userVisibleOnly: true,
|
|
66
|
+
applicationServerKey
|
|
67
|
+
});
|
|
68
|
+
sendToWorker({
|
|
69
|
+
type: "EIDOS_CACHE_VAPID_KEY",
|
|
70
|
+
key: config.vapidPublicKey
|
|
71
|
+
});
|
|
72
|
+
const json = subscription.toJSON();
|
|
73
|
+
config.onSubscribe?.(json);
|
|
74
|
+
return {
|
|
75
|
+
status: "subscribed",
|
|
76
|
+
subscription: json
|
|
77
|
+
};
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return {
|
|
80
|
+
status: "error",
|
|
81
|
+
error
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function unsubscribeFromPush() {
|
|
86
|
+
const registration = getSwRegistration();
|
|
87
|
+
if (!registration) return;
|
|
88
|
+
await (await registration.pushManager.getSubscription())?.unsubscribe();
|
|
89
|
+
}
|
|
90
|
+
async function getCurrentPushSubscription() {
|
|
91
|
+
const registration = getSwRegistration();
|
|
92
|
+
if (!registration) return null;
|
|
93
|
+
const subscription = await registration.pushManager.getSubscription();
|
|
94
|
+
return subscription ? subscription.toJSON() : null;
|
|
95
|
+
}
|
|
96
|
+
function urlBase64ToUint8Array(base64Url) {
|
|
97
|
+
const base64 = (base64Url + "=".repeat((4 - base64Url.length % 4) % 4)).replace(/-/g, "+").replace(/_/g, "/");
|
|
98
|
+
const raw = atob(base64);
|
|
99
|
+
return Uint8Array.from(raw, (c) => c.charCodeAt(0));
|
|
100
|
+
}
|
|
101
|
+
function uint8ArrayToUrlBase64(bytes) {
|
|
102
|
+
let binary = "";
|
|
103
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
104
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
105
|
+
}
|
|
106
|
+
/** Compares an existing subscription's key against the configured VAPID public key. */
|
|
107
|
+
function subscriptionKeyMatches(subscription, vapidPublicKey) {
|
|
108
|
+
const key = subscription.options.applicationServerKey;
|
|
109
|
+
if (!key) return false;
|
|
110
|
+
return uint8ArrayToUrlBase64(new Uint8Array(key)) === uint8ArrayToUrlBase64(urlBase64ToUint8Array(vapidPublicKey));
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { getCurrentPushSubscription, getPushPermissionState, getPushUnsupportedReason, isPushSupported, registerPushHandlers, subscribeToPush, unsubscribeFromPush };
|
package/dist/query.cjs
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _tanstack_react_query = require("@tanstack/react-query");
|
|
3
|
+
let _sweidos_eidos = require("@sweidos/eidos");
|
|
4
|
+
//#region src/query.ts
|
|
5
|
+
/**
|
|
6
|
+
* @sweidos/eidos/query
|
|
7
|
+
*
|
|
8
|
+
* TanStack Query (React Query) integration for Eidos.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* // Register once (e.g. alongside new QueryClient())
|
|
13
|
+
* import { withEidosQueryClient } from '@sweidos/eidos/query'
|
|
14
|
+
* withEidosQueryClient(queryClient)
|
|
15
|
+
*
|
|
16
|
+
* // In components
|
|
17
|
+
* import { useEidosQuery, useEidosMutation } from '@sweidos/eidos/query'
|
|
18
|
+
*
|
|
19
|
+
* const { data, isPending } = useEidosQuery(products)
|
|
20
|
+
*
|
|
21
|
+
* const mutation = useEidosMutation(createOrder, {
|
|
22
|
+
* invalidates: [products],
|
|
23
|
+
* })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
var _globalClient = null;
|
|
27
|
+
/**
|
|
28
|
+
* Register a QueryClient with Eidos.
|
|
29
|
+
*
|
|
30
|
+
* Once called, `handle.invalidate()` will also call
|
|
31
|
+
* `queryClient.invalidateQueries({ queryKey: ['eidos', url] })`, keeping
|
|
32
|
+
* TanStack Query's cache in sync with Eidos's Cache Storage.
|
|
33
|
+
*
|
|
34
|
+
* Call this once, before rendering — e.g. alongside `new QueryClient()`.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const queryClient = new QueryClient()
|
|
39
|
+
* withEidosQueryClient(queryClient)
|
|
40
|
+
*
|
|
41
|
+
* // Wrap your app as usual
|
|
42
|
+
* <QueryClientProvider client={queryClient}>
|
|
43
|
+
* <App />
|
|
44
|
+
* </QueryClientProvider>
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
function withEidosQueryClient(client) {
|
|
48
|
+
_globalClient = client;
|
|
49
|
+
(0, _sweidos_eidos.setQueryInvalidator)((queryKey) => {
|
|
50
|
+
client.invalidateQueries({ queryKey });
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Wraps `useQuery` with Eidos-smart defaults.
|
|
55
|
+
*
|
|
56
|
+
* Key differences from plain `useQuery`:
|
|
57
|
+
* - `networkMode: 'always'` — Eidos owns offline logic; queries run even when
|
|
58
|
+
* `navigator.onLine` is false (the SW cache or IndexedDB serves the data).
|
|
59
|
+
* - `retry: false` — Eidos handles retries at the SW / replay layer; TQ
|
|
60
|
+
* retrying on top would double-fire and fight Eidos's backoff.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* const products = resource('/api/products', { offline: true })
|
|
65
|
+
*
|
|
66
|
+
* // Automatically typed as UseQueryResult<Product[]>
|
|
67
|
+
* const { data, isPending, isError } = useEidosQuery<Product[]>(products)
|
|
68
|
+
*
|
|
69
|
+
* // Override any TQ option
|
|
70
|
+
* const { data } = useEidosQuery(products, { staleTime: 30_000 })
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
function useEidosQuery(handle, options) {
|
|
74
|
+
return (0, _tanstack_react_query.useQuery)({
|
|
75
|
+
networkMode: "always",
|
|
76
|
+
retry: false,
|
|
77
|
+
...options,
|
|
78
|
+
...handle.query()
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Wraps `useMutation` for a single-argument Eidos action handle.
|
|
83
|
+
*
|
|
84
|
+
* Key differences from plain `useMutation`:
|
|
85
|
+
* - `networkMode: 'always'` — action executes (or queues) even when offline.
|
|
86
|
+
* - `invalidates` — shorthand to clear resource caches on success. Triggers
|
|
87
|
+
* both Eidos Cache Storage and TanStack Query invalidation (requires
|
|
88
|
+
* `withEidosQueryClient` for the TQ half).
|
|
89
|
+
* - Return type is `TData | QueuedResult`. Narrow with `'queued' in data` to
|
|
90
|
+
* detect the offline-queued case.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const mutation = useEidosMutation(createOrder, {
|
|
95
|
+
* invalidates: [products],
|
|
96
|
+
* onSuccess(data) {
|
|
97
|
+
* if ('queued' in data) toast('Saved offline — will sync when back online')
|
|
98
|
+
* else toast(`Order #${data.id} created!`)
|
|
99
|
+
* },
|
|
100
|
+
* })
|
|
101
|
+
*
|
|
102
|
+
* // Trigger
|
|
103
|
+
* mutation.mutate({ productId: 1, qty: 2 })
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
function useEidosMutation(handle, options) {
|
|
107
|
+
let contextClient = null;
|
|
108
|
+
try {
|
|
109
|
+
contextClient = (0, _tanstack_react_query.useQueryClient)();
|
|
110
|
+
} catch {}
|
|
111
|
+
const { invalidates, onSuccess, ...rest } = options ?? {};
|
|
112
|
+
return (0, _tanstack_react_query.useMutation)({
|
|
113
|
+
networkMode: "always",
|
|
114
|
+
...rest,
|
|
115
|
+
mutationFn: (arg) => handle(arg),
|
|
116
|
+
onSuccess: async (...args) => {
|
|
117
|
+
const [data] = args;
|
|
118
|
+
if (invalidates?.length) {
|
|
119
|
+
await Promise.all(invalidates.map((h) => h.invalidate()));
|
|
120
|
+
if (!_globalClient && contextClient) invalidates.forEach((h) => {
|
|
121
|
+
contextClient.invalidateQueries({ queryKey: h.query().queryKey });
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (onSuccess) await onSuccess(...args);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
exports.useEidosMutation = useEidosMutation;
|
|
130
|
+
exports.useEidosQuery = useEidosQuery;
|
|
131
|
+
exports.withEidosQueryClient = withEidosQueryClient;
|
package/dist/query.js
CHANGED
|
@@ -1,48 +1,128 @@
|
|
|
1
|
-
import { useQuery, useQueryClient
|
|
1
|
+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
2
2
|
import { setQueryInvalidator } from "@sweidos/eidos";
|
|
3
|
-
|
|
3
|
+
//#region src/query.ts
|
|
4
|
+
/**
|
|
5
|
+
* @sweidos/eidos/query
|
|
6
|
+
*
|
|
7
|
+
* TanStack Query (React Query) integration for Eidos.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* // Register once (e.g. alongside new QueryClient())
|
|
12
|
+
* import { withEidosQueryClient } from '@sweidos/eidos/query'
|
|
13
|
+
* withEidosQueryClient(queryClient)
|
|
14
|
+
*
|
|
15
|
+
* // In components
|
|
16
|
+
* import { useEidosQuery, useEidosMutation } from '@sweidos/eidos/query'
|
|
17
|
+
*
|
|
18
|
+
* const { data, isPending } = useEidosQuery(products)
|
|
19
|
+
*
|
|
20
|
+
* const mutation = useEidosMutation(createOrder, {
|
|
21
|
+
* invalidates: [products],
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
var _globalClient = null;
|
|
26
|
+
/**
|
|
27
|
+
* Register a QueryClient with Eidos.
|
|
28
|
+
*
|
|
29
|
+
* Once called, `handle.invalidate()` will also call
|
|
30
|
+
* `queryClient.invalidateQueries({ queryKey: ['eidos', url] })`, keeping
|
|
31
|
+
* TanStack Query's cache in sync with Eidos's Cache Storage.
|
|
32
|
+
*
|
|
33
|
+
* Call this once, before rendering — e.g. alongside `new QueryClient()`.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const queryClient = new QueryClient()
|
|
38
|
+
* withEidosQueryClient(queryClient)
|
|
39
|
+
*
|
|
40
|
+
* // Wrap your app as usual
|
|
41
|
+
* <QueryClientProvider client={queryClient}>
|
|
42
|
+
* <App />
|
|
43
|
+
* </QueryClientProvider>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
4
46
|
function withEidosQueryClient(client) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
47
|
+
_globalClient = client;
|
|
48
|
+
setQueryInvalidator((queryKey) => {
|
|
49
|
+
client.invalidateQueries({ queryKey });
|
|
50
|
+
});
|
|
9
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Wraps `useQuery` with Eidos-smart defaults.
|
|
54
|
+
*
|
|
55
|
+
* Key differences from plain `useQuery`:
|
|
56
|
+
* - `networkMode: 'always'` — Eidos owns offline logic; queries run even when
|
|
57
|
+
* `navigator.onLine` is false (the SW cache or IndexedDB serves the data).
|
|
58
|
+
* - `retry: false` — Eidos handles retries at the SW / replay layer; TQ
|
|
59
|
+
* retrying on top would double-fire and fight Eidos's backoff.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const products = resource('/api/products', { offline: true })
|
|
64
|
+
*
|
|
65
|
+
* // Automatically typed as UseQueryResult<Product[]>
|
|
66
|
+
* const { data, isPending, isError } = useEidosQuery<Product[]>(products)
|
|
67
|
+
*
|
|
68
|
+
* // Override any TQ option
|
|
69
|
+
* const { data } = useEidosQuery(products, { staleTime: 30_000 })
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
10
72
|
function useEidosQuery(handle, options) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
73
|
+
return useQuery({
|
|
74
|
+
networkMode: "always",
|
|
75
|
+
retry: false,
|
|
76
|
+
...options,
|
|
77
|
+
...handle.query()
|
|
78
|
+
});
|
|
17
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Wraps `useMutation` for a single-argument Eidos action handle.
|
|
82
|
+
*
|
|
83
|
+
* Key differences from plain `useMutation`:
|
|
84
|
+
* - `networkMode: 'always'` — action executes (or queues) even when offline.
|
|
85
|
+
* - `invalidates` — shorthand to clear resource caches on success. Triggers
|
|
86
|
+
* both Eidos Cache Storage and TanStack Query invalidation (requires
|
|
87
|
+
* `withEidosQueryClient` for the TQ half).
|
|
88
|
+
* - Return type is `TData | QueuedResult`. Narrow with `'queued' in data` to
|
|
89
|
+
* detect the offline-queued case.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const mutation = useEidosMutation(createOrder, {
|
|
94
|
+
* invalidates: [products],
|
|
95
|
+
* onSuccess(data) {
|
|
96
|
+
* if ('queued' in data) toast('Saved offline — will sync when back online')
|
|
97
|
+
* else toast(`Order #${data.id} created!`)
|
|
98
|
+
* },
|
|
99
|
+
* })
|
|
100
|
+
*
|
|
101
|
+
* // Trigger
|
|
102
|
+
* mutation.mutate({ productId: 1, qty: 2 })
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
18
105
|
function useEidosMutation(handle, options) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
if (onSuccess) await onSuccess(...args);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
106
|
+
let contextClient = null;
|
|
107
|
+
try {
|
|
108
|
+
contextClient = useQueryClient();
|
|
109
|
+
} catch {}
|
|
110
|
+
const { invalidates, onSuccess, ...rest } = options ?? {};
|
|
111
|
+
return useMutation({
|
|
112
|
+
networkMode: "always",
|
|
113
|
+
...rest,
|
|
114
|
+
mutationFn: (arg) => handle(arg),
|
|
115
|
+
onSuccess: async (...args) => {
|
|
116
|
+
const [data] = args;
|
|
117
|
+
if (invalidates?.length) {
|
|
118
|
+
await Promise.all(invalidates.map((h) => h.invalidate()));
|
|
119
|
+
if (!_globalClient && contextClient) invalidates.forEach((h) => {
|
|
120
|
+
contextClient.invalidateQueries({ queryKey: h.query().queryKey });
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (onSuccess) await onSuccess(...args);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
43
126
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
useEidosQuery,
|
|
47
|
-
withEidosQueryClient
|
|
48
|
-
};
|
|
127
|
+
//#endregion
|
|
128
|
+
export { useEidosMutation, useEidosQuery, withEidosQueryClient };
|
package/dist/queue-storage.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
var e = null;
|
|
2
2
|
function u(t) {
|
|
3
3
|
e = t;
|
|
4
4
|
}
|
|
5
|
-
function
|
|
5
|
+
function r() {
|
|
6
6
|
return e;
|
|
7
7
|
}
|
|
8
8
|
export {
|
|
9
|
-
|
|
9
|
+
r as _getQueueStorage,
|
|
10
10
|
u as setQueueStorage
|
|
11
11
|
};
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=queue-storage.js.map
|
package/dist/react/Devtools.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export interface EidosDevtoolsProps {
|
|
|
4
4
|
/** Start expanded. Default: false. */
|
|
5
5
|
defaultOpen?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare function EidosDevtools({ position, defaultOpen }: EidosDevtoolsProps): import("react").JSX.Element;
|
|
7
|
+
export declare function EidosDevtools({ position, defaultOpen, }: EidosDevtoolsProps): import("react").JSX.Element;
|
package/dist/react/Provider.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useEffect as
|
|
3
|
-
import {
|
|
1
|
+
import { initEidos as t } from "../runtime.js";
|
|
2
|
+
import { useEffect as m } from "react";
|
|
3
|
+
import { Fragment as e, jsx as f } from "react/jsx-runtime";
|
|
4
4
|
function d({ children: r, swPath: o, autoReplay: i }) {
|
|
5
|
-
return
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
return m(() => {
|
|
6
|
+
t({
|
|
7
|
+
swPath: o,
|
|
8
|
+
autoReplay: i
|
|
9
|
+
});
|
|
10
|
+
}, []), /* @__PURE__ */ f(e, { children: r });
|
|
8
11
|
}
|
|
9
12
|
export {
|
|
10
13
|
d as EidosProvider
|
|
11
14
|
};
|
|
12
|
-
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=Provider.js.map
|
package/dist/react/hooks.js
CHANGED
|
@@ -1,51 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
function
|
|
1
|
+
import { useEidosStore as a } from "../store.js";
|
|
2
|
+
import { useEffect as d, useRef as l, useSyncExternalStore as E } from "react";
|
|
3
|
+
function u(e) {
|
|
4
4
|
const t = e ?? ((n) => n);
|
|
5
|
-
return
|
|
5
|
+
return E(a.subscribe, () => t(a.getState()));
|
|
6
|
+
}
|
|
7
|
+
function S() {
|
|
8
|
+
return u();
|
|
6
9
|
}
|
|
7
10
|
function q() {
|
|
8
|
-
return
|
|
11
|
+
return u((e) => e.resources);
|
|
9
12
|
}
|
|
10
|
-
function R() {
|
|
11
|
-
return
|
|
13
|
+
function R(e) {
|
|
14
|
+
return u((t) => t.resources[e]);
|
|
12
15
|
}
|
|
13
|
-
function m(
|
|
14
|
-
return
|
|
16
|
+
function m() {
|
|
17
|
+
return u((e) => e.queue);
|
|
15
18
|
}
|
|
16
|
-
function w() {
|
|
17
|
-
return
|
|
19
|
+
function w(e) {
|
|
20
|
+
return u((t) => t.queue.find((n) => n.id === e));
|
|
18
21
|
}
|
|
19
|
-
function y(
|
|
20
|
-
return
|
|
22
|
+
function y() {
|
|
23
|
+
return {
|
|
24
|
+
isOnline: u((e) => e.isOnline),
|
|
25
|
+
swStatus: u((e) => e.swStatus),
|
|
26
|
+
swError: u((e) => e.swError)
|
|
27
|
+
};
|
|
21
28
|
}
|
|
22
29
|
function $() {
|
|
23
|
-
const e
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
function
|
|
36
|
-
const t =
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
const [e, t, n, r] = u((s) => {
|
|
31
|
+
let o = 0, f = 0, c = 0;
|
|
32
|
+
for (const i of s.queue) i.status === "pending" ? o++ : i.status === "failed" ? f++ : i.status === "replaying" && c++;
|
|
33
|
+
return `${o},${f},${c},${s.queue.length}`;
|
|
34
|
+
}).split(",");
|
|
35
|
+
return {
|
|
36
|
+
pending: +e,
|
|
37
|
+
failed: +t,
|
|
38
|
+
replaying: +n,
|
|
39
|
+
total: +r
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function O(e) {
|
|
43
|
+
const t = u((s) => s.queue.length), n = l(0), r = l(e);
|
|
44
|
+
d(() => {
|
|
45
|
+
r.current = e;
|
|
46
|
+
}), d(() => {
|
|
47
|
+
n.current > 0 && t === 0 && r.current(), n.current = t;
|
|
39
48
|
}, [t]);
|
|
40
49
|
}
|
|
41
50
|
export {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
S as useEidos,
|
|
52
|
+
w as useEidosAction,
|
|
53
|
+
O as useEidosOnDrain,
|
|
54
|
+
m as useEidosQueue,
|
|
55
|
+
$ as useEidosQueueStats,
|
|
56
|
+
R as useEidosResource,
|
|
57
|
+
q as useEidosResources,
|
|
58
|
+
y as useEidosStatus
|
|
50
59
|
};
|
|
51
|
-
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=hooks.js.map
|
package/dist/react-native.js
CHANGED
|
@@ -1,59 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import { AsyncStorageQueueStorage, AsyncStorageQueueStorage as AsyncStorageQueueStorage$1, setQueueStorage, setQueueStorage as setQueueStorage$1, subscribeReplayOnReconnect, useEidosStore } from "@sweidos/eidos";
|
|
3
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/react/ProviderRN.tsx
|
|
5
|
+
/**
|
|
6
|
+
* Connectivity bridge for React Native.
|
|
7
|
+
* Syncs the network state into the Eidos store so `initEidosRN`'s autoReplay
|
|
8
|
+
* subscription fires when the device comes back online.
|
|
9
|
+
*
|
|
10
|
+
* Render this near the root of your app, after calling `initEidosRN()`.
|
|
11
|
+
*/
|
|
5
12
|
function EidosProviderRN({ children, isConnected }) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const prevRef = useRef(void 0);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const online = isConnected !== false;
|
|
16
|
+
if (online !== prevRef.current) {
|
|
17
|
+
prevRef.current = online;
|
|
18
|
+
useEidosStore.getState().setOnline(online);
|
|
19
|
+
}
|
|
20
|
+
}, [isConnected]);
|
|
21
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
15
22
|
}
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/runtime-rn.ts
|
|
25
|
+
var _initialized = false;
|
|
26
|
+
var _unsubscribe = null;
|
|
27
|
+
/**
|
|
28
|
+
* Initialize Eidos for React Native.
|
|
29
|
+
* Call this once at app startup (outside any component) before rendering.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
33
|
+
* await initEidosRN({ storage: AsyncStorage })
|
|
34
|
+
*/
|
|
18
35
|
async function initEidosRN(config) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
} catch {
|
|
30
|
-
}
|
|
31
|
-
if (autoReplay) {
|
|
32
|
-
let prevIsOnline = useEidosStore.getState().isOnline;
|
|
33
|
-
_unsubscribe = useEidosStore.subscribe(() => {
|
|
34
|
-
const { isOnline } = useEidosStore.getState();
|
|
35
|
-
const justCameOnline = isOnline && !prevIsOnline;
|
|
36
|
-
prevIsOnline = isOnline;
|
|
37
|
-
if (justCameOnline) {
|
|
38
|
-
setTimeout(replayQueue, 600);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
const store = useEidosStore.getState();
|
|
42
|
-
const hasPending = store.queue.some((q) => q.status === "pending");
|
|
43
|
-
if (store.isOnline && hasPending) {
|
|
44
|
-
setTimeout(replayQueue, 1200);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
36
|
+
if (_initialized) return;
|
|
37
|
+
_initialized = true;
|
|
38
|
+
const { storage, autoReplay = true } = config;
|
|
39
|
+
const queueStorage = new AsyncStorageQueueStorage$1(storage);
|
|
40
|
+
setQueueStorage$1(queueStorage);
|
|
41
|
+
try {
|
|
42
|
+
const persisted = await queueStorage.getAll();
|
|
43
|
+
if (persisted.length > 0) useEidosStore.getState().hydrateQueue(persisted);
|
|
44
|
+
} catch {}
|
|
45
|
+
if (autoReplay) _unsubscribe = subscribeReplayOnReconnect();
|
|
47
46
|
}
|
|
48
47
|
function _resetEidosRN() {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
_unsubscribe?.();
|
|
49
|
+
_unsubscribe = null;
|
|
50
|
+
_initialized = false;
|
|
52
51
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
EidosProviderRN,
|
|
56
|
-
_resetEidosRN,
|
|
57
|
-
initEidosRN,
|
|
58
|
-
setQueueStorage2 as setQueueStorage
|
|
59
|
-
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { AsyncStorageQueueStorage, EidosProviderRN, _resetEidosRN, initEidosRN, setQueueStorage };
|