silosdk 0.0.1 → 0.0.3

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.
Files changed (92) hide show
  1. package/dist/settings.cjs +70 -0
  2. package/dist/settings.d.cts +20 -0
  3. package/dist/settings.d.mts +20 -0
  4. package/dist/settings.mjs +68 -0
  5. package/dist/source.cjs +162 -0
  6. package/dist/source.d.cts +29 -0
  7. package/dist/source.d.mts +29 -0
  8. package/dist/source.mjs +161 -0
  9. package/package.json +23 -20
  10. package/README.md +0 -3
  11. package/dist/cli/d1.cjs +0 -93
  12. package/dist/cli/d1.mjs +0 -92
  13. package/dist/cli/index.cjs +0 -93
  14. package/dist/cli/index.d.cts +0 -1
  15. package/dist/cli/index.d.mts +0 -1
  16. package/dist/cli/index.mjs +0 -94
  17. package/dist/cli/init.cjs +0 -134
  18. package/dist/cli/init.mjs +0 -133
  19. package/dist/cli/kv.cjs +0 -63
  20. package/dist/cli/kv.mjs +0 -60
  21. package/dist/cli/r2.cjs +0 -83
  22. package/dist/cli/r2.mjs +0 -82
  23. package/dist/cli/wrangler.cjs +0 -93
  24. package/dist/cli/wrangler.mjs +0 -89
  25. package/dist/local/adapters/cloudflare.cjs +0 -200
  26. package/dist/local/adapters/cloudflare.d.cts +0 -50
  27. package/dist/local/adapters/cloudflare.d.mts +0 -50
  28. package/dist/local/adapters/cloudflare.mjs +0 -200
  29. package/dist/local/auth-context.cjs +0 -14
  30. package/dist/local/auth-context.d.cts +0 -7
  31. package/dist/local/auth-context.d.mts +0 -7
  32. package/dist/local/auth-context.mjs +0 -12
  33. package/dist/local/auth.cjs +0 -109
  34. package/dist/local/auth.d.cts +0 -26
  35. package/dist/local/auth.d.mts +0 -26
  36. package/dist/local/auth.mjs +0 -99
  37. package/dist/local/commit.cjs +0 -350
  38. package/dist/local/commit.d.cts +0 -59
  39. package/dist/local/commit.d.mts +0 -59
  40. package/dist/local/commit.mjs +0 -349
  41. package/dist/local/config.cjs +0 -17
  42. package/dist/local/config.mjs +0 -15
  43. package/dist/local/index.cjs +0 -16
  44. package/dist/local/index.d.cts +0 -10
  45. package/dist/local/index.d.mts +0 -10
  46. package/dist/local/index.mjs +0 -9
  47. package/dist/local/provider.cjs +0 -204
  48. package/dist/local/provider.d.cts +0 -25
  49. package/dist/local/provider.d.mts +0 -25
  50. package/dist/local/provider.mjs +0 -203
  51. package/dist/local/query-store.cjs +0 -276
  52. package/dist/local/query-store.mjs +0 -274
  53. package/dist/local/storage.cjs +0 -71
  54. package/dist/local/storage.d.cts +0 -7
  55. package/dist/local/storage.d.mts +0 -7
  56. package/dist/local/storage.mjs +0 -68
  57. package/dist/local/sync.cjs +0 -124
  58. package/dist/local/sync.d.cts +0 -36
  59. package/dist/local/sync.d.mts +0 -36
  60. package/dist/local/sync.mjs +0 -122
  61. package/dist/local/view.cjs +0 -257
  62. package/dist/local/view.d.cts +0 -24
  63. package/dist/local/view.d.mts +0 -24
  64. package/dist/local/view.mjs +0 -254
  65. package/dist/package.cjs +0 -11
  66. package/dist/package.mjs +0 -5
  67. package/dist/schema/index.cjs +0 -276
  68. package/dist/schema/index.d.cts +0 -207
  69. package/dist/schema/index.d.mts +0 -207
  70. package/dist/schema/index.mjs +0 -265
  71. package/dist/server/auth.cjs +0 -132
  72. package/dist/server/auth.d.cts +0 -49
  73. package/dist/server/auth.d.mts +0 -49
  74. package/dist/server/auth.mjs +0 -122
  75. package/dist/server/d1.cjs +0 -120
  76. package/dist/server/d1.mjs +0 -116
  77. package/dist/server/do.cjs +0 -132
  78. package/dist/server/do.d.cts +0 -21
  79. package/dist/server/do.d.mts +0 -21
  80. package/dist/server/do.mjs +0 -131
  81. package/dist/server/index.cjs +0 -355
  82. package/dist/server/index.d.cts +0 -65
  83. package/dist/server/index.d.mts +0 -65
  84. package/dist/server/index.mjs +0 -348
  85. package/dist/server/protect.cjs +0 -34
  86. package/dist/server/protect.d.cts +0 -32
  87. package/dist/server/protect.d.mts +0 -32
  88. package/dist/server/protect.mjs +0 -33
  89. package/dist/server/r2.cjs +0 -58
  90. package/dist/server/r2.d.cts +0 -4
  91. package/dist/server/r2.d.mts +0 -4
  92. package/dist/server/r2.mjs +0 -53
