@reifydb/auth 0.9.0 → 0.9.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/index.d.ts +11 -10
- package/dist/index.js +148 -127
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -8,9 +8,9 @@ type AuthStatus = "disconnected" | "verifying" | "signing" | "authenticated" | "
|
|
|
8
8
|
interface AuthSession {
|
|
9
9
|
readonly token: string;
|
|
10
10
|
readonly identity: string;
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
13
|
-
readonly method?: "wallet" | "password";
|
|
11
|
+
readonly walletAddress: string;
|
|
12
|
+
readonly expiresAt: number;
|
|
13
|
+
readonly method?: "wallet" | "password" | "token";
|
|
14
14
|
readonly identifier?: string;
|
|
15
15
|
}
|
|
16
16
|
interface PasswordCredentials {
|
|
@@ -32,11 +32,11 @@ interface WalletConnector {
|
|
|
32
32
|
encodeSignature(bytes: Uint8Array): string;
|
|
33
33
|
}
|
|
34
34
|
interface AuthCapableClient {
|
|
35
|
-
|
|
35
|
+
loginChallenge(method: string, credentials: Record<string, string>): Promise<LoginChallengeResult>;
|
|
36
36
|
logout(): Promise<void>;
|
|
37
37
|
}
|
|
38
38
|
interface CredentialAuthCapableClient extends AuthCapableClient {
|
|
39
|
-
|
|
39
|
+
loginWithPassword(identifier: string, password: string): Promise<LoginResult>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
interface AuthTransport<TClient extends AuthCapableClient = AuthCapableClient> {
|
|
@@ -44,13 +44,14 @@ interface AuthTransport<TClient extends AuthCapableClient = AuthCapableClient> {
|
|
|
44
44
|
connect(url: string, token?: string): Promise<TClient>;
|
|
45
45
|
release(client: TClient): void;
|
|
46
46
|
}
|
|
47
|
-
declare const
|
|
48
|
-
declare const
|
|
49
|
-
declare const
|
|
50
|
-
declare const
|
|
47
|
+
declare const wsTransport: AuthTransport<WsClient>;
|
|
48
|
+
declare const httpTransport: AuthTransport<HttpClient>;
|
|
49
|
+
declare const jsonWsTransport: AuthTransport<JsonWsClient>;
|
|
50
|
+
declare const jsonHttpTransport: AuthTransport<JsonHttpClient>;
|
|
51
51
|
|
|
52
52
|
interface AuthContextValue extends AuthState {
|
|
53
53
|
signIn(credentials?: PasswordCredentials): Promise<void>;
|
|
54
|
+
adoptSession(session: AuthSession): void;
|
|
54
55
|
signOut(): Promise<void>;
|
|
55
56
|
}
|
|
56
57
|
declare const AuthContext: React.Context<AuthContextValue | null>;
|
|
@@ -100,4 +101,4 @@ declare function ensureClient<T extends AuthCapableClient>(transport: AuthTransp
|
|
|
100
101
|
declare function clearClient(): void;
|
|
101
102
|
declare function currentClient<T extends AuthCapableClient = AuthCapableClient>(): T;
|
|
102
103
|
|
|
103
|
-
export { type AuthCapableClient, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthSession, type AuthState, type AuthStatus, type AuthTransport, type CredentialAuthCapableClient, type PasswordCredentials, type PasswordSignInArgs, type SignInArgs, type WalletConnector, clearClient, clearStoredSession, currentClient, ensureClient,
|
|
104
|
+
export { type AuthCapableClient, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthSession, type AuthState, type AuthStatus, type AuthTransport, type CredentialAuthCapableClient, type PasswordCredentials, type PasswordSignInArgs, type SignInArgs, type WalletConnector, clearClient, clearStoredSession, currentClient, ensureClient, httpTransport, jsonHttpTransport, jsonWsTransport, performPasswordSignIn, performSignIn, readStoredSession, storageKeyFor, useAuth, useAuthClient, writeStoredSession, wsTransport };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Client
|
|
4
4
|
} from "@reifydb/client";
|
|
5
|
-
function
|
|
5
|
+
function releaseWithDisconnect(client) {
|
|
6
6
|
if (typeof client.disconnect === "function") {
|
|
7
7
|
try {
|
|
8
8
|
client.disconnect();
|
|
@@ -10,22 +10,22 @@ function release_with_disconnect(client) {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
var
|
|
13
|
+
var wsTransport = {
|
|
14
14
|
kind: "ws",
|
|
15
15
|
async connect(url, token) {
|
|
16
|
-
return Client.
|
|
16
|
+
return Client.connectWs(
|
|
17
17
|
url,
|
|
18
18
|
token != null ? { format: "rbcf", token } : { format: "rbcf" }
|
|
19
19
|
);
|
|
20
20
|
},
|
|
21
21
|
release(client) {
|
|
22
|
-
|
|
22
|
+
releaseWithDisconnect(client);
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
-
var
|
|
25
|
+
var httpTransport = {
|
|
26
26
|
kind: "http",
|
|
27
27
|
async connect(url, token) {
|
|
28
|
-
return Client.
|
|
28
|
+
return Client.connectHttp(
|
|
29
29
|
url,
|
|
30
30
|
token != null ? { format: "rbcf", token } : { format: "rbcf" }
|
|
31
31
|
);
|
|
@@ -33,19 +33,19 @@ var http_transport = {
|
|
|
33
33
|
release(_client) {
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
|
-
var
|
|
36
|
+
var jsonWsTransport = {
|
|
37
37
|
kind: "ws",
|
|
38
38
|
async connect(url, token) {
|
|
39
|
-
return Client.
|
|
39
|
+
return Client.connectJsonWs(url, token != null ? { token } : void 0);
|
|
40
40
|
},
|
|
41
41
|
release(client) {
|
|
42
|
-
|
|
42
|
+
releaseWithDisconnect(client);
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
var
|
|
45
|
+
var jsonHttpTransport = {
|
|
46
46
|
kind: "http",
|
|
47
47
|
async connect(url, token) {
|
|
48
|
-
return Client.
|
|
48
|
+
return Client.connectJsonHttp(url, token != null ? { token } : void 0);
|
|
49
49
|
},
|
|
50
50
|
release(_client) {
|
|
51
51
|
}
|
|
@@ -62,67 +62,67 @@ import {
|
|
|
62
62
|
} from "react";
|
|
63
63
|
|
|
64
64
|
// src/client-cache.ts
|
|
65
|
-
var
|
|
66
|
-
var
|
|
67
|
-
var
|
|
68
|
-
var
|
|
69
|
-
function
|
|
65
|
+
var currentKey = null;
|
|
66
|
+
var cachedClient = null;
|
|
67
|
+
var currentTransport = null;
|
|
68
|
+
var pendingPromise = null;
|
|
69
|
+
function keyOf(kind, url, token) {
|
|
70
70
|
return `${kind}|${url}|${token}`;
|
|
71
71
|
}
|
|
72
72
|
async function ensureClient(transport, url, token) {
|
|
73
|
-
const key =
|
|
74
|
-
if (
|
|
75
|
-
if (
|
|
76
|
-
if (
|
|
73
|
+
const key = keyOf(transport.kind, url, token);
|
|
74
|
+
if (currentKey === key) {
|
|
75
|
+
if (cachedClient) return cachedClient;
|
|
76
|
+
if (pendingPromise) return pendingPromise;
|
|
77
77
|
}
|
|
78
|
-
if (
|
|
78
|
+
if (cachedClient && currentTransport) {
|
|
79
79
|
try {
|
|
80
|
-
|
|
80
|
+
currentTransport.release(cachedClient);
|
|
81
81
|
} catch {
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
cachedClient = null;
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
currentKey = key;
|
|
86
|
+
currentTransport = transport;
|
|
87
87
|
const p = transport.connect(url, token).then((client) => {
|
|
88
|
-
if (
|
|
88
|
+
if (currentKey !== key) {
|
|
89
89
|
try {
|
|
90
90
|
transport.release(client);
|
|
91
91
|
} catch {
|
|
92
92
|
}
|
|
93
93
|
throw new Error("@reifydb/auth: client connect superseded");
|
|
94
94
|
}
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
cachedClient = client;
|
|
96
|
+
pendingPromise = null;
|
|
97
97
|
return client;
|
|
98
98
|
});
|
|
99
|
-
|
|
99
|
+
pendingPromise = p;
|
|
100
100
|
return p;
|
|
101
101
|
}
|
|
102
102
|
function clearClient() {
|
|
103
|
-
if (
|
|
103
|
+
if (cachedClient && currentTransport) {
|
|
104
104
|
try {
|
|
105
|
-
|
|
105
|
+
currentTransport.release(cachedClient);
|
|
106
106
|
} catch {
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
109
|
+
currentKey = null;
|
|
110
|
+
cachedClient = null;
|
|
111
|
+
currentTransport = null;
|
|
112
|
+
pendingPromise = null;
|
|
113
113
|
}
|
|
114
114
|
function currentClient() {
|
|
115
|
-
if (!
|
|
115
|
+
if (!cachedClient) {
|
|
116
116
|
throw new Error("@reifydb/auth: no authenticated client; call ensureClient first");
|
|
117
117
|
}
|
|
118
|
-
return
|
|
118
|
+
return cachedClient;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// src/sign-in.ts
|
|
122
122
|
async function performSignIn(args) {
|
|
123
123
|
const { url, transport, method, wallet, domain, statement, sessionTtlSeconds } = args;
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
124
|
+
const walletAddress = wallet.publicKey;
|
|
125
|
+
if (walletAddress == null || walletAddress.length === 0) {
|
|
126
126
|
throw new Error("@reifydb/auth: wallet.publicKey is required to sign in");
|
|
127
127
|
}
|
|
128
128
|
if (!Number.isFinite(sessionTtlSeconds) || sessionTtlSeconds <= 0) {
|
|
@@ -130,9 +130,9 @@ async function performSignIn(args) {
|
|
|
130
130
|
}
|
|
131
131
|
const client = await transport.connect(url);
|
|
132
132
|
try {
|
|
133
|
-
const challenge = await client.
|
|
134
|
-
identifier:
|
|
135
|
-
public_key:
|
|
133
|
+
const challenge = await client.loginChallenge(method, {
|
|
134
|
+
identifier: walletAddress,
|
|
135
|
+
public_key: walletAddress,
|
|
136
136
|
domain,
|
|
137
137
|
statement
|
|
138
138
|
});
|
|
@@ -144,8 +144,8 @@ async function performSignIn(args) {
|
|
|
144
144
|
const messageBytes = new TextEncoder().encode(challenge.message);
|
|
145
145
|
const signatureBytes = await wallet.signMessage(messageBytes);
|
|
146
146
|
const signature = wallet.encodeSignature(signatureBytes);
|
|
147
|
-
const auth = await client.
|
|
148
|
-
challenge_id: challenge.
|
|
147
|
+
const auth = await client.loginChallenge(method, {
|
|
148
|
+
challenge_id: challenge.challengeId,
|
|
149
149
|
signature,
|
|
150
150
|
signed_message: challenge.message
|
|
151
151
|
});
|
|
@@ -157,8 +157,8 @@ async function performSignIn(args) {
|
|
|
157
157
|
return {
|
|
158
158
|
token: auth.token,
|
|
159
159
|
identity: auth.identity,
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
walletAddress,
|
|
161
|
+
expiresAt: Math.floor(Date.now() / 1e3) + sessionTtlSeconds
|
|
162
162
|
};
|
|
163
163
|
} finally {
|
|
164
164
|
transport.release(client);
|
|
@@ -166,8 +166,8 @@ async function performSignIn(args) {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// src/sign-in-password.ts
|
|
169
|
-
function
|
|
170
|
-
return typeof client.
|
|
169
|
+
function supportsPasswordLogin(client) {
|
|
170
|
+
return typeof client.loginWithPassword === "function";
|
|
171
171
|
}
|
|
172
172
|
async function performPasswordSignIn(args) {
|
|
173
173
|
const { url, transport, identifier, password, sessionTtlSeconds } = args;
|
|
@@ -182,19 +182,19 @@ async function performPasswordSignIn(args) {
|
|
|
182
182
|
}
|
|
183
183
|
const client = await transport.connect(url);
|
|
184
184
|
try {
|
|
185
|
-
if (!
|
|
185
|
+
if (!supportsPasswordLogin(client)) {
|
|
186
186
|
throw new Error(
|
|
187
|
-
"@reifydb/auth: transport client does not support
|
|
187
|
+
"@reifydb/auth: transport client does not support loginWithPassword"
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
|
-
const auth = await client.
|
|
190
|
+
const auth = await client.loginWithPassword(identifier, password);
|
|
191
191
|
return {
|
|
192
192
|
token: auth.token,
|
|
193
193
|
identity: auth.identity,
|
|
194
|
-
|
|
194
|
+
walletAddress: identifier,
|
|
195
195
|
identifier,
|
|
196
196
|
method: "password",
|
|
197
|
-
|
|
197
|
+
expiresAt: Math.floor(Date.now() / 1e3) + sessionTtlSeconds
|
|
198
198
|
};
|
|
199
199
|
} finally {
|
|
200
200
|
transport.release(client);
|
|
@@ -203,11 +203,11 @@ async function performPasswordSignIn(args) {
|
|
|
203
203
|
|
|
204
204
|
// src/storage.ts
|
|
205
205
|
var SUFFIX = ".auth";
|
|
206
|
-
function
|
|
206
|
+
function keyFor(namespace) {
|
|
207
207
|
return `${namespace}${SUFFIX}`;
|
|
208
208
|
}
|
|
209
209
|
var TAB_ID_KEY = "reifydb.auth.tab";
|
|
210
|
-
function
|
|
210
|
+
function newTabId() {
|
|
211
211
|
try {
|
|
212
212
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
213
213
|
return crypto.randomUUID();
|
|
@@ -216,36 +216,36 @@ function new_tab_id() {
|
|
|
216
216
|
}
|
|
217
217
|
return `t-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
218
218
|
}
|
|
219
|
-
function
|
|
219
|
+
function resolveTabId() {
|
|
220
220
|
if (typeof window === "undefined") return "ssr";
|
|
221
221
|
try {
|
|
222
222
|
const existing = sessionStorage.getItem(TAB_ID_KEY);
|
|
223
223
|
if (existing) return existing;
|
|
224
|
-
const id =
|
|
224
|
+
const id = newTabId();
|
|
225
225
|
sessionStorage.setItem(TAB_ID_KEY, id);
|
|
226
226
|
return id;
|
|
227
227
|
} catch {
|
|
228
|
-
return
|
|
228
|
+
return newTabId();
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
-
var TAB_ID =
|
|
231
|
+
var TAB_ID = resolveTabId();
|
|
232
232
|
function tabScopedNamespace(namespace) {
|
|
233
233
|
return `${namespace}.${TAB_ID}`;
|
|
234
234
|
}
|
|
235
|
-
function
|
|
235
|
+
function isAuthSession(v) {
|
|
236
236
|
if (v === null || typeof v !== "object") return false;
|
|
237
237
|
const o = v;
|
|
238
|
-
if (o.method !== void 0 && o.method !== "wallet" && o.method !== "password") {
|
|
238
|
+
if (o.method !== void 0 && o.method !== "wallet" && o.method !== "password" && o.method !== "token") {
|
|
239
239
|
return false;
|
|
240
240
|
}
|
|
241
241
|
if (o.identifier !== void 0 && typeof o.identifier !== "string") {
|
|
242
242
|
return false;
|
|
243
243
|
}
|
|
244
|
-
return typeof o.token === "string" && o.token.length > 0 && typeof o.identity === "string" && o.identity.length > 0 && typeof o.
|
|
244
|
+
return typeof o.token === "string" && o.token.length > 0 && typeof o.identity === "string" && o.identity.length > 0 && typeof o.walletAddress === "string" && o.walletAddress.length > 0 && typeof o.expiresAt === "number" && Number.isFinite(o.expiresAt) && o.expiresAt > 0;
|
|
245
245
|
}
|
|
246
|
-
function
|
|
246
|
+
function safeRemove(namespace) {
|
|
247
247
|
try {
|
|
248
|
-
localStorage.removeItem(
|
|
248
|
+
localStorage.removeItem(keyFor(namespace));
|
|
249
249
|
} catch {
|
|
250
250
|
}
|
|
251
251
|
}
|
|
@@ -253,7 +253,7 @@ function readStoredSession(namespace) {
|
|
|
253
253
|
if (typeof window === "undefined") return null;
|
|
254
254
|
let raw;
|
|
255
255
|
try {
|
|
256
|
-
raw = localStorage.getItem(
|
|
256
|
+
raw = localStorage.getItem(keyFor(namespace));
|
|
257
257
|
} catch {
|
|
258
258
|
return null;
|
|
259
259
|
}
|
|
@@ -262,46 +262,46 @@ function readStoredSession(namespace) {
|
|
|
262
262
|
try {
|
|
263
263
|
parsed = JSON.parse(raw);
|
|
264
264
|
} catch {
|
|
265
|
-
|
|
265
|
+
safeRemove(namespace);
|
|
266
266
|
return null;
|
|
267
267
|
}
|
|
268
|
-
if (!
|
|
269
|
-
|
|
268
|
+
if (!isAuthSession(parsed)) {
|
|
269
|
+
safeRemove(namespace);
|
|
270
270
|
return null;
|
|
271
271
|
}
|
|
272
|
-
if (parsed.
|
|
273
|
-
|
|
272
|
+
if (parsed.expiresAt <= Date.now() / 1e3) {
|
|
273
|
+
safeRemove(namespace);
|
|
274
274
|
return null;
|
|
275
275
|
}
|
|
276
276
|
return parsed;
|
|
277
277
|
}
|
|
278
278
|
function writeStoredSession(namespace, session) {
|
|
279
279
|
if (typeof window === "undefined") return;
|
|
280
|
-
if (!
|
|
280
|
+
if (!isAuthSession(session)) {
|
|
281
281
|
throw new Error("@reifydb/auth: refusing to persist malformed session");
|
|
282
282
|
}
|
|
283
283
|
try {
|
|
284
|
-
localStorage.setItem(
|
|
284
|
+
localStorage.setItem(keyFor(namespace), JSON.stringify(session));
|
|
285
285
|
} catch {
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
function clearStoredSession(namespace) {
|
|
289
289
|
if (typeof window === "undefined") return;
|
|
290
|
-
|
|
290
|
+
safeRemove(namespace);
|
|
291
291
|
}
|
|
292
292
|
function storageKeyFor(namespace) {
|
|
293
|
-
return
|
|
293
|
+
return keyFor(namespace);
|
|
294
294
|
}
|
|
295
295
|
function sweepExpiredSessions(baseNamespace) {
|
|
296
296
|
if (typeof window === "undefined") return;
|
|
297
297
|
try {
|
|
298
298
|
const now = Date.now() / 1e3;
|
|
299
|
-
const
|
|
299
|
+
const ownKey = keyFor(tabScopedNamespace(baseNamespace));
|
|
300
300
|
const prefix = `${baseNamespace}.`;
|
|
301
301
|
const dead = [];
|
|
302
302
|
for (let i = 0; i < localStorage.length; i += 1) {
|
|
303
303
|
const k = localStorage.key(i);
|
|
304
|
-
if (k == null || k ===
|
|
304
|
+
if (k == null || k === ownKey) continue;
|
|
305
305
|
if (!k.startsWith(prefix) || !k.endsWith(SUFFIX)) continue;
|
|
306
306
|
const raw = localStorage.getItem(k);
|
|
307
307
|
if (raw == null) continue;
|
|
@@ -311,7 +311,7 @@ function sweepExpiredSessions(baseNamespace) {
|
|
|
311
311
|
} catch {
|
|
312
312
|
continue;
|
|
313
313
|
}
|
|
314
|
-
if (
|
|
314
|
+
if (isAuthSession(parsed) && parsed.expiresAt <= now) {
|
|
315
315
|
dead.push(k);
|
|
316
316
|
}
|
|
317
317
|
}
|
|
@@ -337,31 +337,31 @@ function AuthProvider(props) {
|
|
|
337
337
|
sessionScope = "tab",
|
|
338
338
|
children
|
|
339
339
|
} = props;
|
|
340
|
-
const
|
|
340
|
+
const effectiveNamespace = sessionScope === "browser" ? storageNamespace : tabScopedNamespace(storageNamespace);
|
|
341
341
|
const [state, setState] = useState(() => {
|
|
342
|
-
const stored = readStoredSession(
|
|
342
|
+
const stored = readStoredSession(effectiveNamespace);
|
|
343
343
|
return stored ? { status: "verifying", session: stored, clientReady: false, error: null } : { status: "disconnected", session: null, clientReady: false, error: null };
|
|
344
344
|
});
|
|
345
|
-
const
|
|
346
|
-
const
|
|
347
|
-
const
|
|
348
|
-
const
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
const
|
|
354
|
-
(
|
|
355
|
-
clearStoredSession(
|
|
345
|
+
const walletConnected = wallet?.connected ?? false;
|
|
346
|
+
const walletConnecting = wallet?.connecting ?? false;
|
|
347
|
+
const walletPublicKey = wallet?.publicKey ?? null;
|
|
348
|
+
const walletHasSelected = wallet?.hasSelectedWallet ?? false;
|
|
349
|
+
const sessionRef = useRef(state.session);
|
|
350
|
+
sessionRef.current = state.session;
|
|
351
|
+
const walletRef = useRef(wallet);
|
|
352
|
+
walletRef.current = wallet;
|
|
353
|
+
const tearDown = useCallback(
|
|
354
|
+
(nextStatus, nextError) => {
|
|
355
|
+
clearStoredSession(effectiveNamespace);
|
|
356
356
|
clearClient();
|
|
357
357
|
setState({
|
|
358
|
-
status:
|
|
358
|
+
status: nextStatus,
|
|
359
359
|
session: null,
|
|
360
360
|
clientReady: false,
|
|
361
|
-
error:
|
|
361
|
+
error: nextError
|
|
362
362
|
});
|
|
363
363
|
},
|
|
364
|
-
[
|
|
364
|
+
[effectiveNamespace]
|
|
365
365
|
);
|
|
366
366
|
useEffect(() => {
|
|
367
367
|
const session = state.session;
|
|
@@ -376,66 +376,72 @@ function AuthProvider(props) {
|
|
|
376
376
|
}).catch((err) => {
|
|
377
377
|
if (cancelled) return;
|
|
378
378
|
const message = err instanceof Error ? err.message : "Failed to connect client";
|
|
379
|
-
|
|
379
|
+
console.error("DBG auth error: client connect", message, err);
|
|
380
|
+
tearDown("error", message);
|
|
380
381
|
});
|
|
381
382
|
return () => {
|
|
382
383
|
cancelled = true;
|
|
383
384
|
};
|
|
384
385
|
};
|
|
385
|
-
if (session.method
|
|
386
|
+
if (session.method != null && session.method !== "wallet") {
|
|
386
387
|
return establish();
|
|
387
388
|
}
|
|
388
|
-
if (
|
|
389
|
-
if (
|
|
390
|
-
|
|
389
|
+
if (walletConnected && walletPublicKey != null) {
|
|
390
|
+
if (walletPublicKey !== session.walletAddress) {
|
|
391
|
+
tearDown("disconnected", null);
|
|
391
392
|
return;
|
|
392
393
|
}
|
|
393
394
|
return establish();
|
|
394
395
|
}
|
|
395
|
-
if (!
|
|
396
|
+
if (!walletConnected && (walletConnecting || walletHasSelected)) {
|
|
396
397
|
setState(
|
|
397
398
|
(prev) => prev.session === session ? { ...prev, status: "verifying", clientReady: false } : prev
|
|
398
399
|
);
|
|
399
400
|
return;
|
|
400
401
|
}
|
|
401
|
-
|
|
402
|
+
tearDown("disconnected", null);
|
|
402
403
|
}, [
|
|
403
404
|
state.session,
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
405
|
+
walletConnected,
|
|
406
|
+
walletConnecting,
|
|
407
|
+
walletPublicKey,
|
|
408
|
+
walletHasSelected,
|
|
408
409
|
transport,
|
|
409
410
|
url,
|
|
410
|
-
|
|
411
|
+
tearDown
|
|
411
412
|
]);
|
|
412
413
|
useEffect(() => {
|
|
413
414
|
if (typeof window === "undefined") return;
|
|
414
|
-
const key = storageKeyFor(
|
|
415
|
-
const
|
|
415
|
+
const key = storageKeyFor(effectiveNamespace);
|
|
416
|
+
const onStorage = (e) => {
|
|
416
417
|
if (e.key !== key) return;
|
|
417
|
-
const current =
|
|
418
|
+
const current = sessionRef.current;
|
|
418
419
|
if (e.newValue == null) {
|
|
419
|
-
if (current != null)
|
|
420
|
+
if (current != null) tearDown("disconnected", null);
|
|
420
421
|
return;
|
|
421
422
|
}
|
|
422
423
|
let parsed;
|
|
423
424
|
try {
|
|
424
425
|
parsed = JSON.parse(e.newValue);
|
|
425
426
|
} catch {
|
|
426
|
-
if (current != null)
|
|
427
|
+
if (current != null) tearDown("disconnected", null);
|
|
427
428
|
return;
|
|
428
429
|
}
|
|
429
430
|
if (current == null) return;
|
|
430
|
-
if (parsed.
|
|
431
|
-
|
|
431
|
+
if (parsed.walletAddress !== current.walletAddress || parsed.identity !== current.identity) {
|
|
432
|
+
const followed = sessionScope === "browser" ? readStoredSession(effectiveNamespace) : null;
|
|
433
|
+
if (followed == null) {
|
|
434
|
+
tearDown("disconnected", null);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
setState({ status: "verifying", session: followed, clientReady: false, error: null });
|
|
432
438
|
}
|
|
433
439
|
};
|
|
434
|
-
window.addEventListener("storage",
|
|
440
|
+
window.addEventListener("storage", onStorage);
|
|
435
441
|
return () => {
|
|
436
|
-
window.removeEventListener("storage",
|
|
442
|
+
window.removeEventListener("storage", onStorage);
|
|
437
443
|
};
|
|
438
|
-
}, [
|
|
444
|
+
}, [effectiveNamespace, sessionScope, tearDown]);
|
|
439
445
|
useEffect(() => {
|
|
440
446
|
sweepExpiredSessions(storageNamespace);
|
|
441
447
|
}, [storageNamespace]);
|
|
@@ -450,7 +456,7 @@ function AuthProvider(props) {
|
|
|
450
456
|
password: credentials.password,
|
|
451
457
|
sessionTtlSeconds
|
|
452
458
|
});
|
|
453
|
-
writeStoredSession(
|
|
459
|
+
writeStoredSession(effectiveNamespace, session);
|
|
454
460
|
setState({
|
|
455
461
|
status: "verifying",
|
|
456
462
|
session,
|
|
@@ -468,8 +474,9 @@ function AuthProvider(props) {
|
|
|
468
474
|
}
|
|
469
475
|
return;
|
|
470
476
|
}
|
|
471
|
-
const w =
|
|
477
|
+
const w = walletRef.current;
|
|
472
478
|
if (w == null || !w.connected || w.publicKey == null) {
|
|
479
|
+
console.error("DBG auth error: wallet not connected");
|
|
473
480
|
setState((prev) => ({ ...prev, status: "error", error: "Wallet not connected" }));
|
|
474
481
|
return;
|
|
475
482
|
}
|
|
@@ -492,10 +499,10 @@ function AuthProvider(props) {
|
|
|
492
499
|
statement,
|
|
493
500
|
sessionTtlSeconds
|
|
494
501
|
});
|
|
495
|
-
if (session.
|
|
502
|
+
if (session.walletAddress !== walletRef.current?.publicKey) {
|
|
496
503
|
throw new Error("Wallet changed during sign in");
|
|
497
504
|
}
|
|
498
|
-
writeStoredSession(
|
|
505
|
+
writeStoredSession(effectiveNamespace, session);
|
|
499
506
|
setState({
|
|
500
507
|
status: "verifying",
|
|
501
508
|
session,
|
|
@@ -504,6 +511,7 @@ function AuthProvider(props) {
|
|
|
504
511
|
});
|
|
505
512
|
} catch (err) {
|
|
506
513
|
const message = err instanceof Error ? err.message : "Sign in failed";
|
|
514
|
+
console.error("DBG auth error: wallet sign in", message, err);
|
|
507
515
|
setState({
|
|
508
516
|
status: "error",
|
|
509
517
|
session: null,
|
|
@@ -518,15 +526,27 @@ function AuthProvider(props) {
|
|
|
518
526
|
domain,
|
|
519
527
|
statement,
|
|
520
528
|
sessionTtlSeconds,
|
|
521
|
-
|
|
529
|
+
effectiveNamespace
|
|
522
530
|
]);
|
|
531
|
+
const adoptSession = useCallback(
|
|
532
|
+
(session) => {
|
|
533
|
+
writeStoredSession(effectiveNamespace, session);
|
|
534
|
+
setState({
|
|
535
|
+
status: "verifying",
|
|
536
|
+
session,
|
|
537
|
+
clientReady: false,
|
|
538
|
+
error: null
|
|
539
|
+
});
|
|
540
|
+
},
|
|
541
|
+
[effectiveNamespace]
|
|
542
|
+
);
|
|
523
543
|
const signOut = useCallback(async () => {
|
|
524
544
|
try {
|
|
525
545
|
await currentClient().logout();
|
|
526
546
|
} catch {
|
|
527
547
|
}
|
|
528
|
-
|
|
529
|
-
}, [
|
|
548
|
+
tearDown("disconnected", null);
|
|
549
|
+
}, [tearDown]);
|
|
530
550
|
const value = useMemo(
|
|
531
551
|
() => ({
|
|
532
552
|
status: state.status,
|
|
@@ -534,9 +554,10 @@ function AuthProvider(props) {
|
|
|
534
554
|
clientReady: state.clientReady,
|
|
535
555
|
error: state.error,
|
|
536
556
|
signIn,
|
|
557
|
+
adoptSession,
|
|
537
558
|
signOut
|
|
538
559
|
}),
|
|
539
|
-
[state, signIn, signOut]
|
|
560
|
+
[state, signIn, adoptSession, signOut]
|
|
540
561
|
);
|
|
541
562
|
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
|
|
542
563
|
}
|
|
@@ -568,9 +589,9 @@ export {
|
|
|
568
589
|
clearStoredSession,
|
|
569
590
|
currentClient,
|
|
570
591
|
ensureClient,
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
592
|
+
httpTransport,
|
|
593
|
+
jsonHttpTransport,
|
|
594
|
+
jsonWsTransport,
|
|
574
595
|
performPasswordSignIn,
|
|
575
596
|
performSignIn,
|
|
576
597
|
readStoredSession,
|
|
@@ -578,6 +599,6 @@ export {
|
|
|
578
599
|
useAuth,
|
|
579
600
|
useAuthClient,
|
|
580
601
|
writeStoredSession,
|
|
581
|
-
|
|
602
|
+
wsTransport
|
|
582
603
|
};
|
|
583
604
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transport.ts","../src/auth-provider.tsx","../src/client-cache.ts","../src/sign-in.ts","../src/sign-in-password.ts","../src/storage.ts","../src/use-auth.ts","../src/index.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport {\n Client,\n type WsClient,\n type HttpClient,\n type JsonWsClient,\n type JsonHttpClient,\n} from \"@reifydb/client\";\nimport type { AuthCapableClient } from \"./types\";\n\nexport interface AuthTransport<\n TClient extends AuthCapableClient = AuthCapableClient,\n> {\n readonly kind: \"ws\" | \"http\";\n connect(url: string, token?: string): Promise<TClient>;\n release(client: TClient): void;\n}\n\nfunction release_with_disconnect(client: { disconnect?: () => void }): void {\n if (typeof client.disconnect === \"function\") {\n try {\n client.disconnect();\n } catch {\n // disconnect should be idempotent and never throw, but guard anyway\n }\n }\n}\n\nexport const ws_transport: AuthTransport<WsClient> = {\n kind: \"ws\",\n async connect(url, token) {\n return Client.connect_ws(\n url,\n token != null ? { format: \"rbcf\", token } : { format: \"rbcf\" },\n );\n },\n release(client) {\n release_with_disconnect(client);\n },\n};\n\nexport const http_transport: AuthTransport<HttpClient> = {\n kind: \"http\",\n async connect(url, token) {\n return Client.connect_http(\n url,\n token != null ? { format: \"rbcf\", token } : { format: \"rbcf\" },\n );\n },\n release(_client) {\n // HttpClient has no persistent socket; nothing to release.\n },\n};\n\nexport const json_ws_transport: AuthTransport<JsonWsClient> = {\n kind: \"ws\",\n async connect(url, token) {\n return Client.connect_json_ws(url, token != null ? { token } : undefined);\n },\n release(client) {\n release_with_disconnect(client);\n },\n};\n\nexport const json_http_transport: AuthTransport<JsonHttpClient> = {\n kind: \"http\",\n async connect(url, token) {\n return Client.connect_json_http(url, token != null ? { token } : undefined);\n },\n release(_client) {\n // JsonHttpClient has no persistent socket; nothing to release.\n },\n};\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport { clearClient, currentClient, ensureClient } from \"./client-cache\";\nimport { performSignIn } from \"./sign-in\";\nimport { performPasswordSignIn } from \"./sign-in-password\";\nimport {\n clearStoredSession,\n readStoredSession,\n storageKeyFor,\n sweepExpiredSessions,\n tabScopedNamespace,\n writeStoredSession,\n} from \"./storage\";\nimport type {\n AuthCapableClient,\n AuthSession,\n AuthState,\n PasswordCredentials,\n WalletConnector,\n} from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\nconst DEFAULT_TTL_SECONDS = 86400;\n\nexport interface AuthContextValue extends AuthState {\n signIn(credentials?: PasswordCredentials): Promise<void>;\n signOut(): Promise<void>;\n}\n\nexport const AuthContext = createContext<AuthContextValue | null>(null);\n\nexport interface AuthProviderProps<\n TClient extends AuthCapableClient = AuthCapableClient,\n> {\n url: string;\n transport: AuthTransport<TClient>;\n storageNamespace: string;\n method?: string;\n domain?: string;\n statement?: string;\n sessionTtlSeconds?: number;\n wallet?: WalletConnector;\n sessionScope?: \"tab\" | \"browser\";\n children: ReactNode;\n}\n\ninterface InternalState {\n status: AuthState[\"status\"];\n session: AuthSession | null;\n clientReady: boolean;\n error: string | null;\n}\n\nexport function AuthProvider<TClient extends AuthCapableClient>(\n props: AuthProviderProps<TClient>,\n): ReactElement {\n const {\n url,\n transport,\n storageNamespace,\n method,\n domain,\n statement,\n sessionTtlSeconds = DEFAULT_TTL_SECONDS,\n wallet,\n sessionScope = \"tab\",\n children,\n } = props;\n\n // Per-tab storage slot: each tab gets its own localStorage key so concurrent\n // sign-ins in different tabs cannot stomp each other's session. With\n // sessionScope \"browser\" all tabs deliberately share one slot instead.\n const effective_namespace =\n sessionScope === \"browser\"\n ? storageNamespace\n : tabScopedNamespace(storageNamespace);\n\n const [state, setState] = useState<InternalState>(() => {\n const stored = readStoredSession(effective_namespace);\n return stored\n ? { status: \"verifying\", session: stored, clientReady: false, error: null }\n : { status: \"disconnected\", session: null, clientReady: false, error: null };\n });\n\n // Pull live wallet fields into stable primitives for effect deps.\n const wallet_connected = wallet?.connected ?? false;\n const wallet_connecting = wallet?.connecting ?? false;\n const wallet_public_key = wallet?.publicKey ?? null;\n const wallet_has_selected = wallet?.hasSelectedWallet ?? false;\n\n // Refs so callbacks can read latest values without re-binding.\n const session_ref = useRef(state.session);\n session_ref.current = state.session;\n const wallet_ref = useRef(wallet);\n wallet_ref.current = wallet;\n\n const tear_down = useCallback(\n (next_status: InternalState[\"status\"], next_error: string | null) => {\n clearStoredSession(effective_namespace);\n clearClient();\n setState({\n status: next_status,\n session: null,\n clientReady: false,\n error: next_error,\n });\n },\n [effective_namespace],\n );\n\n // Session gate. Password sessions connect directly; wallet sessions keep the\n // security invariant: the authenticated client is only ever constructed when\n // the connected wallet matches the persisted session.\n useEffect(() => {\n const session = state.session;\n if (session == null) return;\n\n const establish = () => {\n let cancelled = false;\n ensureClient(transport, url, session.token)\n .then(() => {\n if (cancelled) return;\n setState((prev) =>\n prev.session === session\n ? { ...prev, status: \"authenticated\", clientReady: true, error: null }\n : prev,\n );\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n const message = err instanceof Error ? err.message : \"Failed to connect client\";\n tear_down(\"error\", message);\n });\n return () => {\n cancelled = true;\n };\n };\n\n if (session.method === \"password\") {\n return establish();\n }\n\n if (wallet_connected && wallet_public_key != null) {\n if (wallet_public_key !== session.wallet_address) {\n tear_down(\"disconnected\", null);\n return;\n }\n return establish();\n }\n\n if (!wallet_connected && (wallet_connecting || wallet_has_selected)) {\n // Wallet adapter is autoConnecting; stay in verifying. Do NOT construct\n // the client yet - we must not authenticate before the match is confirmed.\n setState((prev) =>\n prev.session === session\n ? { ...prev, status: \"verifying\", clientReady: false }\n : prev,\n );\n return;\n }\n\n // Wallet is definitively absent (no selected wallet, not connecting). User\n // explicitly disconnected, so the session can no longer be proven; tear down.\n tear_down(\"disconnected\", null);\n }, [\n state.session,\n wallet_connected,\n wallet_connecting,\n wallet_public_key,\n wallet_has_selected,\n transport,\n url,\n tear_down,\n ]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const key = storageKeyFor(effective_namespace);\n const on_storage = (e: StorageEvent) => {\n if (e.key !== key) return;\n const current = session_ref.current;\n\n // Another tab signed out / cleared the session.\n if (e.newValue == null) {\n if (current != null) tear_down(\"disconnected\", null);\n return;\n }\n\n let parsed: Partial<AuthSession>;\n try {\n parsed = JSON.parse(e.newValue) as Partial<AuthSession>;\n } catch {\n // Corrupt entry written by another tab. Only react if we actually hold\n // a session; otherwise there is nothing to defend.\n if (current != null) tear_down(\"disconnected\", null);\n return;\n }\n\n // We hold no session of our own: nothing to defend. Clearing storage here\n // would clobber the session the other tab just wrote (and bounce it back\n // out through this same handler). Let our own sign-in / autoConnect flow\n // converge independently.\n if (current == null) return;\n\n // A genuinely different principal took over our storage slot.\n if (\n parsed.wallet_address !== current.wallet_address ||\n parsed.identity !== current.identity\n ) {\n tear_down(\"disconnected\", null);\n }\n\n // Same principal, different token: a concurrent sign-in in another tab,\n // not an intrusion. Keep our own still-valid client.\n };\n window.addEventListener(\"storage\", on_storage);\n return () => {\n window.removeEventListener(\"storage\", on_storage);\n };\n }, [effective_namespace, tear_down]);\n\n // Housekeeping: drop expired per-tab slots left behind by closed tabs.\n useEffect(() => {\n sweepExpiredSessions(storageNamespace);\n }, [storageNamespace]);\n\n const signIn = useCallback(async (credentials?: PasswordCredentials) => {\n if (credentials != null) {\n setState((prev) => ({ ...prev, status: \"signing\", error: null }));\n try {\n const session = await performPasswordSignIn({\n url,\n transport,\n identifier: credentials.identifier,\n password: credentials.password,\n sessionTtlSeconds,\n });\n writeStoredSession(effective_namespace, session);\n setState({\n status: \"verifying\",\n session,\n clientReady: false,\n error: null,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Sign in failed\";\n setState({\n status: \"error\",\n session: null,\n clientReady: false,\n error: message,\n });\n }\n return;\n }\n\n const w = wallet_ref.current;\n if (w == null || !w.connected || w.publicKey == null) {\n setState((prev) => ({ ...prev, status: \"error\", error: \"Wallet not connected\" }));\n return;\n }\n if (method == null || domain == null || statement == null) {\n setState((prev) => ({\n ...prev,\n status: \"error\",\n error: \"Wallet sign in requires method, domain, and statement\",\n }));\n return;\n }\n setState((prev) => ({ ...prev, status: \"signing\", error: null }));\n try {\n const session = await performSignIn({\n url,\n transport,\n method,\n wallet: w,\n domain,\n statement,\n sessionTtlSeconds,\n });\n // Sanity: signed-in wallet must match the live publicKey. If the user\n // swapped wallets while the signature was in flight, refuse the session.\n if (session.wallet_address !== wallet_ref.current?.publicKey) {\n throw new Error(\"Wallet changed during sign in\");\n }\n writeStoredSession(effective_namespace, session);\n setState({\n status: \"verifying\",\n session,\n clientReady: false,\n error: null,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Sign in failed\";\n setState({\n status: \"error\",\n session: null,\n clientReady: false,\n error: message,\n });\n }\n }, [\n url,\n transport,\n method,\n domain,\n statement,\n sessionTtlSeconds,\n effective_namespace,\n ]);\n\n const signOut = useCallback(async () => {\n // Best-effort server-side logout via the currently-cached client.\n try {\n await currentClient().logout();\n } catch {\n // no current client, or server-side logout failed; tear down regardless\n }\n tear_down(\"disconnected\", null);\n }, [tear_down]);\n\n const value = useMemo<AuthContextValue>(\n () => ({\n status: state.status,\n session: state.session,\n clientReady: state.clientReady,\n error: state.error,\n signIn,\n signOut,\n }),\n [state, signIn, signOut],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type { AuthCapableClient } from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\n// Module-level dedupe: in React StrictMode (dev) the AuthProvider effect runs\n// twice with the same inputs, which previously opened two sockets. We cache the\n// in-flight promise so both runs share one connection.\n\nlet current_key: string | null = null;\nlet current_client: AuthCapableClient | null = null;\nlet current_transport: AuthTransport | null = null;\nlet pending_promise: Promise<AuthCapableClient> | null = null;\n\nfunction key_of(kind: string, url: string, token: string): string {\n return `${kind}|${url}|${token}`;\n}\n\nexport async function ensureClient<T extends AuthCapableClient>(\n transport: AuthTransport<T>,\n url: string,\n token: string,\n): Promise<T> {\n const key = key_of(transport.kind, url, token);\n\n if (current_key === key) {\n if (current_client) return current_client as T;\n if (pending_promise) return pending_promise as Promise<T>;\n }\n\n // New (kind, url, token) — release any prior client, start fresh.\n if (current_client && current_transport) {\n try {\n (current_transport as AuthTransport<AuthCapableClient>).release(current_client);\n } catch {\n // release must be idempotent; ignore\n }\n current_client = null;\n }\n current_key = key;\n current_transport = transport as AuthTransport;\n\n const p = transport.connect(url, token).then((client) => {\n // Another ensure/clear ran while we were connecting — drop this one.\n if (current_key !== key) {\n try {\n transport.release(client);\n } catch {\n // ignore\n }\n throw new Error(\"@reifydb/auth: client connect superseded\");\n }\n current_client = client;\n pending_promise = null;\n return client;\n });\n pending_promise = p as Promise<AuthCapableClient>;\n return p;\n}\n\nexport function clearClient(): void {\n if (current_client && current_transport) {\n try {\n (current_transport as AuthTransport<AuthCapableClient>).release(current_client);\n } catch {\n // ignore\n }\n }\n current_key = null;\n current_client = null;\n current_transport = null;\n pending_promise = null;\n}\n\nexport function currentClient<T extends AuthCapableClient = AuthCapableClient>(): T {\n if (!current_client) {\n throw new Error(\"@reifydb/auth: no authenticated client; call ensureClient first\");\n }\n return current_client as T;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type { AuthCapableClient, AuthSession, WalletConnector } from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\nexport interface SignInArgs<TClient extends AuthCapableClient = AuthCapableClient> {\n url: string;\n transport: AuthTransport<TClient>;\n method: string;\n wallet: Pick<WalletConnector, \"publicKey\" | \"signMessage\" | \"encodeSignature\">;\n domain: string;\n statement: string;\n sessionTtlSeconds: number;\n}\n\nexport async function performSignIn<TClient extends AuthCapableClient>(\n args: SignInArgs<TClient>,\n): Promise<AuthSession> {\n const { url, transport, method, wallet, domain, statement, sessionTtlSeconds } = args;\n\n const wallet_address = wallet.publicKey;\n if (wallet_address == null || wallet_address.length === 0) {\n throw new Error(\"@reifydb/auth: wallet.publicKey is required to sign in\");\n }\n if (!Number.isFinite(sessionTtlSeconds) || sessionTtlSeconds <= 0) {\n throw new Error(\"@reifydb/auth: sessionTtlSeconds must be a positive number\");\n }\n\n const client = await transport.connect(url);\n try {\n const challenge = await client.login_challenge(method, {\n identifier: wallet_address,\n public_key: wallet_address,\n domain,\n statement,\n });\n if (challenge.kind !== \"challenge\") {\n throw new Error(\n `@reifydb/auth: expected challenge response, got ${challenge.kind}`,\n );\n }\n\n const messageBytes = new TextEncoder().encode(challenge.message);\n const signatureBytes = await wallet.signMessage(messageBytes);\n const signature = wallet.encodeSignature(signatureBytes);\n\n const auth = await client.login_challenge(method, {\n challenge_id: challenge.challenge_id,\n signature,\n signed_message: challenge.message,\n });\n if (auth.kind !== \"authenticated\") {\n throw new Error(\n `@reifydb/auth: expected authenticated response, got ${auth.kind}`,\n );\n }\n\n return {\n token: auth.token,\n identity: auth.identity,\n wallet_address,\n expires_at: Math.floor(Date.now() / 1000) + sessionTtlSeconds,\n };\n } finally {\n transport.release(client);\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type {\n AuthCapableClient,\n AuthSession,\n CredentialAuthCapableClient,\n} from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\nexport interface PasswordSignInArgs<\n TClient extends AuthCapableClient = AuthCapableClient,\n> {\n url: string;\n transport: AuthTransport<TClient>;\n identifier: string;\n password: string;\n sessionTtlSeconds: number;\n}\n\nfunction supports_password_login(\n client: AuthCapableClient,\n): client is CredentialAuthCapableClient {\n return (\n typeof (client as CredentialAuthCapableClient).login_with_password ===\n \"function\"\n );\n}\n\nexport async function performPasswordSignIn<TClient extends AuthCapableClient>(\n args: PasswordSignInArgs<TClient>,\n): Promise<AuthSession> {\n const { url, transport, identifier, password, sessionTtlSeconds } = args;\n\n if (identifier.length === 0) {\n throw new Error(\"@reifydb/auth: identifier is required to sign in\");\n }\n if (password.length === 0) {\n throw new Error(\"@reifydb/auth: password is required to sign in\");\n }\n if (!Number.isFinite(sessionTtlSeconds) || sessionTtlSeconds <= 0) {\n throw new Error(\"@reifydb/auth: sessionTtlSeconds must be a positive number\");\n }\n\n const client = await transport.connect(url);\n try {\n if (!supports_password_login(client)) {\n throw new Error(\n \"@reifydb/auth: transport client does not support login_with_password\",\n );\n }\n const auth = await client.login_with_password(identifier, password);\n return {\n token: auth.token,\n identity: auth.identity,\n wallet_address: identifier,\n identifier,\n method: \"password\",\n expires_at: Math.floor(Date.now() / 1000) + sessionTtlSeconds,\n };\n } finally {\n transport.release(client);\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type { AuthSession } from \"./types\";\n\nconst SUFFIX = \".auth\";\n\nfunction key_for(namespace: string): string {\n return `${namespace}${SUFFIX}`;\n}\n\n// A per-tab id so two tabs never share one localStorage slot and stomp each\n// other's session. Backed by sessionStorage: stable across reloads within a\n// tab, unique per tab, gone when the tab closes. Falls back to an ephemeral\n// in-memory id when sessionStorage or crypto.randomUUID is unavailable\n// (degraded: the session will not survive a reload).\nconst TAB_ID_KEY = \"reifydb.auth.tab\";\n\nfunction new_tab_id(): string {\n try {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n } catch {\n // crypto unavailable; fall through to the cheap fallback\n }\n return `t-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction resolve_tab_id(): string {\n if (typeof window === \"undefined\") return \"ssr\";\n try {\n const existing = sessionStorage.getItem(TAB_ID_KEY);\n if (existing) return existing;\n const id = new_tab_id();\n sessionStorage.setItem(TAB_ID_KEY, id);\n return id;\n } catch {\n // sessionStorage unavailable (private mode, disabled): ephemeral id.\n return new_tab_id();\n }\n}\n\nconst TAB_ID = resolve_tab_id();\n\n// Scopes a caller's namespace to this browser tab. AuthProvider feeds the\n// result into every storage operation so each tab gets its own slot and the\n// cross-tab `storage` listener filters other tabs out by key.\nexport function tabScopedNamespace(namespace: string): string {\n return `${namespace}.${TAB_ID}`;\n}\n\nfunction is_auth_session(v: unknown): v is AuthSession {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as Record<string, unknown>;\n if (o.method !== undefined && o.method !== \"wallet\" && o.method !== \"password\") {\n return false;\n }\n if (o.identifier !== undefined && typeof o.identifier !== \"string\") {\n return false;\n }\n return (\n typeof o.token === \"string\" && o.token.length > 0 &&\n typeof o.identity === \"string\" && o.identity.length > 0 &&\n typeof o.wallet_address === \"string\" && o.wallet_address.length > 0 &&\n typeof o.expires_at === \"number\" && Number.isFinite(o.expires_at) && o.expires_at > 0\n );\n}\n\nfunction safe_remove(namespace: string): void {\n try {\n localStorage.removeItem(key_for(namespace));\n } catch {\n // localStorage may be unavailable; ignore\n }\n}\n\nexport function readStoredSession(namespace: string): AuthSession | null {\n if (typeof window === \"undefined\") return null;\n let raw: string | null;\n try {\n raw = localStorage.getItem(key_for(namespace));\n } catch {\n return null;\n }\n if (raw == null) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n safe_remove(namespace);\n return null;\n }\n if (!is_auth_session(parsed)) {\n safe_remove(namespace);\n return null;\n }\n if (parsed.expires_at <= Date.now() / 1000) {\n safe_remove(namespace);\n return null;\n }\n return parsed;\n}\n\nexport function writeStoredSession(namespace: string, session: AuthSession): void {\n if (typeof window === \"undefined\") return;\n if (!is_auth_session(session)) {\n throw new Error(\"@reifydb/auth: refusing to persist malformed session\");\n }\n try {\n localStorage.setItem(key_for(namespace), JSON.stringify(session));\n } catch {\n // localStorage may be unavailable (private mode, full quota); ignore.\n }\n}\n\nexport function clearStoredSession(namespace: string): void {\n if (typeof window === \"undefined\") return;\n safe_remove(namespace);\n}\n\nexport function storageKeyFor(namespace: string): string {\n return key_for(namespace);\n}\n\n// Closed tabs leave their per-tab slot in localStorage forever - nothing ever\n// reads that namespace again. Sweep once on mount: drop slots under\n// `baseNamespace` that belong to other tabs and have already expired. Live\n// tabs' slots have a future `expires_at` and are never touched.\nexport function sweepExpiredSessions(baseNamespace: string): void {\n if (typeof window === \"undefined\") return;\n try {\n const now = Date.now() / 1000;\n const own_key = key_for(tabScopedNamespace(baseNamespace));\n const prefix = `${baseNamespace}.`;\n const dead: string[] = [];\n for (let i = 0; i < localStorage.length; i += 1) {\n const k = localStorage.key(i);\n if (k == null || k === own_key) continue;\n if (!k.startsWith(prefix) || !k.endsWith(SUFFIX)) continue;\n const raw = localStorage.getItem(k);\n if (raw == null) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n continue;\n }\n if (is_auth_session(parsed) && parsed.expires_at <= now) {\n dead.push(k);\n }\n }\n for (const k of dead) localStorage.removeItem(k);\n } catch {\n // localStorage unavailable; nothing to sweep.\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport { useContext } from \"react\";\n\nimport { AuthContext, type AuthContextValue } from \"./auth-provider\";\nimport { currentClient } from \"./client-cache\";\nimport type { AuthCapableClient } from \"./types\";\n\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (ctx == null) {\n throw new Error(\"@reifydb/auth: useAuth must be used inside <AuthProvider>\");\n }\n return ctx;\n}\n\nexport function useAuthClient<\n TClient extends AuthCapableClient = AuthCapableClient,\n>(): TClient {\n const { clientReady } = useAuth();\n if (!clientReady) {\n throw new Error(\"@reifydb/auth: useAuthClient called before clientReady\");\n }\n return currentClient<TClient>();\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nexport type {\n AuthCapableClient,\n AuthSession,\n AuthState,\n AuthStatus,\n CredentialAuthCapableClient,\n LoginChallengeResult,\n LoginResult,\n PasswordCredentials,\n WalletConnector,\n} from \"./types\";\n\nexport type { AuthTransport } from \"./transport\";\nexport {\n http_transport,\n json_http_transport,\n json_ws_transport,\n ws_transport,\n} from \"./transport\";\n\nexport {\n AuthContext,\n AuthProvider,\n type AuthContextValue,\n type AuthProviderProps,\n} from \"./auth-provider\";\n\nexport { useAuth, useAuthClient } from \"./use-auth\";\n\nexport { performSignIn, type SignInArgs } from \"./sign-in\";\n\nexport {\n performPasswordSignIn,\n type PasswordSignInArgs,\n} from \"./sign-in-password\";\n\nexport {\n clearStoredSession,\n readStoredSession,\n storageKeyFor,\n writeStoredSession,\n} from \"./storage\";\n\nexport { clearClient, currentClient, ensureClient } from \"./client-cache\";\n\nexport * from \"@reifydb/core\";\nexport * from \"@reifydb/client\";\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/transport.ts","../src/auth-provider.tsx","../src/client-cache.ts","../src/sign-in.ts","../src/sign-in-password.ts","../src/storage.ts","../src/use-auth.ts","../src/index.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport {\n Client,\n type WsClient,\n type HttpClient,\n type JsonWsClient,\n type JsonHttpClient,\n} from \"@reifydb/client\";\nimport type { AuthCapableClient } from \"./types\";\n\nexport interface AuthTransport<\n TClient extends AuthCapableClient = AuthCapableClient,\n> {\n readonly kind: \"ws\" | \"http\";\n connect(url: string, token?: string): Promise<TClient>;\n release(client: TClient): void;\n}\n\nfunction releaseWithDisconnect(client: { disconnect?: () => void }): void {\n if (typeof client.disconnect === \"function\") {\n try {\n client.disconnect();\n } catch {\n }\n }\n}\n\nexport const wsTransport: AuthTransport<WsClient> = {\n kind: \"ws\",\n async connect(url, token) {\n return Client.connectWs(\n url,\n token != null ? { format: \"rbcf\", token } : { format: \"rbcf\" },\n );\n },\n release(client) {\n releaseWithDisconnect(client);\n },\n};\n\nexport const httpTransport: AuthTransport<HttpClient> = {\n kind: \"http\",\n async connect(url, token) {\n return Client.connectHttp(\n url,\n token != null ? { format: \"rbcf\", token } : { format: \"rbcf\" },\n );\n },\n release(_client) {\n },\n};\n\nexport const jsonWsTransport: AuthTransport<JsonWsClient> = {\n kind: \"ws\",\n async connect(url, token) {\n return Client.connectJsonWs(url, token != null ? { token } : undefined);\n },\n release(client) {\n releaseWithDisconnect(client);\n },\n};\n\nexport const jsonHttpTransport: AuthTransport<JsonHttpClient> = {\n kind: \"http\",\n async connect(url, token) {\n return Client.connectJsonHttp(url, token != null ? { token } : undefined);\n },\n release(_client) {\n },\n};\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport { clearClient, currentClient, ensureClient } from \"./client-cache\";\nimport { performSignIn } from \"./sign-in\";\nimport { performPasswordSignIn } from \"./sign-in-password\";\nimport {\n clearStoredSession,\n readStoredSession,\n storageKeyFor,\n sweepExpiredSessions,\n tabScopedNamespace,\n writeStoredSession,\n} from \"./storage\";\nimport type {\n AuthCapableClient,\n AuthSession,\n AuthState,\n PasswordCredentials,\n WalletConnector,\n} from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\nconst DEFAULT_TTL_SECONDS = 86400;\n\nexport interface AuthContextValue extends AuthState {\n signIn(credentials?: PasswordCredentials): Promise<void>;\n adoptSession(session: AuthSession): void;\n signOut(): Promise<void>;\n}\n\nexport const AuthContext = createContext<AuthContextValue | null>(null);\n\nexport interface AuthProviderProps<\n TClient extends AuthCapableClient = AuthCapableClient,\n> {\n url: string;\n transport: AuthTransport<TClient>;\n storageNamespace: string;\n method?: string;\n domain?: string;\n statement?: string;\n sessionTtlSeconds?: number;\n wallet?: WalletConnector;\n sessionScope?: \"tab\" | \"browser\";\n children: ReactNode;\n}\n\ninterface InternalState {\n status: AuthState[\"status\"];\n session: AuthSession | null;\n clientReady: boolean;\n error: string | null;\n}\n\nexport function AuthProvider<TClient extends AuthCapableClient>(\n props: AuthProviderProps<TClient>,\n): ReactElement {\n const {\n url,\n transport,\n storageNamespace,\n method,\n domain,\n statement,\n sessionTtlSeconds = DEFAULT_TTL_SECONDS,\n wallet,\n sessionScope = \"tab\",\n children,\n } = props;\n\n // Per-tab storage slot: each tab gets its own localStorage key so concurrent\n // sign-ins in different tabs cannot stomp each other's session. With\n // sessionScope \"browser\" all tabs deliberately share one slot instead.\n const effectiveNamespace =\n sessionScope === \"browser\"\n ? storageNamespace\n : tabScopedNamespace(storageNamespace);\n\n const [state, setState] = useState<InternalState>(() => {\n const stored = readStoredSession(effectiveNamespace);\n return stored\n ? { status: \"verifying\", session: stored, clientReady: false, error: null }\n : { status: \"disconnected\", session: null, clientReady: false, error: null };\n });\n\n // Pull live wallet fields into stable primitives for effect deps.\n const walletConnected = wallet?.connected ?? false;\n const walletConnecting = wallet?.connecting ?? false;\n const walletPublicKey = wallet?.publicKey ?? null;\n const walletHasSelected = wallet?.hasSelectedWallet ?? false;\n\n // Refs so callbacks can read latest values without re-binding.\n const sessionRef = useRef(state.session);\n sessionRef.current = state.session;\n const walletRef = useRef(wallet);\n walletRef.current = wallet;\n\n const tearDown = useCallback(\n (nextStatus: InternalState[\"status\"], nextError: string | null) => {\n clearStoredSession(effectiveNamespace);\n clearClient();\n setState({\n status: nextStatus,\n session: null,\n clientReady: false,\n error: nextError,\n });\n },\n [effectiveNamespace],\n );\n\n // Session gate. Password sessions connect directly; wallet sessions keep the\n // security invariant: the authenticated client is only ever constructed when\n // the connected wallet matches the persisted session.\n useEffect(() => {\n const session = state.session;\n if (session == null) return;\n\n const establish = () => {\n let cancelled = false;\n ensureClient(transport, url, session.token)\n .then(() => {\n if (cancelled) return;\n setState((prev) =>\n prev.session === session\n ? { ...prev, status: \"authenticated\", clientReady: true, error: null }\n : prev,\n );\n })\n .catch((err: unknown) => {\n if (cancelled) return;\n const message = err instanceof Error ? err.message : \"Failed to connect client\";\n console.error(\"DBG auth error: client connect\", message, err);\n tearDown(\"error\", message);\n });\n return () => {\n cancelled = true;\n };\n };\n\n // Credential-bound sessions (password, or a token minted server-side) carry\n // no wallet to prove, so they connect straight away.\n if (session.method != null && session.method !== \"wallet\") {\n return establish();\n }\n\n if (walletConnected && walletPublicKey != null) {\n if (walletPublicKey !== session.walletAddress) {\n tearDown(\"disconnected\", null);\n return;\n }\n return establish();\n }\n\n if (!walletConnected && (walletConnecting || walletHasSelected)) {\n // Wallet adapter is autoConnecting; stay in verifying. Do NOT construct\n // the client yet - we must not authenticate before the match is confirmed.\n setState((prev) =>\n prev.session === session\n ? { ...prev, status: \"verifying\", clientReady: false }\n : prev,\n );\n return;\n }\n\n // Wallet is definitively absent (no selected wallet, not connecting). User\n // explicitly disconnected, so the session can no longer be proven; tear down.\n tearDown(\"disconnected\", null);\n }, [\n state.session,\n walletConnected,\n walletConnecting,\n walletPublicKey,\n walletHasSelected,\n transport,\n url,\n tearDown,\n ]);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const key = storageKeyFor(effectiveNamespace);\n const onStorage = (e: StorageEvent) => {\n if (e.key !== key) return;\n const current = sessionRef.current;\n\n // Another tab signed out / cleared the session.\n if (e.newValue == null) {\n if (current != null) tearDown(\"disconnected\", null);\n return;\n }\n\n let parsed: Partial<AuthSession>;\n try {\n parsed = JSON.parse(e.newValue) as Partial<AuthSession>;\n } catch {\n // Corrupt entry written by another tab. Only react if we actually hold\n // a session; otherwise there is nothing to defend.\n if (current != null) tearDown(\"disconnected\", null);\n return;\n }\n\n // We hold no session of our own: nothing to defend. Clearing storage here\n // would clobber the session the other tab just wrote (and bounce it back\n // out through this same handler). Let our own sign-in / autoConnect flow\n // converge independently.\n if (current == null) return;\n\n // A genuinely different principal took over our storage slot.\n if (\n parsed.walletAddress !== current.walletAddress ||\n parsed.identity !== current.identity\n ) {\n const followed =\n sessionScope === \"browser\" ? readStoredSession(effectiveNamespace) : null;\n if (followed == null) {\n tearDown(\"disconnected\", null);\n return;\n }\n setState({ status: \"verifying\", session: followed, clientReady: false, error: null });\n }\n\n // Same principal, different token: a concurrent sign-in in another tab,\n // not an intrusion. Keep our own still-valid client.\n };\n window.addEventListener(\"storage\", onStorage);\n return () => {\n window.removeEventListener(\"storage\", onStorage);\n };\n }, [effectiveNamespace, sessionScope, tearDown]);\n\n // Housekeeping: drop expired per-tab slots left behind by closed tabs.\n useEffect(() => {\n sweepExpiredSessions(storageNamespace);\n }, [storageNamespace]);\n\n const signIn = useCallback(async (credentials?: PasswordCredentials) => {\n if (credentials != null) {\n setState((prev) => ({ ...prev, status: \"signing\", error: null }));\n try {\n const session = await performPasswordSignIn({\n url,\n transport,\n identifier: credentials.identifier,\n password: credentials.password,\n sessionTtlSeconds,\n });\n writeStoredSession(effectiveNamespace, session);\n setState({\n status: \"verifying\",\n session,\n clientReady: false,\n error: null,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Sign in failed\";\n setState({\n status: \"error\",\n session: null,\n clientReady: false,\n error: message,\n });\n }\n return;\n }\n\n const w = walletRef.current;\n if (w == null || !w.connected || w.publicKey == null) {\n console.error(\"DBG auth error: wallet not connected\");\n setState((prev) => ({ ...prev, status: \"error\", error: \"Wallet not connected\" }));\n return;\n }\n if (method == null || domain == null || statement == null) {\n setState((prev) => ({\n ...prev,\n status: \"error\",\n error: \"Wallet sign in requires method, domain, and statement\",\n }));\n return;\n }\n setState((prev) => ({ ...prev, status: \"signing\", error: null }));\n try {\n const session = await performSignIn({\n url,\n transport,\n method,\n wallet: w,\n domain,\n statement,\n sessionTtlSeconds,\n });\n // Sanity: signed-in wallet must match the live publicKey. If the user\n // swapped wallets while the signature was in flight, refuse the session.\n if (session.walletAddress !== walletRef.current?.publicKey) {\n throw new Error(\"Wallet changed during sign in\");\n }\n writeStoredSession(effectiveNamespace, session);\n setState({\n status: \"verifying\",\n session,\n clientReady: false,\n error: null,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Sign in failed\";\n console.error(\"DBG auth error: wallet sign in\", message, err);\n setState({\n status: \"error\",\n session: null,\n clientReady: false,\n error: message,\n });\n }\n }, [\n url,\n transport,\n method,\n domain,\n statement,\n sessionTtlSeconds,\n effectiveNamespace,\n ]);\n\n // Adopt a session minted outside the sign-in flows - a guest session handed\n // out by the application server, for instance. The session gate below picks\n // it up and connects the client exactly as it would after a sign-in.\n const adoptSession = useCallback(\n (session: AuthSession) => {\n writeStoredSession(effectiveNamespace, session);\n setState({\n status: \"verifying\",\n session,\n clientReady: false,\n error: null,\n });\n },\n [effectiveNamespace],\n );\n\n const signOut = useCallback(async () => {\n // Best-effort server-side logout via the currently-cached client.\n try {\n await currentClient().logout();\n } catch {\n // no current client, or server-side logout failed; tear down regardless\n }\n tearDown(\"disconnected\", null);\n }, [tearDown]);\n\n const value = useMemo<AuthContextValue>(\n () => ({\n status: state.status,\n session: state.session,\n clientReady: state.clientReady,\n error: state.error,\n signIn,\n adoptSession,\n signOut,\n }),\n [state, signIn, adoptSession, signOut],\n );\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type { AuthCapableClient } from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\n// Module-level dedupe: in React StrictMode (dev) the AuthProvider effect runs\n// twice with the same inputs, which previously opened two sockets. We cache the\n// in-flight promise so both runs share one connection.\n\nlet currentKey: string | null = null;\nlet cachedClient: AuthCapableClient | null = null;\nlet currentTransport: AuthTransport | null = null;\nlet pendingPromise: Promise<AuthCapableClient> | null = null;\n\nfunction keyOf(kind: string, url: string, token: string): string {\n return `${kind}|${url}|${token}`;\n}\n\nexport async function ensureClient<T extends AuthCapableClient>(\n transport: AuthTransport<T>,\n url: string,\n token: string,\n): Promise<T> {\n const key = keyOf(transport.kind, url, token);\n\n if (currentKey === key) {\n if (cachedClient) return cachedClient as T;\n if (pendingPromise) return pendingPromise as Promise<T>;\n }\n\n // New (kind, url, token) — release any prior client, start fresh.\n if (cachedClient && currentTransport) {\n try {\n (currentTransport as AuthTransport<AuthCapableClient>).release(cachedClient);\n } catch {\n // release must be idempotent; ignore\n }\n cachedClient = null;\n }\n currentKey = key;\n currentTransport = transport as AuthTransport;\n\n const p = transport.connect(url, token).then((client) => {\n // Another ensure/clear ran while we were connecting — drop this one.\n if (currentKey !== key) {\n try {\n transport.release(client);\n } catch {\n // ignore\n }\n throw new Error(\"@reifydb/auth: client connect superseded\");\n }\n cachedClient = client;\n pendingPromise = null;\n return client;\n });\n pendingPromise = p as Promise<AuthCapableClient>;\n return p;\n}\n\nexport function clearClient(): void {\n if (cachedClient && currentTransport) {\n try {\n (currentTransport as AuthTransport<AuthCapableClient>).release(cachedClient);\n } catch {\n }\n }\n currentKey = null;\n cachedClient = null;\n currentTransport = null;\n pendingPromise = null;\n}\n\nexport function currentClient<T extends AuthCapableClient = AuthCapableClient>(): T {\n if (!cachedClient) {\n throw new Error(\"@reifydb/auth: no authenticated client; call ensureClient first\");\n }\n return cachedClient as T;\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type { AuthCapableClient, AuthSession, WalletConnector } from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\nexport interface SignInArgs<TClient extends AuthCapableClient = AuthCapableClient> {\n url: string;\n transport: AuthTransport<TClient>;\n method: string;\n wallet: Pick<WalletConnector, \"publicKey\" | \"signMessage\" | \"encodeSignature\">;\n domain: string;\n statement: string;\n sessionTtlSeconds: number;\n}\n\nexport async function performSignIn<TClient extends AuthCapableClient>(\n args: SignInArgs<TClient>,\n): Promise<AuthSession> {\n const { url, transport, method, wallet, domain, statement, sessionTtlSeconds } = args;\n\n const walletAddress = wallet.publicKey;\n if (walletAddress == null || walletAddress.length === 0) {\n throw new Error(\"@reifydb/auth: wallet.publicKey is required to sign in\");\n }\n if (!Number.isFinite(sessionTtlSeconds) || sessionTtlSeconds <= 0) {\n throw new Error(\"@reifydb/auth: sessionTtlSeconds must be a positive number\");\n }\n\n const client = await transport.connect(url);\n try {\n const challenge = await client.loginChallenge(method, {\n identifier: walletAddress,\n public_key: walletAddress,\n domain,\n statement,\n });\n if (challenge.kind !== \"challenge\") {\n throw new Error(\n `@reifydb/auth: expected challenge response, got ${challenge.kind}`,\n );\n }\n\n const messageBytes = new TextEncoder().encode(challenge.message);\n const signatureBytes = await wallet.signMessage(messageBytes);\n const signature = wallet.encodeSignature(signatureBytes);\n\n const auth = await client.loginChallenge(method, {\n challenge_id: challenge.challengeId,\n signature,\n signed_message: challenge.message,\n });\n if (auth.kind !== \"authenticated\") {\n throw new Error(\n `@reifydb/auth: expected authenticated response, got ${auth.kind}`,\n );\n }\n\n return {\n token: auth.token,\n identity: auth.identity,\n walletAddress,\n expiresAt: Math.floor(Date.now() / 1000) + sessionTtlSeconds,\n };\n } finally {\n transport.release(client);\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type {\n AuthCapableClient,\n AuthSession,\n CredentialAuthCapableClient,\n} from \"./types\";\nimport type { AuthTransport } from \"./transport\";\n\nexport interface PasswordSignInArgs<\n TClient extends AuthCapableClient = AuthCapableClient,\n> {\n url: string;\n transport: AuthTransport<TClient>;\n identifier: string;\n password: string;\n sessionTtlSeconds: number;\n}\n\nfunction supportsPasswordLogin(\n client: AuthCapableClient,\n): client is CredentialAuthCapableClient {\n return (\n typeof (client as CredentialAuthCapableClient).loginWithPassword ===\n \"function\"\n );\n}\n\nexport async function performPasswordSignIn<TClient extends AuthCapableClient>(\n args: PasswordSignInArgs<TClient>,\n): Promise<AuthSession> {\n const { url, transport, identifier, password, sessionTtlSeconds } = args;\n\n if (identifier.length === 0) {\n throw new Error(\"@reifydb/auth: identifier is required to sign in\");\n }\n if (password.length === 0) {\n throw new Error(\"@reifydb/auth: password is required to sign in\");\n }\n if (!Number.isFinite(sessionTtlSeconds) || sessionTtlSeconds <= 0) {\n throw new Error(\"@reifydb/auth: sessionTtlSeconds must be a positive number\");\n }\n\n const client = await transport.connect(url);\n try {\n if (!supportsPasswordLogin(client)) {\n throw new Error(\n \"@reifydb/auth: transport client does not support loginWithPassword\",\n );\n }\n const auth = await client.loginWithPassword(identifier, password);\n return {\n token: auth.token,\n identity: auth.identity,\n walletAddress: identifier,\n identifier,\n method: \"password\",\n expiresAt: Math.floor(Date.now() / 1000) + sessionTtlSeconds,\n };\n } finally {\n transport.release(client);\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport type { AuthSession } from \"./types\";\n\nconst SUFFIX = \".auth\";\n\nfunction keyFor(namespace: string): string {\n return `${namespace}${SUFFIX}`;\n}\n\n// A per-tab id so two tabs never share one localStorage slot and stomp each\n// other's session. Backed by sessionStorage: stable across reloads within a\n// tab, unique per tab, gone when the tab closes. Falls back to an ephemeral\n// in-memory id when sessionStorage or crypto.randomUUID is unavailable\n// (degraded: the session will not survive a reload).\nconst TAB_ID_KEY = \"reifydb.auth.tab\";\n\nfunction newTabId(): string {\n try {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n } catch {\n }\n return `t-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction resolveTabId(): string {\n if (typeof window === \"undefined\") return \"ssr\";\n try {\n const existing = sessionStorage.getItem(TAB_ID_KEY);\n if (existing) return existing;\n const id = newTabId();\n sessionStorage.setItem(TAB_ID_KEY, id);\n return id;\n } catch {\n // sessionStorage unavailable (private mode, disabled): ephemeral id.\n return newTabId();\n }\n}\n\nconst TAB_ID = resolveTabId();\n\n// Scopes a caller's namespace to this browser tab. AuthProvider feeds the\n// result into every storage operation so each tab gets its own slot and the\n// cross-tab `storage` listener filters other tabs out by key.\nexport function tabScopedNamespace(namespace: string): string {\n return `${namespace}.${TAB_ID}`;\n}\n\nfunction isAuthSession(v: unknown): v is AuthSession {\n if (v === null || typeof v !== \"object\") return false;\n const o = v as Record<string, unknown>;\n if (\n o.method !== undefined &&\n o.method !== \"wallet\" &&\n o.method !== \"password\" &&\n o.method !== \"token\"\n ) {\n return false;\n }\n if (o.identifier !== undefined && typeof o.identifier !== \"string\") {\n return false;\n }\n return (\n typeof o.token === \"string\" && o.token.length > 0 &&\n typeof o.identity === \"string\" && o.identity.length > 0 &&\n typeof o.walletAddress === \"string\" && o.walletAddress.length > 0 &&\n typeof o.expiresAt === \"number\" && Number.isFinite(o.expiresAt) && o.expiresAt > 0\n );\n}\n\nfunction safeRemove(namespace: string): void {\n try {\n localStorage.removeItem(keyFor(namespace));\n } catch {\n // localStorage may be unavailable; ignore\n }\n}\n\nexport function readStoredSession(namespace: string): AuthSession | null {\n if (typeof window === \"undefined\") return null;\n let raw: string | null;\n try {\n raw = localStorage.getItem(keyFor(namespace));\n } catch {\n return null;\n }\n if (raw == null) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n safeRemove(namespace);\n return null;\n }\n if (!isAuthSession(parsed)) {\n safeRemove(namespace);\n return null;\n }\n if (parsed.expiresAt <= Date.now() / 1000) {\n safeRemove(namespace);\n return null;\n }\n return parsed;\n}\n\nexport function writeStoredSession(namespace: string, session: AuthSession): void {\n if (typeof window === \"undefined\") return;\n if (!isAuthSession(session)) {\n throw new Error(\"@reifydb/auth: refusing to persist malformed session\");\n }\n try {\n localStorage.setItem(keyFor(namespace), JSON.stringify(session));\n } catch {\n // localStorage may be unavailable (private mode, full quota); ignore.\n }\n}\n\nexport function clearStoredSession(namespace: string): void {\n if (typeof window === \"undefined\") return;\n safeRemove(namespace);\n}\n\nexport function storageKeyFor(namespace: string): string {\n return keyFor(namespace);\n}\n\n// Closed tabs leave their per-tab slot in localStorage forever - nothing ever\n// reads that namespace again. Sweep once on mount: drop slots under\n// `baseNamespace` that belong to other tabs and have already expired. Live\n// tabs' slots have a future `expires_at` and are never touched.\nexport function sweepExpiredSessions(baseNamespace: string): void {\n if (typeof window === \"undefined\") return;\n try {\n const now = Date.now() / 1000;\n const ownKey = keyFor(tabScopedNamespace(baseNamespace));\n const prefix = `${baseNamespace}.`;\n const dead: string[] = [];\n for (let i = 0; i < localStorage.length; i += 1) {\n const k = localStorage.key(i);\n if (k == null || k === ownKey) continue;\n if (!k.startsWith(prefix) || !k.endsWith(SUFFIX)) continue;\n const raw = localStorage.getItem(k);\n if (raw == null) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n continue;\n }\n if (isAuthSession(parsed) && parsed.expiresAt <= now) {\n dead.push(k);\n }\n }\n for (const k of dead) localStorage.removeItem(k);\n } catch {\n // localStorage unavailable; nothing to sweep.\n }\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nimport { useContext } from \"react\";\n\nimport { AuthContext, type AuthContextValue } from \"./auth-provider\";\nimport { currentClient } from \"./client-cache\";\nimport type { AuthCapableClient } from \"./types\";\n\nexport function useAuth(): AuthContextValue {\n const ctx = useContext(AuthContext);\n if (ctx == null) {\n throw new Error(\"@reifydb/auth: useAuth must be used inside <AuthProvider>\");\n }\n return ctx;\n}\n\nexport function useAuthClient<\n TClient extends AuthCapableClient = AuthCapableClient,\n>(): TClient {\n const { clientReady } = useAuth();\n if (!clientReady) {\n throw new Error(\"@reifydb/auth: useAuthClient called before clientReady\");\n }\n return currentClient<TClient>();\n}\n","// SPDX-License-Identifier: Apache-2.0\n// Copyright (c) 2026 ReifyDB\n\nexport type {\n AuthCapableClient,\n AuthSession,\n AuthState,\n AuthStatus,\n CredentialAuthCapableClient,\n LoginChallengeResult,\n LoginResult,\n PasswordCredentials,\n WalletConnector,\n} from \"./types\";\n\nexport type { AuthTransport } from \"./transport\";\nexport {\n httpTransport,\n jsonHttpTransport,\n jsonWsTransport,\n wsTransport,\n} from \"./transport\";\n\nexport {\n AuthContext,\n AuthProvider,\n type AuthContextValue,\n type AuthProviderProps,\n} from \"./auth-provider\";\n\nexport { useAuth, useAuthClient } from \"./use-auth\";\n\nexport { performSignIn, type SignInArgs } from \"./sign-in\";\n\nexport {\n performPasswordSignIn,\n type PasswordSignInArgs,\n} from \"./sign-in-password\";\n\nexport {\n clearStoredSession,\n readStoredSession,\n storageKeyFor,\n writeStoredSession,\n} from \"./storage\";\n\nexport { clearClient, currentClient, ensureClient } from \"./client-cache\";\n\nexport * from \"@reifydb/core\";\nexport * from \"@reifydb/client\";\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reifydb/auth",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@reifydb/core": "0.9.
|
|
9
|
-
"@reifydb/client": "0.9.
|
|
8
|
+
"@reifydb/core": "0.9.2",
|
|
9
|
+
"@reifydb/client": "0.9.2"
|
|
10
10
|
},
|
|
11
11
|
"peerDependencies": {
|
|
12
12
|
"react": ">=16.8.0"
|