silosdk 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/source.cjs +161 -0
- package/dist/source.d.cts +29 -0
- package/dist/source.d.mts +29 -0
- package/dist/source.mjs +161 -0
- package/package.json +19 -21
- package/README.md +0 -3
- package/dist/_virtual/rolldown_runtime.cjs +0 -29
- package/dist/cli/d1.cjs +0 -93
- package/dist/cli/d1.mjs +0 -92
- package/dist/cli/index.cjs +0 -93
- package/dist/cli/index.d.cts +0 -1
- package/dist/cli/index.d.mts +0 -1
- package/dist/cli/index.mjs +0 -94
- package/dist/cli/init.cjs +0 -134
- package/dist/cli/init.mjs +0 -133
- package/dist/cli/kv.cjs +0 -63
- package/dist/cli/kv.mjs +0 -60
- package/dist/cli/r2.cjs +0 -83
- package/dist/cli/r2.mjs +0 -82
- package/dist/cli/wrangler.cjs +0 -93
- package/dist/cli/wrangler.mjs +0 -89
- package/dist/local/adapters/cloudflare.cjs +0 -200
- package/dist/local/adapters/cloudflare.d.cts +0 -50
- package/dist/local/adapters/cloudflare.d.mts +0 -50
- package/dist/local/adapters/cloudflare.mjs +0 -200
- package/dist/local/auth-context.cjs +0 -14
- package/dist/local/auth-context.d.cts +0 -7
- package/dist/local/auth-context.d.mts +0 -7
- package/dist/local/auth-context.mjs +0 -12
- package/dist/local/auth.cjs +0 -109
- package/dist/local/auth.d.cts +0 -26
- package/dist/local/auth.d.mts +0 -26
- package/dist/local/auth.mjs +0 -99
- package/dist/local/commit.cjs +0 -350
- package/dist/local/commit.d.cts +0 -59
- package/dist/local/commit.d.mts +0 -59
- package/dist/local/commit.mjs +0 -349
- package/dist/local/config.cjs +0 -17
- package/dist/local/config.mjs +0 -15
- package/dist/local/index.cjs +0 -16
- package/dist/local/index.d.cts +0 -10
- package/dist/local/index.d.mts +0 -10
- package/dist/local/index.mjs +0 -9
- package/dist/local/provider.cjs +0 -204
- package/dist/local/provider.d.cts +0 -25
- package/dist/local/provider.d.mts +0 -25
- package/dist/local/provider.mjs +0 -203
- package/dist/local/query-store.cjs +0 -276
- package/dist/local/query-store.mjs +0 -274
- package/dist/local/storage.cjs +0 -71
- package/dist/local/storage.d.cts +0 -7
- package/dist/local/storage.d.mts +0 -7
- package/dist/local/storage.mjs +0 -68
- package/dist/local/sync.cjs +0 -124
- package/dist/local/sync.d.cts +0 -36
- package/dist/local/sync.d.mts +0 -36
- package/dist/local/sync.mjs +0 -122
- package/dist/local/view.cjs +0 -257
- package/dist/local/view.d.cts +0 -24
- package/dist/local/view.d.mts +0 -24
- package/dist/local/view.mjs +0 -254
- package/dist/package.cjs +0 -11
- package/dist/package.mjs +0 -5
- package/dist/schema/index.cjs +0 -276
- package/dist/schema/index.d.cts +0 -207
- package/dist/schema/index.d.mts +0 -207
- package/dist/schema/index.mjs +0 -265
- package/dist/server/auth.cjs +0 -132
- package/dist/server/auth.d.cts +0 -49
- package/dist/server/auth.d.mts +0 -49
- package/dist/server/auth.mjs +0 -122
- package/dist/server/d1.cjs +0 -120
- package/dist/server/d1.mjs +0 -116
- package/dist/server/do.cjs +0 -132
- package/dist/server/do.d.cts +0 -21
- package/dist/server/do.d.mts +0 -21
- package/dist/server/do.mjs +0 -131
- package/dist/server/index.cjs +0 -355
- package/dist/server/index.d.cts +0 -65
- package/dist/server/index.d.mts +0 -65
- package/dist/server/index.mjs +0 -348
- package/dist/server/protect.cjs +0 -34
- package/dist/server/protect.d.cts +0 -32
- package/dist/server/protect.d.mts +0 -32
- package/dist/server/protect.mjs +0 -33
- package/dist/server/r2.cjs +0 -58
- package/dist/server/r2.d.cts +0 -4
- package/dist/server/r2.d.mts +0 -4
- package/dist/server/r2.mjs +0 -53
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { SyncAdapter, applyRemoteOps } from "../sync.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/local/adapters/cloudflare.ts
|
|
4
|
-
const INITIAL_BACKOFF = 1e3;
|
|
5
|
-
const MAX_BACKOFF = 3e4;
|
|
6
|
-
const SYNC_RETRY_WINDOW_MS = 3e4;
|
|
7
|
-
const SYNC_MAX_RETRIES = 5;
|
|
8
|
-
var CloudflareSyncAdapter = class extends SyncAdapter {
|
|
9
|
-
constructor(options) {
|
|
10
|
-
super({ merge: options.merge });
|
|
11
|
-
this.ws = null;
|
|
12
|
-
this.reconnectTimer = null;
|
|
13
|
-
this.backoff = INITIAL_BACKOFF;
|
|
14
|
-
this.alive = true;
|
|
15
|
-
this.registeredViews = [];
|
|
16
|
-
this.failureCount = 0;
|
|
17
|
-
this.firstFailureAt = 0;
|
|
18
|
-
this.blocked = false;
|
|
19
|
-
this.warned = false;
|
|
20
|
-
this.ignoreClose = false;
|
|
21
|
-
this.pendingCommits = /* @__PURE__ */ new Map();
|
|
22
|
-
this.url = options.url;
|
|
23
|
-
this.getToken = options.getToken;
|
|
24
|
-
this.db = options.db;
|
|
25
|
-
this.subscribers = options.subscribers;
|
|
26
|
-
}
|
|
27
|
-
/** Register the view names this adapter should subscribe to on connect. */
|
|
28
|
-
registerViews(names) {
|
|
29
|
-
this.registeredViews = names;
|
|
30
|
-
}
|
|
31
|
-
async connect() {
|
|
32
|
-
if (!this.alive) return;
|
|
33
|
-
if (this.blocked) return;
|
|
34
|
-
try {
|
|
35
|
-
const wsUrl = this.url.replace(/^https?/, (m) => m === "https" ? "wss" : "ws");
|
|
36
|
-
const token = this.getToken ? await this.getToken() : null;
|
|
37
|
-
if (this.getToken && !token) return;
|
|
38
|
-
const url = token ? `${wsUrl}/sync?token=${encodeURIComponent(token)}` : `${wsUrl}/sync`;
|
|
39
|
-
this.ws = new WebSocket(url);
|
|
40
|
-
this.ws.onopen = () => {
|
|
41
|
-
this.backoff = INITIAL_BACKOFF;
|
|
42
|
-
if (this.registeredViews.length > 0) this.ws.send(JSON.stringify({
|
|
43
|
-
type: "subscribe",
|
|
44
|
-
views: this.registeredViews
|
|
45
|
-
}));
|
|
46
|
-
};
|
|
47
|
-
this.ws.onmessage = async (event) => {
|
|
48
|
-
const msg = JSON.parse(event.data);
|
|
49
|
-
await this.handleMessage(msg);
|
|
50
|
-
};
|
|
51
|
-
this.ws.onclose = () => {
|
|
52
|
-
if (this.ignoreClose) {
|
|
53
|
-
this.ignoreClose = false;
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (this.alive) this.scheduleReconnect();
|
|
57
|
-
};
|
|
58
|
-
this.ws.onerror = () => {
|
|
59
|
-
this.ws?.close();
|
|
60
|
-
};
|
|
61
|
-
} catch {
|
|
62
|
-
if (this.alive) this.scheduleReconnect();
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
async handleMessage(msg) {
|
|
66
|
-
switch (msg.type) {
|
|
67
|
-
case "hydrate": {
|
|
68
|
-
const ops = (msg.rows ?? []).map((row) => ({
|
|
69
|
-
kind: "add",
|
|
70
|
-
view: { name: msg.view },
|
|
71
|
-
id: row.id,
|
|
72
|
-
value: row.data,
|
|
73
|
-
version: row.version ?? 1,
|
|
74
|
-
timestamp: row.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
75
|
-
}));
|
|
76
|
-
if (ops.length > 0) await applyRemoteOps(this.db, ops, this.subscribers, this.merge);
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
case "push": {
|
|
80
|
-
const ops = msg.ops ?? [];
|
|
81
|
-
if (ops.length > 0) await applyRemoteOps(this.db, ops, this.subscribers, this.merge);
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
case "committed": {
|
|
85
|
-
const pending = this.pendingCommits.get(msg.requestId);
|
|
86
|
-
if (pending) {
|
|
87
|
-
pending.resolve();
|
|
88
|
-
this.pendingCommits.delete(msg.requestId);
|
|
89
|
-
}
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
case "rejected": {
|
|
93
|
-
const pending = this.pendingCommits.get(msg.requestId);
|
|
94
|
-
if (pending) {
|
|
95
|
-
pending.reject(msg.reason ?? "Rejected by server");
|
|
96
|
-
this.pendingCommits.delete(msg.requestId);
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
case "error":
|
|
101
|
-
console.error("[CloudflareSyncAdapter] server error:", msg.message);
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
if (msg.type === "push" && this.receiveHandler) await this.receiveHandler({ ops: msg.ops ?? [] });
|
|
105
|
-
}
|
|
106
|
-
scheduleReconnect() {
|
|
107
|
-
this.recordFailure();
|
|
108
|
-
if (this.blocked) return;
|
|
109
|
-
if (this.reconnectTimer) return;
|
|
110
|
-
this.reconnectTimer = setTimeout(() => {
|
|
111
|
-
this.reconnectTimer = null;
|
|
112
|
-
this.backoff = Math.min(this.backoff * 2, MAX_BACKOFF);
|
|
113
|
-
this.connect();
|
|
114
|
-
}, this.backoff);
|
|
115
|
-
}
|
|
116
|
-
recordFailure() {
|
|
117
|
-
const now = Date.now();
|
|
118
|
-
if (!this.firstFailureAt || now - this.firstFailureAt > SYNC_RETRY_WINDOW_MS) {
|
|
119
|
-
this.firstFailureAt = now;
|
|
120
|
-
this.failureCount = 0;
|
|
121
|
-
}
|
|
122
|
-
this.failureCount += 1;
|
|
123
|
-
if (this.failureCount > SYNC_MAX_RETRIES) {
|
|
124
|
-
this.blocked = true;
|
|
125
|
-
if (!this.warned) {
|
|
126
|
-
this.warned = true;
|
|
127
|
-
console.warn("[CloudflareSyncAdapter] Retry budget exceeded, blocking reconnects");
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
resetConnection() {
|
|
132
|
-
this.blocked = false;
|
|
133
|
-
this.warned = false;
|
|
134
|
-
this.failureCount = 0;
|
|
135
|
-
this.firstFailureAt = 0;
|
|
136
|
-
this.backoff = INITIAL_BACKOFF;
|
|
137
|
-
if (this.reconnectTimer) {
|
|
138
|
-
clearTimeout(this.reconnectTimer);
|
|
139
|
-
this.reconnectTimer = null;
|
|
140
|
-
}
|
|
141
|
-
if (this.ws) {
|
|
142
|
-
this.ignoreClose = true;
|
|
143
|
-
this.ws.close();
|
|
144
|
-
this.ws = null;
|
|
145
|
-
}
|
|
146
|
-
this.connect();
|
|
147
|
-
}
|
|
148
|
-
async send(payload) {
|
|
149
|
-
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
|
|
150
|
-
const requestId = Math.random().toString(36).slice(2);
|
|
151
|
-
return new Promise((resolve, reject) => {
|
|
152
|
-
this.pendingCommits.set(requestId, {
|
|
153
|
-
resolve,
|
|
154
|
-
reject
|
|
155
|
-
});
|
|
156
|
-
this.ws.send(JSON.stringify({
|
|
157
|
-
type: "commit",
|
|
158
|
-
ops: payload.ops,
|
|
159
|
-
requestId
|
|
160
|
-
}));
|
|
161
|
-
setTimeout(() => {
|
|
162
|
-
if (this.pendingCommits.has(requestId)) {
|
|
163
|
-
this.pendingCommits.delete(requestId);
|
|
164
|
-
resolve();
|
|
165
|
-
}
|
|
166
|
-
}, 1e4);
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
onReceive(handler) {
|
|
170
|
-
this.receiveHandler = handler;
|
|
171
|
-
}
|
|
172
|
-
async fetchInitialState() {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
disconnect() {
|
|
176
|
-
this.alive = false;
|
|
177
|
-
if (this.reconnectTimer) {
|
|
178
|
-
clearTimeout(this.reconnectTimer);
|
|
179
|
-
this.reconnectTimer = null;
|
|
180
|
-
}
|
|
181
|
-
this.ws?.close();
|
|
182
|
-
this.ws = null;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Reset backoff and force an immediate reconnect.
|
|
186
|
-
* Used after token changes (e.g. elevation from anonymous to authenticated).
|
|
187
|
-
*/
|
|
188
|
-
forceReconnect() {
|
|
189
|
-
if (this.reconnectTimer) {
|
|
190
|
-
clearTimeout(this.reconnectTimer);
|
|
191
|
-
this.reconnectTimer = null;
|
|
192
|
-
}
|
|
193
|
-
this.backoff = INITIAL_BACKOFF;
|
|
194
|
-
if (this.ws) this.ws.close();
|
|
195
|
-
else this.connect();
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
//#endregion
|
|
200
|
-
export { CloudflareSyncAdapter };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
-
let react = require("react");
|
|
3
|
-
|
|
4
|
-
//#region src/local/auth-context.ts
|
|
5
|
-
const AuthContext = (0, react.createContext)(null);
|
|
6
|
-
function useAuth() {
|
|
7
|
-
const ctx = (0, react.useContext)(AuthContext);
|
|
8
|
-
if (!ctx) throw new Error("silosdk: useAuth() must be used within <Provider>");
|
|
9
|
-
return ctx;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
exports.AuthContext = AuthContext;
|
|
14
|
-
exports.useAuth = useAuth;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from "react";
|
|
2
|
-
|
|
3
|
-
//#region src/local/auth-context.ts
|
|
4
|
-
const AuthContext = createContext(null);
|
|
5
|
-
function useAuth() {
|
|
6
|
-
const ctx = useContext(AuthContext);
|
|
7
|
-
if (!ctx) throw new Error("silosdk: useAuth() must be used within <Provider>");
|
|
8
|
-
return ctx;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
//#endregion
|
|
12
|
-
export { AuthContext, useAuth };
|
package/dist/local/auth.cjs
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
-
let expo_secure_store = require("expo-secure-store");
|
|
3
|
-
expo_secure_store = require_rolldown_runtime.__toESM(expo_secure_store);
|
|
4
|
-
|
|
5
|
-
//#region src/local/auth.ts
|
|
6
|
-
const SESSION_KEY = "silosdk_session_token";
|
|
7
|
-
let prodUrl = null;
|
|
8
|
-
function setAuthProdUrl(url) {
|
|
9
|
-
prodUrl = url;
|
|
10
|
-
}
|
|
11
|
-
function getSessionKey(url) {
|
|
12
|
-
if (!url) return SESSION_KEY;
|
|
13
|
-
return url === prodUrl ? `${SESSION_KEY}_prod` : `${SESSION_KEY}_dev`;
|
|
14
|
-
}
|
|
15
|
-
var AuthEventBus = class {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.listeners = /* @__PURE__ */ new Map();
|
|
18
|
-
}
|
|
19
|
-
on(event, listener) {
|
|
20
|
-
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
21
|
-
this.listeners.get(event).add(listener);
|
|
22
|
-
}
|
|
23
|
-
off(event, listener) {
|
|
24
|
-
this.listeners.get(event)?.delete(listener);
|
|
25
|
-
}
|
|
26
|
-
emit(event) {
|
|
27
|
-
this.listeners.get(event)?.forEach((l) => l());
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
const authEvents = new AuthEventBus();
|
|
31
|
-
function createAuthUser(data) {
|
|
32
|
-
return {
|
|
33
|
-
id: data.id,
|
|
34
|
-
email: data.email,
|
|
35
|
-
role: data.role,
|
|
36
|
-
isAnonymous: data.isAnonymous
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
async function getStoredSessionToken(url) {
|
|
40
|
-
try {
|
|
41
|
-
return await expo_secure_store.getItemAsync(getSessionKey(url));
|
|
42
|
-
} catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async function clearStoredSessionToken(url) {
|
|
47
|
-
try {
|
|
48
|
-
await expo_secure_store.deleteItemAsync(getSessionKey(url));
|
|
49
|
-
} catch {}
|
|
50
|
-
}
|
|
51
|
-
async function requestOtp(url, email) {
|
|
52
|
-
const res = await fetch(`${url}/auth/request`, {
|
|
53
|
-
method: "POST",
|
|
54
|
-
headers: { "Content-Type": "application/json" },
|
|
55
|
-
body: JSON.stringify({ email })
|
|
56
|
-
});
|
|
57
|
-
if (!res.ok) throw new Error(`OTP request failed: ${res.status}`);
|
|
58
|
-
}
|
|
59
|
-
async function verifyOtpWithServer(url, opts) {
|
|
60
|
-
const res = await fetch(`${url}/auth/verify`, {
|
|
61
|
-
method: "POST",
|
|
62
|
-
headers: { "Content-Type": "application/json" },
|
|
63
|
-
body: JSON.stringify(opts)
|
|
64
|
-
});
|
|
65
|
-
if (!res.ok) throw new Error(`OTP verification failed: ${res.status}`);
|
|
66
|
-
const { token, user: userData } = await res.json();
|
|
67
|
-
await expo_secure_store.setItemAsync(getSessionKey(url), token);
|
|
68
|
-
return {
|
|
69
|
-
token,
|
|
70
|
-
user: createAuthUser(userData)
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
async function signOutFromServer(url, token) {
|
|
74
|
-
if (token) await fetch(`${url}/auth/signout`, {
|
|
75
|
-
method: "POST",
|
|
76
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
77
|
-
});
|
|
78
|
-
await clearStoredSessionToken(url);
|
|
79
|
-
}
|
|
80
|
-
async function fetchCurrentUser(url, token) {
|
|
81
|
-
const res = await fetch(`${url}/auth/me`, { headers: { Authorization: `Bearer ${token}` } });
|
|
82
|
-
if (res.status === 401) return {
|
|
83
|
-
user: null,
|
|
84
|
-
unauthorized: true
|
|
85
|
-
};
|
|
86
|
-
if (!res.ok) return {
|
|
87
|
-
user: null,
|
|
88
|
-
unauthorized: false
|
|
89
|
-
};
|
|
90
|
-
return {
|
|
91
|
-
user: createAuthUser(await res.json()),
|
|
92
|
-
unauthorized: false
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
async function handleUnauthorized(url) {
|
|
96
|
-
await clearStoredSessionToken(url);
|
|
97
|
-
authEvents.emit("unauthorized");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
//#endregion
|
|
101
|
-
exports.authEvents = authEvents;
|
|
102
|
-
exports.clearStoredSessionToken = clearStoredSessionToken;
|
|
103
|
-
exports.fetchCurrentUser = fetchCurrentUser;
|
|
104
|
-
exports.getStoredSessionToken = getStoredSessionToken;
|
|
105
|
-
exports.handleUnauthorized = handleUnauthorized;
|
|
106
|
-
exports.requestOtp = requestOtp;
|
|
107
|
-
exports.setAuthProdUrl = setAuthProdUrl;
|
|
108
|
-
exports.signOutFromServer = signOutFromServer;
|
|
109
|
-
exports.verifyOtpWithServer = verifyOtpWithServer;
|
package/dist/local/auth.d.cts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//#region src/local/auth.d.ts
|
|
2
|
-
type AuthUser = {
|
|
3
|
-
id: string;
|
|
4
|
-
email: string | null;
|
|
5
|
-
role: string;
|
|
6
|
-
isAnonymous: boolean;
|
|
7
|
-
};
|
|
8
|
-
type AuthState = {
|
|
9
|
-
/** Resolved user — null for public-only access or while loading. */
|
|
10
|
-
user: AuthUser | null;
|
|
11
|
-
/** True while restoring session on first mount. */
|
|
12
|
-
isLoading: boolean;
|
|
13
|
-
/** Request an OTP to be sent to the given email address. */
|
|
14
|
-
signIn: (opts: {
|
|
15
|
-
email: string;
|
|
16
|
-
}) => Promise<void>;
|
|
17
|
-
/** Verify the OTP code sent to the email and establish an authenticated session. */
|
|
18
|
-
verifyOtp: (opts: {
|
|
19
|
-
email: string;
|
|
20
|
-
otp: string;
|
|
21
|
-
}) => Promise<void>;
|
|
22
|
-
/** Sign out and clear session. */
|
|
23
|
-
signOut: () => Promise<void>;
|
|
24
|
-
};
|
|
25
|
-
//#endregion
|
|
26
|
-
export { AuthState, AuthUser };
|
package/dist/local/auth.d.mts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
//#region src/local/auth.d.ts
|
|
2
|
-
type AuthUser = {
|
|
3
|
-
id: string;
|
|
4
|
-
email: string | null;
|
|
5
|
-
role: string;
|
|
6
|
-
isAnonymous: boolean;
|
|
7
|
-
};
|
|
8
|
-
type AuthState = {
|
|
9
|
-
/** Resolved user — null for public-only access or while loading. */
|
|
10
|
-
user: AuthUser | null;
|
|
11
|
-
/** True while restoring session on first mount. */
|
|
12
|
-
isLoading: boolean;
|
|
13
|
-
/** Request an OTP to be sent to the given email address. */
|
|
14
|
-
signIn: (opts: {
|
|
15
|
-
email: string;
|
|
16
|
-
}) => Promise<void>;
|
|
17
|
-
/** Verify the OTP code sent to the email and establish an authenticated session. */
|
|
18
|
-
verifyOtp: (opts: {
|
|
19
|
-
email: string;
|
|
20
|
-
otp: string;
|
|
21
|
-
}) => Promise<void>;
|
|
22
|
-
/** Sign out and clear session. */
|
|
23
|
-
signOut: () => Promise<void>;
|
|
24
|
-
};
|
|
25
|
-
//#endregion
|
|
26
|
-
export { AuthState, AuthUser };
|
package/dist/local/auth.mjs
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import * as SecureStore from "expo-secure-store";
|
|
2
|
-
|
|
3
|
-
//#region src/local/auth.ts
|
|
4
|
-
const SESSION_KEY = "silosdk_session_token";
|
|
5
|
-
let prodUrl = null;
|
|
6
|
-
function setAuthProdUrl(url) {
|
|
7
|
-
prodUrl = url;
|
|
8
|
-
}
|
|
9
|
-
function getSessionKey(url) {
|
|
10
|
-
if (!url) return SESSION_KEY;
|
|
11
|
-
return url === prodUrl ? `${SESSION_KEY}_prod` : `${SESSION_KEY}_dev`;
|
|
12
|
-
}
|
|
13
|
-
var AuthEventBus = class {
|
|
14
|
-
constructor() {
|
|
15
|
-
this.listeners = /* @__PURE__ */ new Map();
|
|
16
|
-
}
|
|
17
|
-
on(event, listener) {
|
|
18
|
-
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
19
|
-
this.listeners.get(event).add(listener);
|
|
20
|
-
}
|
|
21
|
-
off(event, listener) {
|
|
22
|
-
this.listeners.get(event)?.delete(listener);
|
|
23
|
-
}
|
|
24
|
-
emit(event) {
|
|
25
|
-
this.listeners.get(event)?.forEach((l) => l());
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
const authEvents = new AuthEventBus();
|
|
29
|
-
function createAuthUser(data) {
|
|
30
|
-
return {
|
|
31
|
-
id: data.id,
|
|
32
|
-
email: data.email,
|
|
33
|
-
role: data.role,
|
|
34
|
-
isAnonymous: data.isAnonymous
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
async function getStoredSessionToken(url) {
|
|
38
|
-
try {
|
|
39
|
-
return await SecureStore.getItemAsync(getSessionKey(url));
|
|
40
|
-
} catch {
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
async function clearStoredSessionToken(url) {
|
|
45
|
-
try {
|
|
46
|
-
await SecureStore.deleteItemAsync(getSessionKey(url));
|
|
47
|
-
} catch {}
|
|
48
|
-
}
|
|
49
|
-
async function requestOtp(url, email) {
|
|
50
|
-
const res = await fetch(`${url}/auth/request`, {
|
|
51
|
-
method: "POST",
|
|
52
|
-
headers: { "Content-Type": "application/json" },
|
|
53
|
-
body: JSON.stringify({ email })
|
|
54
|
-
});
|
|
55
|
-
if (!res.ok) throw new Error(`OTP request failed: ${res.status}`);
|
|
56
|
-
}
|
|
57
|
-
async function verifyOtpWithServer(url, opts) {
|
|
58
|
-
const res = await fetch(`${url}/auth/verify`, {
|
|
59
|
-
method: "POST",
|
|
60
|
-
headers: { "Content-Type": "application/json" },
|
|
61
|
-
body: JSON.stringify(opts)
|
|
62
|
-
});
|
|
63
|
-
if (!res.ok) throw new Error(`OTP verification failed: ${res.status}`);
|
|
64
|
-
const { token, user: userData } = await res.json();
|
|
65
|
-
await SecureStore.setItemAsync(getSessionKey(url), token);
|
|
66
|
-
return {
|
|
67
|
-
token,
|
|
68
|
-
user: createAuthUser(userData)
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
async function signOutFromServer(url, token) {
|
|
72
|
-
if (token) await fetch(`${url}/auth/signout`, {
|
|
73
|
-
method: "POST",
|
|
74
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
75
|
-
});
|
|
76
|
-
await clearStoredSessionToken(url);
|
|
77
|
-
}
|
|
78
|
-
async function fetchCurrentUser(url, token) {
|
|
79
|
-
const res = await fetch(`${url}/auth/me`, { headers: { Authorization: `Bearer ${token}` } });
|
|
80
|
-
if (res.status === 401) return {
|
|
81
|
-
user: null,
|
|
82
|
-
unauthorized: true
|
|
83
|
-
};
|
|
84
|
-
if (!res.ok) return {
|
|
85
|
-
user: null,
|
|
86
|
-
unauthorized: false
|
|
87
|
-
};
|
|
88
|
-
return {
|
|
89
|
-
user: createAuthUser(await res.json()),
|
|
90
|
-
unauthorized: false
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
async function handleUnauthorized(url) {
|
|
94
|
-
await clearStoredSessionToken(url);
|
|
95
|
-
authEvents.emit("unauthorized");
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
//#endregion
|
|
99
|
-
export { authEvents, clearStoredSessionToken, fetchCurrentUser, getStoredSessionToken, handleUnauthorized, requestOtp, setAuthProdUrl, signOutFromServer, verifyOtpWithServer };
|