@@ -1,50 +0,0 @@
1
- import { MergeFn, SyncAdapter, SyncPayload } from "../sync.cjs";
2
- import { SQLiteDatabase } from "expo-sqlite";
3
-
4
- //#region src/local/adapters/cloudflare.d.ts
5
- type CloudflareAdapterOptions = {
6
- url: string;
7
- getToken?: () => Promise<string | null>;
8
- db: SQLiteDatabase;
9
- subscribers: Map<string, {
10
- update: () => void;
11
- }>;
12
- merge?: MergeFn;
13
- };
14
- declare class CloudflareSyncAdapter extends SyncAdapter {
15
- private url;
16
- private getToken?;
17
- private db;
18
- private subscribers;
19
- private ws;
20
- private receiveHandler?;
21
- private reconnectTimer;
22
- private backoff;
23
- private alive;
24
- private registeredViews;
25
- private failureCount;
26
- private firstFailureAt;
27
- private blocked;
28
- private warned;
29
- private ignoreClose;
30
- private pendingCommits;
31
- constructor(options: CloudflareAdapterOptions);
32
- /** Register the view names this adapter should subscribe to on connect. */
33
- registerViews(names: string[]): void;
34
- connect(): Promise<void>;
35
- private handleMessage;
36
- private scheduleReconnect;
37
- private recordFailure;
38
- resetConnection(): void;
39
- send(payload: SyncPayload): Promise<void>;
40
- onReceive(handler: (payload: SyncPayload) => Promise<void>): void;
41
- fetchInitialState(): Promise<SyncPayload | null>;
42
- disconnect(): void;
43
- /**
44
- * Reset backoff and force an immediate reconnect.
45
- * Used after token changes (e.g. elevation from anonymous to authenticated).
46
- */
47
- forceReconnect(): void;
48
- }
49
- //#endregion
50
- export { CloudflareSyncAdapter };
@@ -1,50 +0,0 @@
1
- import { MergeFn, SyncAdapter, SyncPayload } from "../sync.mjs";
2
- import { SQLiteDatabase } from "expo-sqlite";
3
-
4
- //#region src/local/adapters/cloudflare.d.ts
5
- type CloudflareAdapterOptions = {
6
- url: string;
7
- getToken?: () => Promise<string | null>;
8
- db: SQLiteDatabase;
9
- subscribers: Map<string, {
10
- update: () => void;
11
- }>;
12
- merge?: MergeFn;
13
- };
14
- declare class CloudflareSyncAdapter extends SyncAdapter {
15
- private url;
16
- private getToken?;
17
- private db;
18
- private subscribers;
19
- private ws;
20
- private receiveHandler?;
21
- private reconnectTimer;
22
- private backoff;
23
- private alive;
24
- private registeredViews;
25
- private failureCount;
26
- private firstFailureAt;
27
- private blocked;
28
- private warned;
29
- private ignoreClose;
30
- private pendingCommits;
31
- constructor(options: CloudflareAdapterOptions);
32
- /** Register the view names this adapter should subscribe to on connect. */
33
- registerViews(names: string[]): void;
34
- connect(): Promise<void>;
35
- private handleMessage;
36
- private scheduleReconnect;
37
- private recordFailure;
38
- resetConnection(): void;
39
- send(payload: SyncPayload): Promise<void>;
40
- onReceive(handler: (payload: SyncPayload) => Promise<void>): void;
41
- fetchInitialState(): Promise<SyncPayload | null>;
42
- disconnect(): void;
43
- /**
44
- * Reset backoff and force an immediate reconnect.
45
- * Used after token changes (e.g. elevation from anonymous to authenticated).
46
- */
47
- forceReconnect(): void;
48
- }
49
- //#endregion
50
- export { CloudflareSyncAdapter };
@@ -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,7 +0,0 @@
1
- import { AuthState } from "./auth.cjs";
2
- import "react";
3
-
4
- //#region src/local/auth-context.d.ts
5
- declare function useAuth(): AuthState;
6
- //#endregion
7
- export { useAuth };
@@ -1,7 +0,0 @@
1
- import { AuthState } from "./auth.mjs";
2
- import "react";
3
-
4
- //#region src/local/auth-context.d.ts
5
- declare function useAuth(): AuthState;
6
- //#endregion
7
- export { 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 };
@@ -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;
@@ -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 };
@@ -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 };
@@ -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 };