@voltro/react-native 0.81.0 → 0.82.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/CHANGELOG.md +1520 -6
- package/THIRD-PARTY-NOTICES.md +115 -1
- package/dist/index.d.ts +239 -112
- package/dist/index.js +217 -135
- package/dist/schema.d.ts +15 -0
- package/dist/schema.js +18 -15
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1,71 +1,8 @@
|
|
|
1
1
|
import { a as e, i as t, n, r, t as i } from "./devices-BjXAU-8I.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
//#region src/
|
|
5
|
-
var
|
|
6
|
-
let t = e.pattern;
|
|
7
|
-
if (t.length === 0 || t[0] !== "/") throw Error(`defineDeepLink: pattern must start with "/" (got "${t}")`);
|
|
8
|
-
return {
|
|
9
|
-
_tag: "VoltroDeepLink",
|
|
10
|
-
pattern: t,
|
|
11
|
-
handler: e.handler
|
|
12
|
-
};
|
|
13
|
-
}, m = (e) => {
|
|
14
|
-
let t = e, n = /^([a-zA-Z][a-zA-Z0-9+.-]*):\/\//.exec(t);
|
|
15
|
-
if (n) {
|
|
16
|
-
let e = t.slice(n[0].length), r = n[1].toLowerCase();
|
|
17
|
-
if (r === "http" || r === "https") {
|
|
18
|
-
let n = e.indexOf("/");
|
|
19
|
-
t = n === -1 ? "/" : e.slice(n);
|
|
20
|
-
} else t = `/${e}`;
|
|
21
|
-
}
|
|
22
|
-
let r = t.search(/[?#]/);
|
|
23
|
-
return r !== -1 && (t = t.slice(0, r)), t.split("/").filter((e) => e.length > 0).map((e) => {
|
|
24
|
-
try {
|
|
25
|
-
return decodeURIComponent(e);
|
|
26
|
-
} catch {
|
|
27
|
-
return e;
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}, h = (e, t) => {
|
|
31
|
-
let n = m(e), r = m(t);
|
|
32
|
-
if (n.length !== r.length) return null;
|
|
33
|
-
let i = {};
|
|
34
|
-
for (let e = 0; e < n.length; e++) {
|
|
35
|
-
let t = n[e], a = r[e];
|
|
36
|
-
if (t.startsWith(":")) {
|
|
37
|
-
let e = t.slice(1);
|
|
38
|
-
if (e.length === 0) return null;
|
|
39
|
-
i[e] = a;
|
|
40
|
-
} else if (t !== "*" && t !== a) return null;
|
|
41
|
-
}
|
|
42
|
-
return i;
|
|
43
|
-
}, g = (e, t) => {
|
|
44
|
-
let n = h(e.pattern, t);
|
|
45
|
-
return n === null ? null : (e.handler(n), n);
|
|
46
|
-
}, _ = (e, t) => {
|
|
47
|
-
let n = e.split("/").map((n) => {
|
|
48
|
-
if (!n.startsWith(":")) return n;
|
|
49
|
-
let r = n.slice(1), i = t[r];
|
|
50
|
-
if (i === void 0) throw Error(`deepLinkHref: pattern "${e}" needs a ":${r}" param`);
|
|
51
|
-
return encodeURIComponent(i);
|
|
52
|
-
}).join("/");
|
|
53
|
-
return n.length === 0 ? "/" : n;
|
|
54
|
-
}, v = (e, t) => {
|
|
55
|
-
for (let n of e) {
|
|
56
|
-
let e = h(n.pattern, t);
|
|
57
|
-
if (e !== null) return {
|
|
58
|
-
descriptor: n,
|
|
59
|
-
params: e
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return null;
|
|
63
|
-
}, y = (e, t) => {
|
|
64
|
-
let n = v(e, t);
|
|
65
|
-
if (n === null) return null;
|
|
66
|
-
let r = n.descriptor.handler;
|
|
67
|
-
return r(n.params), n.params;
|
|
68
|
-
}, b = {
|
|
2
|
+
import { browserOnlineSource as a, browserOnlineSource as o, buildApiRuntime as s, deepLinkHref as c, defineDeepLink as l, definePlatform as u, dispatchDeepLink as d, matchDeepLink as f, matchFirstDeepLink as p, recoveryCoordinatorFor as m, runDeepLink as h, startApiSupervisor as g } from "@voltro/client";
|
|
3
|
+
import { useCallback as _, useEffect as v, useReducer as y, useRef as b, useState as x } from "react";
|
|
4
|
+
//#region src/backgroundSync.ts
|
|
5
|
+
var S = {
|
|
69
6
|
status: "idle",
|
|
70
7
|
isForeground: !0,
|
|
71
8
|
lastSyncAt: void 0,
|
|
@@ -73,7 +10,7 @@ var p = (e) => {
|
|
|
73
10
|
lastError: void 0,
|
|
74
11
|
successCount: 0,
|
|
75
12
|
failureCount: 0
|
|
76
|
-
},
|
|
13
|
+
}, C = (e, t) => {
|
|
77
14
|
switch (t.type) {
|
|
78
15
|
case "foreground": return e.isForeground ? e : {
|
|
79
16
|
...e,
|
|
@@ -104,11 +41,11 @@ var p = (e) => {
|
|
|
104
41
|
failureCount: e.failureCount + 1
|
|
105
42
|
};
|
|
106
43
|
case "reset": return {
|
|
107
|
-
...
|
|
44
|
+
...S,
|
|
108
45
|
isForeground: e.isForeground
|
|
109
46
|
};
|
|
110
47
|
}
|
|
111
|
-
},
|
|
48
|
+
}, w = (e, t, n, r = !1) => !(!n.enabled || e.status === "syncing" || !r && !e.isForeground || !r && n.intervalMs > 0 && e.lastAttemptAt !== void 0 && t - e.lastAttemptAt < n.intervalMs), T = (e, t) => {
|
|
112
49
|
if (typeof document > "u" || typeof window > "u") return () => {};
|
|
113
50
|
let n = () => {
|
|
114
51
|
document.visibilityState === "visible" ? e() : t();
|
|
@@ -116,58 +53,58 @@ var p = (e) => {
|
|
|
116
53
|
return document.addEventListener("visibilitychange", n), window.addEventListener("focus", e), () => {
|
|
117
54
|
document.removeEventListener("visibilitychange", n), window.removeEventListener("focus", e);
|
|
118
55
|
};
|
|
119
|
-
},
|
|
120
|
-
let n = t.intervalMs ??
|
|
121
|
-
|
|
122
|
-
let
|
|
123
|
-
|
|
124
|
-
let
|
|
125
|
-
|
|
56
|
+
}, E = 3e5, D = (e, t = {}) => {
|
|
57
|
+
let n = t.intervalMs ?? E, r = t.syncOnForeground ?? !0, i = t.enabled ?? !0, a = t.now ?? Date.now, o = t.subscribeForeground ?? T, [s, c] = y(C, S), l = b(e);
|
|
58
|
+
l.current = e;
|
|
59
|
+
let u = b(s);
|
|
60
|
+
u.current = s;
|
|
61
|
+
let d = b(!0), f = _((e) => {
|
|
62
|
+
w(u.current, a(), {
|
|
126
63
|
intervalMs: n,
|
|
127
64
|
enabled: i
|
|
128
|
-
}, e) && (
|
|
65
|
+
}, e) && (c({
|
|
129
66
|
type: "syncStarted",
|
|
130
|
-
at:
|
|
131
|
-
}), Promise.resolve().then(() =>
|
|
132
|
-
|
|
67
|
+
at: a()
|
|
68
|
+
}), Promise.resolve().then(() => l.current()).then(() => {
|
|
69
|
+
d.current && c({
|
|
133
70
|
type: "syncSucceeded",
|
|
134
|
-
at:
|
|
71
|
+
at: a()
|
|
135
72
|
});
|
|
136
73
|
}).catch((e) => {
|
|
137
|
-
|
|
74
|
+
d.current && c({
|
|
138
75
|
type: "syncFailed",
|
|
139
|
-
at:
|
|
76
|
+
at: a(),
|
|
140
77
|
error: e instanceof Error ? e.message : String(e)
|
|
141
78
|
});
|
|
142
79
|
}));
|
|
143
80
|
}, [
|
|
144
81
|
i,
|
|
145
82
|
n,
|
|
146
|
-
|
|
83
|
+
a
|
|
147
84
|
]);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}), []),
|
|
151
|
-
|
|
152
|
-
}, () =>
|
|
153
|
-
|
|
85
|
+
v(() => (d.current = !0, () => {
|
|
86
|
+
d.current = !1;
|
|
87
|
+
}), []), v(() => o(() => {
|
|
88
|
+
c({ type: "foreground" }), r && f(!0);
|
|
89
|
+
}, () => c({ type: "background" })), [
|
|
90
|
+
o,
|
|
154
91
|
r,
|
|
155
|
-
|
|
156
|
-
]),
|
|
92
|
+
f
|
|
93
|
+
]), v(() => {
|
|
157
94
|
if (!i || n <= 0) return;
|
|
158
|
-
let e = setInterval(() =>
|
|
95
|
+
let e = setInterval(() => f(!1), n);
|
|
159
96
|
return () => clearInterval(e);
|
|
160
97
|
}, [
|
|
161
98
|
i,
|
|
162
99
|
n,
|
|
163
|
-
|
|
100
|
+
f
|
|
164
101
|
]);
|
|
165
|
-
let
|
|
102
|
+
let p = _(() => f(!0), [f]);
|
|
166
103
|
return {
|
|
167
|
-
...
|
|
168
|
-
sync:
|
|
104
|
+
...s,
|
|
105
|
+
sync: p
|
|
169
106
|
};
|
|
170
|
-
},
|
|
107
|
+
}, O = {
|
|
171
108
|
localFirst: !0,
|
|
172
109
|
optimistic: !0,
|
|
173
110
|
syncOnForeground: !0,
|
|
@@ -179,16 +116,7 @@ var p = (e) => {
|
|
|
179
116
|
15e3,
|
|
180
117
|
6e4
|
|
181
118
|
]
|
|
182
|
-
},
|
|
183
|
-
read: () => typeof navigator > "u" || navigator.onLine,
|
|
184
|
-
subscribe: (e) => {
|
|
185
|
-
if (typeof window > "u") return () => {};
|
|
186
|
-
let t = () => e(!0), n = () => e(!1);
|
|
187
|
-
return window.addEventListener("online", t), window.addEventListener("offline", n), () => {
|
|
188
|
-
window.removeEventListener("online", t), window.removeEventListener("offline", n);
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
}, k = (e) => {
|
|
119
|
+
}, k = (e, t) => e ? t > 0 ? "degraded" : "connected" : "offline", A = (e) => {
|
|
192
120
|
let t = (e) => typeof e.isInternetReachable == "boolean" ? e.isInternetReachable : e.isConnected === !0, n = !0;
|
|
193
121
|
return {
|
|
194
122
|
read: () => n,
|
|
@@ -201,27 +129,27 @@ var p = (e) => {
|
|
|
201
129
|
}).catch(() => {}), i;
|
|
202
130
|
}
|
|
203
131
|
};
|
|
204
|
-
},
|
|
205
|
-
let t = e?.onlineSource ??
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}), []),
|
|
209
|
-
r(e), e &&
|
|
132
|
+
}, j = (e) => {
|
|
133
|
+
let t = e?.onlineSource ?? o, [n, r] = x(() => t.read()), [i, a] = x(0), [s, c] = x(void 0), l = b(!0);
|
|
134
|
+
v(() => (l.current = !0, () => {
|
|
135
|
+
l.current = !1;
|
|
136
|
+
}), []), v(() => t.subscribe((e) => {
|
|
137
|
+
r(e), e && a(0);
|
|
210
138
|
}), [t]);
|
|
211
|
-
let
|
|
212
|
-
|
|
213
|
-
}, []),
|
|
214
|
-
|
|
139
|
+
let u = _(() => {
|
|
140
|
+
l.current && (a((e) => e + 1), c(Date.now()));
|
|
141
|
+
}, []), d = _(() => {
|
|
142
|
+
l.current && a(0);
|
|
215
143
|
}, []);
|
|
216
144
|
return {
|
|
217
|
-
status:
|
|
145
|
+
status: k(n, i),
|
|
218
146
|
online: n,
|
|
219
147
|
failureCount: i,
|
|
220
|
-
lastFailureAt:
|
|
221
|
-
reportFailure:
|
|
222
|
-
reportSuccess:
|
|
148
|
+
lastFailureAt: s,
|
|
149
|
+
reportFailure: u,
|
|
150
|
+
reportSuccess: d
|
|
223
151
|
};
|
|
224
|
-
},
|
|
152
|
+
}, M = (e) => {
|
|
225
153
|
let { storage: t, keys: n } = e, r = e.onError ?? ((e, t) => {
|
|
226
154
|
console.warn(`[voltro] persisting '${e}' failed`, t);
|
|
227
155
|
}), i = /* @__PURE__ */ new Map(), a = !1, o = null, s = /* @__PURE__ */ new Map(), c = null, l = async () => {
|
|
@@ -280,16 +208,16 @@ var p = (e) => {
|
|
|
280
208
|
},
|
|
281
209
|
keys: () => [...i.keys()]
|
|
282
210
|
};
|
|
283
|
-
},
|
|
211
|
+
}, N = (e, t) => {
|
|
284
212
|
let n = globalThis.WebSocket;
|
|
285
213
|
if (n === void 0) throw Error("startMobileApis: no global WebSocket. React Native provides one; if you are running these bindings somewhere else, pass `webSocketConstructor`.");
|
|
286
214
|
return t === void 0 ? new n(e) : new n(e, t);
|
|
287
|
-
},
|
|
215
|
+
}, P = (e, t, n) => (r, i) => {
|
|
288
216
|
let a = e(r, i);
|
|
289
217
|
return a.addEventListener("open", () => t()), a.addEventListener("close", () => n("close")), a.addEventListener("error", () => n("error")), a;
|
|
290
|
-
},
|
|
291
|
-
let t = e.webSocketConstructor ??
|
|
292
|
-
return
|
|
218
|
+
}, F = (e) => {
|
|
219
|
+
let t = e.webSocketConstructor ?? N;
|
|
220
|
+
return g({
|
|
293
221
|
apis: e.apis.map((e) => ({
|
|
294
222
|
name: e.name,
|
|
295
223
|
group: e.group,
|
|
@@ -300,7 +228,7 @@ var p = (e) => {
|
|
|
300
228
|
})),
|
|
301
229
|
...e.retryDelayMs === void 0 ? {} : { retryDelayMs: e.retryDelayMs },
|
|
302
230
|
onChange: e.onChange,
|
|
303
|
-
buildClient: async (e, n, r, i, a, o) => await
|
|
231
|
+
buildClient: async (e, n, r, i, a, o) => await s({
|
|
304
232
|
name: e.name,
|
|
305
233
|
generation: n,
|
|
306
234
|
wsUrl: e.wsUrl,
|
|
@@ -308,13 +236,13 @@ var p = (e) => {
|
|
|
308
236
|
...e.headers === void 0 ? {} : { headers: e.headers },
|
|
309
237
|
...a === void 0 ? {} : { errorBus: a },
|
|
310
238
|
...o === void 0 ? {} : { recovery: o },
|
|
311
|
-
webSocketConstructor:
|
|
239
|
+
webSocketConstructor: P(t, r, i)
|
|
312
240
|
})
|
|
313
241
|
});
|
|
314
|
-
},
|
|
242
|
+
}, I = (e, t, n = "/ws") => {
|
|
315
243
|
let r = (e ?? "").split(":")[0];
|
|
316
244
|
return r === void 0 || r === "" || r === "localhost" || r === "127.0.0.1" ? `ws://localhost:${t}${n}` : `ws://${r}:${t}${n}`;
|
|
317
|
-
},
|
|
245
|
+
}, L = (e, t) => {
|
|
318
246
|
let n = /* @__PURE__ */ new Map();
|
|
319
247
|
for (let r of e) {
|
|
320
248
|
let e = t.get(r.name);
|
|
@@ -325,10 +253,164 @@ var p = (e) => {
|
|
|
325
253
|
descriptors: r.descriptors,
|
|
326
254
|
inspectBaseUrl: r.wsUrl.replace(/^ws/, "http").replace(/\/ws$/, ""),
|
|
327
255
|
errorBus: e.errorBus,
|
|
328
|
-
recovery: e.recovery ??
|
|
256
|
+
recovery: e.recovery ?? m(e.errorBus, r.name, r.recovery)
|
|
329
257
|
});
|
|
330
258
|
}
|
|
331
259
|
return n;
|
|
260
|
+
}, R = (e) => e === "ios" ? "ios" : e === "android" ? "android" : e === "web" ? "web" : "unknown", z = (e) => e === "active" ? "active" : e === "background" ? "background" : "inactive", B = (e) => e === "granted" ? "granted" : e === "denied" ? "denied" : "prompt", V = (e) => ({
|
|
261
|
+
kind: "keychain",
|
|
262
|
+
get: (t) => e.getItemAsync(t),
|
|
263
|
+
set: (t, n) => e.setItemAsync(t, n),
|
|
264
|
+
delete: (t) => e.deleteItemAsync(t)
|
|
265
|
+
}), H = (e) => ({
|
|
266
|
+
read: () => z(e.currentState),
|
|
267
|
+
subscribe: (t) => {
|
|
268
|
+
let n = e.addEventListener("change", (e) => t(z(e)));
|
|
269
|
+
return () => n.remove();
|
|
270
|
+
}
|
|
271
|
+
}), U = (e) => ({
|
|
272
|
+
initialUrl: () => e.getInitialURL(),
|
|
273
|
+
subscribe: (t) => {
|
|
274
|
+
let n = e.addEventListener("url", ({ url: e }) => t(e));
|
|
275
|
+
return () => n.remove();
|
|
276
|
+
}
|
|
277
|
+
}), W = (e, t) => ({
|
|
278
|
+
permission: async () => B((await e.getPermissionsAsync()).status),
|
|
279
|
+
requestPermission: async () => B((await e.requestPermissionsAsync()).status),
|
|
280
|
+
...e.getExpoPushTokenAsync === void 0 ? {} : { pushToken: async () => (await e.getExpoPushTokenAsync(t === void 0 ? void 0 : { projectId: t })).data },
|
|
281
|
+
...e.scheduleNotificationAsync === void 0 ? {} : { show: async (t) => {
|
|
282
|
+
await e.scheduleNotificationAsync({
|
|
283
|
+
content: {
|
|
284
|
+
title: t.title,
|
|
285
|
+
...t.body === void 0 ? {} : { body: t.body },
|
|
286
|
+
...t.data === void 0 ? {} : { data: { ...t.data } }
|
|
287
|
+
},
|
|
288
|
+
trigger: null
|
|
289
|
+
});
|
|
290
|
+
} }
|
|
291
|
+
}), G = (e) => ({
|
|
292
|
+
check: async () => {
|
|
293
|
+
let t = await e.checkForUpdateAsync();
|
|
294
|
+
return t.isAvailable ? { version: t.manifest?.id ?? "available" } : null;
|
|
295
|
+
},
|
|
296
|
+
apply: async () => {
|
|
297
|
+
await e.fetchUpdateAsync(), await e.reloadAsync();
|
|
298
|
+
}
|
|
299
|
+
}), K = (e) => ({
|
|
300
|
+
available: async () => await e.hasHardwareAsync() && await e.isEnrolledAsync(),
|
|
301
|
+
authenticate: async (t) => (await e.authenticateAsync({ promptMessage: t })).success
|
|
302
|
+
}), q = async (e) => {
|
|
303
|
+
let t = M({
|
|
304
|
+
storage: e.storage,
|
|
305
|
+
...e.persistedKeys === void 0 ? {} : { keys: e.persistedKeys }
|
|
306
|
+
});
|
|
307
|
+
return await t.hydrate(), {
|
|
308
|
+
adapter: u({
|
|
309
|
+
platform: {
|
|
310
|
+
kind: R(e.os),
|
|
311
|
+
shell: "expo",
|
|
312
|
+
installed: !0,
|
|
313
|
+
...e.appVersion === void 0 ? {} : { appVersion: e.appVersion },
|
|
314
|
+
...e.updates?.updateId ? { buildId: e.updates.updateId } : {}
|
|
315
|
+
},
|
|
316
|
+
webSocket: e.webSocket ?? N,
|
|
317
|
+
storage: t.provider,
|
|
318
|
+
secureStorage: V(e.secureStore),
|
|
319
|
+
online: A(e.netInfo),
|
|
320
|
+
lifecycle: H(e.appState),
|
|
321
|
+
links: U(e.linking),
|
|
322
|
+
...e.notifications === void 0 ? {} : { notifications: W(e.notifications, e.expoProjectId) },
|
|
323
|
+
...e.updates === void 0 ? {} : { updates: G(e.updates) },
|
|
324
|
+
...e.localAuthentication === void 0 ? {} : { biometrics: K(e.localAuthentication) },
|
|
325
|
+
clock: { now: () => Date.now() },
|
|
326
|
+
...e.extensions === void 0 ? {} : { extensions: e.extensions },
|
|
327
|
+
...e.capabilities === void 0 ? {} : { capabilities: e.capabilities }
|
|
328
|
+
}),
|
|
329
|
+
persistence: t
|
|
330
|
+
};
|
|
331
|
+
}, J = "\nCREATE TABLE IF NOT EXISTS voltro_crdt (key TEXT PRIMARY KEY NOT NULL, state BLOB NOT NULL);\nCREATE TABLE IF NOT EXISTS voltro_queue (id INTEGER PRIMARY KEY CHECK (id = 1), json TEXT NOT NULL);\nCREATE TABLE IF NOT EXISTS voltro_pins (key TEXT PRIMARY KEY NOT NULL);\nCREATE TABLE IF NOT EXISTS voltro_kv (key TEXT PRIMARY KEY NOT NULL, json TEXT NOT NULL);\n", Y = (e, t) => `${e}\u0001${t}`, X = (e) => {
|
|
332
|
+
if (e instanceof Uint8Array) return new Uint8Array(e);
|
|
333
|
+
if (ArrayBuffer.isView(e)) return new Uint8Array(e.buffer, e.byteOffset, e.byteLength).slice();
|
|
334
|
+
if (e instanceof ArrayBuffer) return new Uint8Array(e.slice(0));
|
|
335
|
+
throw Error("expo-sqlite persistence: CRDT state column is not a BLOB");
|
|
336
|
+
}, Z = (e) => `${e.replace(/[\\%_]/g, (e) => `\\${e}`)}%`, Q = async (e) => {
|
|
337
|
+
let t = async () => {
|
|
338
|
+
await e.execAsync(J);
|
|
339
|
+
};
|
|
340
|
+
return await t(), {
|
|
341
|
+
persistence: {
|
|
342
|
+
kind: "expo-sqlite",
|
|
343
|
+
loadCrdtState: async (t, n) => {
|
|
344
|
+
let r = await e.getFirstAsync("SELECT state FROM voltro_crdt WHERE key = ?", [Y(t, n)]);
|
|
345
|
+
return r === null ? void 0 : X(r.state);
|
|
346
|
+
},
|
|
347
|
+
saveCrdtState: async (t, n, r) => {
|
|
348
|
+
await e.runAsync("INSERT OR REPLACE INTO voltro_crdt (key, state) VALUES (?, ?)", [Y(t, n), new Uint8Array(r)]);
|
|
349
|
+
},
|
|
350
|
+
loadQueue: async () => {
|
|
351
|
+
let t = await e.getFirstAsync("SELECT json FROM voltro_queue WHERE id = 1");
|
|
352
|
+
if (t === null) return [];
|
|
353
|
+
try {
|
|
354
|
+
return JSON.parse(t.json);
|
|
355
|
+
} catch {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
saveQueue: async (t) => {
|
|
360
|
+
await e.runAsync("INSERT OR REPLACE INTO voltro_queue (id, json) VALUES (1, ?)", [JSON.stringify(t)]);
|
|
361
|
+
},
|
|
362
|
+
pin: async (t, n) => {
|
|
363
|
+
await e.runAsync("INSERT OR IGNORE INTO voltro_pins (key) VALUES (?)", [Y(t, n)]);
|
|
364
|
+
},
|
|
365
|
+
isPinned: async (t, n) => await e.getFirstAsync("SELECT key FROM voltro_pins WHERE key = ?", [Y(t, n)]) !== null
|
|
366
|
+
},
|
|
367
|
+
kv: {
|
|
368
|
+
kind: "expo-sqlite",
|
|
369
|
+
get: async (t) => {
|
|
370
|
+
let n = await e.getFirstAsync("SELECT json FROM voltro_kv WHERE key = ?", [t]);
|
|
371
|
+
if (n !== null) try {
|
|
372
|
+
return JSON.parse(n.json);
|
|
373
|
+
} catch {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
put: async (t, n) => {
|
|
378
|
+
await e.runAsync("INSERT OR REPLACE INTO voltro_kv (key, json) VALUES (?, ?)", [t, JSON.stringify(n)]);
|
|
379
|
+
},
|
|
380
|
+
del: async (t) => {
|
|
381
|
+
await e.runAsync("DELETE FROM voltro_kv WHERE key = ?", [t]);
|
|
382
|
+
},
|
|
383
|
+
keysWithPrefix: async (t) => (await e.getAllAsync("SELECT key FROM voltro_kv WHERE key LIKE ? ESCAPE '\\'", [Z(t)])).map((e) => e.key)
|
|
384
|
+
},
|
|
385
|
+
migrate: t
|
|
386
|
+
};
|
|
387
|
+
}, $ = "voltro-background-sync", ee = (e) => {
|
|
388
|
+
let t = e.name ?? "voltro-background-sync", n = e.backgroundFetch.BackgroundFetchResult, r = async () => {
|
|
389
|
+
try {
|
|
390
|
+
let t = await e.run() ?? "no-data";
|
|
391
|
+
return e.onOutcome?.(t), t;
|
|
392
|
+
} catch (t) {
|
|
393
|
+
return e.onOutcome?.("failed", t), "failed";
|
|
394
|
+
}
|
|
395
|
+
}, i = (e) => e === "new-data" ? n.NewData : e === "no-data" ? n.NoData : n.Failed;
|
|
396
|
+
return e.taskManager.defineTask(t, async ({ error: t }) => t ? (e.onOutcome?.("failed", t), n.Failed) : i(await r())), {
|
|
397
|
+
name: t,
|
|
398
|
+
register: async () => {
|
|
399
|
+
e.taskManager.isTaskRegisteredAsync && await e.taskManager.isTaskRegisteredAsync(t) || await e.backgroundFetch.registerTaskAsync(t, {
|
|
400
|
+
minimumInterval: e.minimumIntervalSeconds ?? 900,
|
|
401
|
+
stopOnTerminate: !(e.survivesTermination ?? !0),
|
|
402
|
+
startOnBoot: e.startOnBoot ?? !0
|
|
403
|
+
});
|
|
404
|
+
},
|
|
405
|
+
unregister: () => e.backgroundFetch.unregisterTaskAsync(t),
|
|
406
|
+
availability: async () => {
|
|
407
|
+
let t = e.backgroundFetch;
|
|
408
|
+
if (!t.getStatusAsync || !t.BackgroundFetchStatus) return "unknown";
|
|
409
|
+
let n = await t.getStatusAsync();
|
|
410
|
+
return n === t.BackgroundFetchStatus.Available ? "available" : n === t.BackgroundFetchStatus.Denied ? "denied" : n === t.BackgroundFetchStatus.Restricted ? "restricted" : "unknown";
|
|
411
|
+
},
|
|
412
|
+
runNow: r
|
|
413
|
+
};
|
|
332
414
|
};
|
|
333
415
|
//#endregion
|
|
334
|
-
export { i as DEVICES_TABLE, n as DEVICE_PLATFORMS,
|
|
416
|
+
export { $ as DEFAULT_BACKGROUND_SYNC_TASK, i as DEVICES_TABLE, n as DEVICE_PLATFORMS, H as appStateLifecycle, C as backgroundSyncReducer, a as browserOnlineSource, M as createAsyncStoragePersistence, q as createExpoPlatform, Q as createExpoSqliteLocalFirst, c as deepLinkHref, N as defaultWebSocketConstructor, ee as defineBackgroundSyncTask, l as defineDeepLink, k as deriveConnectionStatus, d as dispatchDeepLink, K as expoBiometrics, W as expoNotifications, V as expoSecureTokenStore, G as expoUpdates, S as initialBackgroundSyncState, r as isDevicePlatform, U as linkingDeepLinks, f as matchDeepLink, p as matchFirstDeepLink, A as netInfoOnlineSource, O as offlineFirstDefaults, t as registerDevice, I as resolveDevWsUrl, e as resolveDeviceRegistration, h as runDeepLink, w as shouldSync, F as startMobileApis, L as toApiHandles, D as useBackgroundSync, j as useMobileConnectionStatus, P as wireSocket };
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { ColumnBuilder } from '@voltro/database';
|
|
2
|
+
import { DataStore } from '@voltro/database';
|
|
2
3
|
import { FieldDefinitions } from '@voltro/database';
|
|
3
4
|
import { Table } from '@voltro/database';
|
|
4
5
|
|
|
6
|
+
/** `localeFor` for `sendNotification`: the most recently seen device's locale. */
|
|
7
|
+
export declare const deviceLocaleFor: (store: DataStore) => (subjectId: string) => Promise<string | null>;
|
|
8
|
+
|
|
9
|
+
/** The push transport a device is reachable on. */
|
|
10
|
+
declare type DevicePlatform = 'ios' | 'android' | 'web';
|
|
11
|
+
|
|
5
12
|
/** The framework table name devices are stored in — shared with `./schema`. */
|
|
6
13
|
export declare const DEVICES_TABLE = "_voltro_devices";
|
|
7
14
|
|
|
@@ -19,4 +26,12 @@ export declare const devicesTable: Table<"_voltro_devices", FieldDefinitions<{
|
|
|
19
26
|
readonly createdAt: ColumnBuilder<Date, "timestamp", true>;
|
|
20
27
|
}>, true, "byDeviceUser" | "byDeviceTenant">;
|
|
21
28
|
|
|
29
|
+
/** `tokensFor` for `pushChannel`: every registered token of a subject, newest
|
|
30
|
+
* first. Optionally one platform (`'ios'`, `'android'`). */
|
|
31
|
+
export declare const deviceTokensFor: (store: DataStore, platform?: DevicePlatform) => (subjectId: string) => Promise<ReadonlyArray<string>>;
|
|
32
|
+
|
|
33
|
+
/** `onTokenRejected` for `pushChannel`: delete the device row a provider
|
|
34
|
+
* reported gone, so the next fan-out does not retry it. */
|
|
35
|
+
export declare const pruneDeviceToken: (store: DataStore) => (token: string) => Promise<void>;
|
|
36
|
+
|
|
22
37
|
export { }
|
package/dist/schema.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { t as e } from "./devices-BjXAU-8I.js";
|
|
2
|
-
import {
|
|
2
|
+
import { eq as t, id as n, queryFor as r, table as i, text as a, timestamp as o } from "@voltro/database";
|
|
3
3
|
//#region src/schema.ts
|
|
4
|
-
var
|
|
5
|
-
id:
|
|
6
|
-
tenantId:
|
|
7
|
-
userId:
|
|
8
|
-
platform:
|
|
9
|
-
token:
|
|
10
|
-
locale:
|
|
11
|
-
timezone:
|
|
12
|
-
appVersion:
|
|
13
|
-
metadata:
|
|
14
|
-
lastSeenAt:
|
|
15
|
-
createdAt:
|
|
16
|
-
}).unique("byDeviceToken", ["platform", "token"]).index("byDeviceUser", ["userId"]).index("byDeviceTenant", ["tenantId"])
|
|
4
|
+
var s = i(e, {
|
|
5
|
+
id: n({ prefix: "device" }),
|
|
6
|
+
tenantId: a().nullable(),
|
|
7
|
+
userId: a(),
|
|
8
|
+
platform: a(),
|
|
9
|
+
token: a(),
|
|
10
|
+
locale: a().nullable(),
|
|
11
|
+
timezone: a().nullable(),
|
|
12
|
+
appVersion: a().nullable(),
|
|
13
|
+
metadata: a().nullable(),
|
|
14
|
+
lastSeenAt: o().default("now"),
|
|
15
|
+
createdAt: o().default("now")
|
|
16
|
+
}).unique("byDeviceToken", ["platform", "token"]).index("byDeviceUser", ["userId"]).index("byDeviceTenant", ["tenantId"]), c = (e, n) => async (i) => (await e.query(r(s).where(t("userId", i)).descriptor)).filter((e) => n === void 0 || e.platform === n).sort((e, t) => t.lastSeenAt.getTime() - e.lastSeenAt.getTime()).map((e) => e.token), l = (n) => async (i) => {
|
|
17
|
+
let a = await n.query(r(s).where(t("token", i)).descriptor);
|
|
18
|
+
for (let t of a) await n.delete(e, t.id);
|
|
19
|
+
}, u = (e) => async (n) => [...await e.query(r(s).where(t("userId", n)).descriptor)].sort((e, t) => t.lastSeenAt.getTime() - e.lastSeenAt.getTime())[0]?.locale ?? null;
|
|
17
20
|
//#endregion
|
|
18
|
-
export { e as DEVICES_TABLE,
|
|
21
|
+
export { e as DEVICES_TABLE, u as deviceLocaleFor, c as deviceTokensFor, s as devicesTable, l as pruneDeviceToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.82.0",
|
|
4
4
|
"description": "React Native bindings for the framework: device-registration primitive, background-sync state machine, offline-first client defaults + connection-status surface, and the deep-link declaration shape — the credential-free mobile plumbing on top of the RN-safe React client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -38,8 +38,9 @@
|
|
|
38
38
|
"node": ">=24.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@voltro/client": "0.
|
|
42
|
-
"@voltro/database": "0.
|
|
41
|
+
"@voltro/client": "0.82.0",
|
|
42
|
+
"@voltro/database": "0.82.0",
|
|
43
|
+
"@voltro/local-first": "0.82.0"
|
|
43
44
|
},
|
|
44
45
|
"peerDependencies": {
|
|
45
46
|
"react": "^19.0.0"
|