@nexauthxyz/browser 0.1.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.
@@ -0,0 +1,496 @@
1
+ import { OpenIdDiscoveryClient, normalizeIssuer } from './discovery.js';
2
+ import { NexAuthError } from './errors.js';
3
+ import { IdTokenVerifier } from './id-token-verifier.js';
4
+ import { createPkcePair, generateSecureRandomValue } from './pkce.js';
5
+ import { getDefaultBrowserStorage, NexAuthStorageManager } from './storage.js';
6
+ const AUTHORIZATION_TRANSACTION_MAX_AGE_MS = 10 * 60 * 1000;
7
+ function isRecord(value) {
8
+ return typeof value === 'object' && value !== null;
9
+ }
10
+ function getWindow() {
11
+ if (typeof window === 'undefined') {
12
+ throw new NexAuthError('invalid_configuration', 'NexAuth browser authentication requires a browser environment.');
13
+ }
14
+ return window;
15
+ }
16
+ function normalizeRequiredValue(value, name) {
17
+ const normalized = value.trim();
18
+ if (!normalized) {
19
+ throw new NexAuthError('invalid_configuration', `${name} is required.`);
20
+ }
21
+ return normalized;
22
+ }
23
+ function normalizeRedirectUri(value) {
24
+ let url;
25
+ try {
26
+ url = new URL(value);
27
+ }
28
+ catch (error) {
29
+ throw new NexAuthError('invalid_configuration', 'The NexAuth redirect URI must be a valid absolute URL.', {
30
+ cause: error,
31
+ });
32
+ }
33
+ const local = url.hostname === 'localhost' ||
34
+ url.hostname === '127.0.0.1' ||
35
+ url.hostname === '[::1]';
36
+ if (url.protocol !== 'https:' && !local) {
37
+ throw new NexAuthError('invalid_configuration', 'The NexAuth redirect URI must use HTTPS outside local development.');
38
+ }
39
+ if (url.username || url.password || url.hash) {
40
+ throw new NexAuthError('invalid_configuration', 'The NexAuth redirect URI contains unsupported URL components.');
41
+ }
42
+ return url.toString();
43
+ }
44
+ function normalizeScope(value) {
45
+ const scopes = value
46
+ .split(/\s+/)
47
+ .map((scope) => scope.trim())
48
+ .filter(Boolean);
49
+ if (!scopes.includes('openid')) {
50
+ scopes.unshift('openid');
51
+ }
52
+ return [...new Set(scopes)].join(' ');
53
+ }
54
+ function mergeScopes(configuredScope, additionalScopes) {
55
+ if (!additionalScopes?.length) {
56
+ return configuredScope;
57
+ }
58
+ return normalizeScope(`${configuredScope} ${additionalScopes.join(' ')}`);
59
+ }
60
+ function normalizeReturnTo(value) {
61
+ if (!value) {
62
+ return undefined;
63
+ }
64
+ const normalized = value.trim();
65
+ if (!normalized) {
66
+ return undefined;
67
+ }
68
+ const browserWindow = getWindow();
69
+ let url;
70
+ try {
71
+ url = new URL(normalized, browserWindow.location.origin);
72
+ }
73
+ catch (error) {
74
+ throw new NexAuthError('login_failed', 'The return route is invalid.', {
75
+ cause: error,
76
+ });
77
+ }
78
+ if (url.origin !== browserWindow.location.origin) {
79
+ throw new NexAuthError('login_failed', 'The return route must belong to the current application.');
80
+ }
81
+ return `${url.pathname}${url.search}${url.hash}`;
82
+ }
83
+ function validateTransaction(value) {
84
+ if (!isRecord(value) ||
85
+ typeof value.state !== 'string' ||
86
+ typeof value.nonce !== 'string' ||
87
+ typeof value.codeVerifier !== 'string' ||
88
+ typeof value.redirectUri !== 'string' ||
89
+ typeof value.createdAt !== 'number') {
90
+ throw new NexAuthError('missing_pkce_transaction', 'The stored authorization transaction is missing or invalid.');
91
+ }
92
+ return {
93
+ state: value.state,
94
+ nonce: value.nonce,
95
+ codeVerifier: value.codeVerifier,
96
+ redirectUri: value.redirectUri,
97
+ createdAt: value.createdAt,
98
+ ...(typeof value.returnTo === 'string'
99
+ ? {
100
+ returnTo: value.returnTo,
101
+ }
102
+ : {}),
103
+ };
104
+ }
105
+ function validateTokenResponse(value) {
106
+ if (!isRecord(value)) {
107
+ throw new NexAuthError('invalid_token_response', 'NexAuth returned an invalid token response.');
108
+ }
109
+ if (typeof value.access_token !== 'string' || !value.access_token.trim()) {
110
+ throw new NexAuthError('invalid_token_response', 'NexAuth did not return an access token.');
111
+ }
112
+ if (typeof value.token_type !== 'string' ||
113
+ value.token_type.toLowerCase() !== 'bearer') {
114
+ throw new NexAuthError('invalid_token_response', 'NexAuth returned an unsupported token type.');
115
+ }
116
+ if (typeof value.expires_in !== 'number' ||
117
+ !Number.isFinite(value.expires_in) ||
118
+ value.expires_in <= 0) {
119
+ throw new NexAuthError('invalid_token_response', 'NexAuth returned an invalid token expiration.');
120
+ }
121
+ return {
122
+ access_token: value.access_token,
123
+ token_type: value.token_type,
124
+ expires_in: value.expires_in,
125
+ ...(typeof value.scope === 'string'
126
+ ? {
127
+ scope: value.scope,
128
+ }
129
+ : {}),
130
+ ...(typeof value.id_token === 'string'
131
+ ? {
132
+ id_token: value.id_token,
133
+ }
134
+ : {}),
135
+ ...(typeof value.refresh_token === 'string'
136
+ ? {
137
+ refresh_token: value.refresh_token,
138
+ }
139
+ : {}),
140
+ };
141
+ }
142
+ function validateUserInfo(value) {
143
+ if (!isRecord(value) || typeof value.sub !== 'string' || !value.sub.trim()) {
144
+ throw new NexAuthError('userinfo_failed', 'NexAuth returned an invalid user profile.');
145
+ }
146
+ return value;
147
+ }
148
+ async function getResponseError(response, fallbackMessage) {
149
+ const headerRequestId = response.headers.get('x-request-id')?.trim() || undefined;
150
+ try {
151
+ const body = (await response.json());
152
+ if (typeof body.error === 'object' && body.error !== null) {
153
+ const requestId = body.error.requestId?.trim() ||
154
+ body.requestId?.trim() ||
155
+ body.request_id?.trim() ||
156
+ headerRequestId;
157
+ return {
158
+ message: body.error.message?.trim() || fallbackMessage,
159
+ ...(requestId ? { requestId } : {}),
160
+ };
161
+ }
162
+ const requestId = body.requestId?.trim() || body.request_id?.trim() || headerRequestId;
163
+ const message = body.error_description?.trim() ||
164
+ body.message?.trim() ||
165
+ (typeof body.error === 'string' ? body.error.trim() : undefined) ||
166
+ fallbackMessage;
167
+ return {
168
+ message,
169
+ ...(requestId ? { requestId } : {}),
170
+ };
171
+ }
172
+ catch {
173
+ return {
174
+ message: fallbackMessage,
175
+ ...(headerRequestId
176
+ ? {
177
+ requestId: headerRequestId,
178
+ }
179
+ : {}),
180
+ };
181
+ }
182
+ }
183
+ export class NexAuthBrowserClient {
184
+ clientId;
185
+ redirectUri;
186
+ scope;
187
+ fetchImplementation;
188
+ storage;
189
+ discovery;
190
+ idTokenVerifier;
191
+ constructor(options) {
192
+ const issuer = normalizeIssuer(options.issuer);
193
+ this.clientId = normalizeRequiredValue(options.clientId, 'NexAuth client ID');
194
+ this.idTokenVerifier = new IdTokenVerifier(this.clientId);
195
+ const browserWindow = getWindow();
196
+ this.redirectUri = normalizeRedirectUri(options.redirectUri ?? `${browserWindow.location.origin}/auth/callback`);
197
+ this.scope = normalizeScope(options.scope?.trim() || 'openid profile email');
198
+ const fetchImplementation = options.fetch ?? globalThis.fetch;
199
+ if (typeof fetchImplementation !== 'function') {
200
+ throw new NexAuthError('invalid_configuration', 'The browser Fetch API is unavailable.');
201
+ }
202
+ this.fetchImplementation = fetchImplementation.bind(globalThis);
203
+ const storage = options.storage ?? getDefaultBrowserStorage();
204
+ this.storage = new NexAuthStorageManager(storage, options.storageKeyPrefix?.trim() || 'nexauth', this.clientId);
205
+ this.discovery = new OpenIdDiscoveryClient({
206
+ issuer,
207
+ fetch: this.fetchImplementation,
208
+ });
209
+ }
210
+ async getConfiguration() {
211
+ return this.discovery.getConfiguration();
212
+ }
213
+ async login(options = {}) {
214
+ const configuration = await this.discovery.getConfiguration();
215
+ const pkce = await createPkcePair();
216
+ const state = generateSecureRandomValue(32);
217
+ const nonce = generateSecureRandomValue(32);
218
+ const returnTo = normalizeReturnTo(options.returnTo);
219
+ const transaction = {
220
+ state,
221
+ nonce,
222
+ codeVerifier: pkce.verifier,
223
+ redirectUri: this.redirectUri,
224
+ createdAt: Date.now(),
225
+ ...(returnTo ? { returnTo } : {}),
226
+ };
227
+ this.storage.set('transaction', transaction);
228
+ const authorizationUrl = new URL(configuration.authorization_endpoint);
229
+ authorizationUrl.search = new URLSearchParams({
230
+ response_type: 'code',
231
+ client_id: this.clientId,
232
+ redirect_uri: this.redirectUri,
233
+ scope: mergeScopes(this.scope, options.additionalScopes),
234
+ state,
235
+ nonce,
236
+ code_challenge: pkce.challenge,
237
+ code_challenge_method: pkce.method,
238
+ ...(options.prompt
239
+ ? {
240
+ prompt: options.prompt,
241
+ }
242
+ : {}),
243
+ }).toString();
244
+ getWindow().location.assign(authorizationUrl.toString());
245
+ }
246
+ async handleCallback(input = {}) {
247
+ let callbackUrl;
248
+ try {
249
+ callbackUrl = new URL(input.url ?? getWindow().location.href);
250
+ }
251
+ catch (error) {
252
+ throw new NexAuthError('callback_failed', 'The authorization callback URL is invalid.', {
253
+ cause: error,
254
+ });
255
+ }
256
+ const transaction = validateTransaction(this.storage.get('transaction'));
257
+ const expectedRedirectUrl = new URL(transaction.redirectUri);
258
+ if (callbackUrl.origin !== expectedRedirectUrl.origin ||
259
+ callbackUrl.pathname !== expectedRedirectUrl.pathname) {
260
+ this.storage.remove('transaction');
261
+ throw new NexAuthError('callback_failed', 'The authorization callback does not match the configured redirect URI.');
262
+ }
263
+ const transactionAge = Date.now() - transaction.createdAt;
264
+ if (transactionAge < 0 ||
265
+ transactionAge > AUTHORIZATION_TRANSACTION_MAX_AGE_MS) {
266
+ this.storage.remove('transaction');
267
+ throw new NexAuthError('callback_failed', 'The authorization transaction has expired. Start sign-in again.');
268
+ }
269
+ const returnedState = callbackUrl.searchParams.get('state');
270
+ if (!returnedState || returnedState !== transaction.state) {
271
+ this.storage.remove('transaction');
272
+ throw new NexAuthError('invalid_state', 'The OAuth state validation failed.');
273
+ }
274
+ const oauthError = callbackUrl.searchParams.get('error');
275
+ if (oauthError) {
276
+ const description = callbackUrl.searchParams.get('error_description')?.trim() ||
277
+ 'NexAuth denied the authorization request.';
278
+ this.storage.remove('transaction');
279
+ throw new NexAuthError('authorization_error', description);
280
+ }
281
+ const code = callbackUrl.searchParams.get('code')?.trim();
282
+ if (!code) {
283
+ this.storage.remove('transaction');
284
+ throw new NexAuthError('missing_authorization_code', 'The authorization callback does not contain a code.');
285
+ }
286
+ const configuration = await this.discovery.getConfiguration();
287
+ const token = await this.exchangeAuthorizationCode(configuration, code, transaction);
288
+ /*
289
+ * The authorization code is single-use and has now been consumed.
290
+ * Remove temporary PKCE state before further processing.
291
+ */
292
+ this.storage.remove('transaction');
293
+ if (!token.id_token) {
294
+ throw new NexAuthError('id_token_validation_failed', 'NexAuth did not return an ID token for an OpenID request.');
295
+ }
296
+ const idTokenClaims = await this.idTokenVerifier.verify(token.id_token, configuration, transaction.nonce);
297
+ const user = await this.loadUserInfo(configuration, token.access_token);
298
+ if (user.sub !== idTokenClaims.sub) {
299
+ throw new NexAuthError('id_token_validation_failed', 'The UserInfo subject does not match the ID-token subject.');
300
+ }
301
+ const session = {
302
+ accessToken: token.access_token,
303
+ tokenType: 'Bearer',
304
+ expiresAt: Date.now() + token.expires_in * 1000,
305
+ user,
306
+ idToken: token.id_token,
307
+ idTokenClaims,
308
+ ...(token.scope
309
+ ? {
310
+ scope: token.scope,
311
+ }
312
+ : {}),
313
+ ...(token.refresh_token
314
+ ? {
315
+ refreshToken: token.refresh_token,
316
+ }
317
+ : {}),
318
+ };
319
+ this.storage.set('session', session);
320
+ return {
321
+ session,
322
+ ...(transaction.returnTo
323
+ ? {
324
+ returnTo: transaction.returnTo,
325
+ }
326
+ : {}),
327
+ };
328
+ }
329
+ getSession() {
330
+ const value = this.storage.get('session');
331
+ if (!isRecord(value)) {
332
+ if (value !== null) {
333
+ this.storage.remove('session');
334
+ }
335
+ return null;
336
+ }
337
+ if (typeof value.accessToken !== 'string' ||
338
+ value.tokenType !== 'Bearer' ||
339
+ typeof value.expiresAt !== 'number' ||
340
+ !isRecord(value.user) ||
341
+ typeof value.user.sub !== 'string') {
342
+ this.storage.remove('session');
343
+ return null;
344
+ }
345
+ if (Date.now() >= value.expiresAt) {
346
+ this.storage.remove('session');
347
+ return null;
348
+ }
349
+ return value;
350
+ }
351
+ isAuthenticated() {
352
+ return this.getSession() !== null;
353
+ }
354
+ getAccessToken() {
355
+ return this.getSession()?.accessToken ?? null;
356
+ }
357
+ getUser() {
358
+ return this.getSession()?.user ?? null;
359
+ }
360
+ async logout(options = {}) {
361
+ if (options.localOnly === true) {
362
+ this.storage.clear();
363
+ return;
364
+ }
365
+ let configuration;
366
+ try {
367
+ configuration = await this.discovery.getConfiguration();
368
+ }
369
+ catch (error) {
370
+ this.storage.clear();
371
+ throw new NexAuthError('logout_failed', 'Local authentication was cleared, but NexAuth logout configuration could not be loaded.', {
372
+ cause: error,
373
+ });
374
+ }
375
+ this.storage.clear();
376
+ if (!configuration.end_session_endpoint) {
377
+ throw new NexAuthError('logout_failed', 'NexAuth does not advertise an end-session endpoint.');
378
+ }
379
+ let response;
380
+ try {
381
+ response = await this.fetchImplementation(configuration.end_session_endpoint, {
382
+ method: 'POST',
383
+ credentials: 'include',
384
+ headers: {
385
+ Accept: 'application/json',
386
+ },
387
+ });
388
+ }
389
+ catch (error) {
390
+ throw new NexAuthError('logout_failed', 'Local authentication was cleared, but the NexAuth server session could not be terminated.', {
391
+ cause: error,
392
+ });
393
+ }
394
+ if (!response.ok) {
395
+ const responseError = await getResponseError(response, 'NexAuth could not terminate the server session.');
396
+ throw new NexAuthError('logout_failed', responseError.message, {
397
+ status: response.status,
398
+ ...(responseError.requestId
399
+ ? {
400
+ requestId: responseError.requestId,
401
+ }
402
+ : {}),
403
+ });
404
+ }
405
+ }
406
+ clearLocalSession() {
407
+ this.storage.clear();
408
+ }
409
+ async exchangeAuthorizationCode(configuration, code, transaction) {
410
+ const body = new URLSearchParams({
411
+ grant_type: 'authorization_code',
412
+ client_id: this.clientId,
413
+ code,
414
+ redirect_uri: transaction.redirectUri,
415
+ code_verifier: transaction.codeVerifier,
416
+ });
417
+ let response;
418
+ try {
419
+ response = await this.fetchImplementation(configuration.token_endpoint, {
420
+ method: 'POST',
421
+ headers: {
422
+ Accept: 'application/json',
423
+ 'Content-Type': 'application/x-www-form-urlencoded',
424
+ },
425
+ body,
426
+ });
427
+ }
428
+ catch (error) {
429
+ throw new NexAuthError('network_error', 'Unable to connect to the NexAuth token endpoint.', {
430
+ cause: error,
431
+ });
432
+ }
433
+ if (!response.ok) {
434
+ const responseError = await getResponseError(response, 'NexAuth rejected the authorization code.');
435
+ throw new NexAuthError('token_exchange_failed', responseError.message, {
436
+ status: response.status,
437
+ ...(responseError.requestId
438
+ ? {
439
+ requestId: responseError.requestId,
440
+ }
441
+ : {}),
442
+ });
443
+ }
444
+ let bodyValue;
445
+ try {
446
+ bodyValue = await response.json();
447
+ }
448
+ catch (error) {
449
+ throw new NexAuthError('invalid_token_response', 'NexAuth returned malformed token JSON.', {
450
+ status: response.status,
451
+ cause: error,
452
+ });
453
+ }
454
+ return validateTokenResponse(bodyValue);
455
+ }
456
+ async loadUserInfo(configuration, accessToken) {
457
+ let response;
458
+ try {
459
+ response = await this.fetchImplementation(configuration.userinfo_endpoint, {
460
+ method: 'GET',
461
+ headers: {
462
+ Accept: 'application/json',
463
+ Authorization: `Bearer ${accessToken}`,
464
+ },
465
+ });
466
+ }
467
+ catch (error) {
468
+ throw new NexAuthError('network_error', 'Unable to connect to the NexAuth UserInfo endpoint.', {
469
+ cause: error,
470
+ });
471
+ }
472
+ if (!response.ok) {
473
+ const responseError = await getResponseError(response, 'NexAuth could not load the authenticated user.');
474
+ throw new NexAuthError('userinfo_failed', responseError.message, {
475
+ status: response.status,
476
+ ...(responseError.requestId
477
+ ? {
478
+ requestId: responseError.requestId,
479
+ }
480
+ : {}),
481
+ });
482
+ }
483
+ let value;
484
+ try {
485
+ value = await response.json();
486
+ }
487
+ catch (error) {
488
+ throw new NexAuthError('userinfo_failed', 'NexAuth returned malformed UserInfo JSON.', {
489
+ status: response.status,
490
+ cause: error,
491
+ });
492
+ }
493
+ return validateUserInfo(value);
494
+ }
495
+ }
496
+ //# sourceMappingURL=nexauth-browser-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nexauth-browser-client.js","sourceRoot":"","sources":["../src/nexauth-browser-client.ts"],"names":[],"mappings":"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"}
package/dist/pkce.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export interface PkcePair {
2
+ readonly verifier: string;
3
+ readonly challenge: string;
4
+ readonly method: 'S256';
5
+ }
6
+ export declare function generateSecureRandomValue(byteLength?: number): string;
7
+ export declare function createCodeChallenge(verifier: string): Promise<string>;
8
+ export declare function createPkcePair(): Promise<PkcePair>;
9
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAgCD,wBAAgB,yBAAyB,CAAC,UAAU,SAAK,GAAG,MAAM,CAajE;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyB3E;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAaxD"}
package/dist/pkce.js ADDED
@@ -0,0 +1,58 @@
1
+ import { NexAuthError } from './errors.js';
2
+ function getWebCrypto() {
3
+ const cryptoImplementation = globalThis.crypto;
4
+ if (!cryptoImplementation ||
5
+ typeof cryptoImplementation.getRandomValues !== 'function' ||
6
+ !cryptoImplementation.subtle) {
7
+ throw new NexAuthError('invalid_configuration', 'This browser does not provide the Web Crypto API required by NexAuth.');
8
+ }
9
+ return cryptoImplementation;
10
+ }
11
+ function bytesToBase64Url(bytes) {
12
+ let binary = '';
13
+ for (const byte of bytes) {
14
+ binary += String.fromCharCode(byte);
15
+ }
16
+ return btoa(binary)
17
+ .replace(/\+/g, '-')
18
+ .replace(/\//g, '_')
19
+ .replace(/=+$/g, '');
20
+ }
21
+ export function generateSecureRandomValue(byteLength = 32) {
22
+ if (!Number.isInteger(byteLength) || byteLength < 16) {
23
+ throw new NexAuthError('invalid_configuration', 'Secure random values must contain at least 16 bytes.');
24
+ }
25
+ const bytes = new Uint8Array(byteLength);
26
+ getWebCrypto().getRandomValues(bytes);
27
+ return bytesToBase64Url(bytes);
28
+ }
29
+ export async function createCodeChallenge(verifier) {
30
+ if (verifier.length < 43 || verifier.length > 128) {
31
+ throw new NexAuthError('invalid_configuration', 'The PKCE verifier must contain between 43 and 128 characters.');
32
+ }
33
+ const encodedVerifier = new TextEncoder().encode(verifier);
34
+ let digest;
35
+ try {
36
+ digest = await getWebCrypto().subtle.digest('SHA-256', encodedVerifier);
37
+ }
38
+ catch (error) {
39
+ throw new NexAuthError('login_failed', 'Unable to create the PKCE authorization challenge.', {
40
+ cause: error,
41
+ });
42
+ }
43
+ return bytesToBase64Url(new Uint8Array(digest));
44
+ }
45
+ export async function createPkcePair() {
46
+ /*
47
+ * 64 random bytes produce an 86-character base64url verifier,
48
+ * which satisfies the RFC 7636 requirement of 43–128 characters.
49
+ */
50
+ const verifier = generateSecureRandomValue(64);
51
+ const challenge = await createCodeChallenge(verifier);
52
+ return {
53
+ verifier,
54
+ challenge,
55
+ method: 'S256',
56
+ };
57
+ }
58
+ //# sourceMappingURL=pkce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../src/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQ3C,SAAS,YAAY;IACnB,MAAM,oBAAoB,GAAG,UAAU,CAAC,MAAM,CAAC;IAE/C,IACE,CAAC,oBAAoB;QACrB,OAAO,oBAAoB,CAAC,eAAe,KAAK,UAAU;QAC1D,CAAC,oBAAoB,CAAC,MAAM,EAC5B,CAAC;QACD,MAAM,IAAI,YAAY,CACpB,uBAAuB,EACvB,uEAAuE,CACxE,CAAC;IACJ,CAAC;IAED,OAAO,oBAAoB,CAAC;AAC9B,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAiB;IACzC,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,CAAC;SAChB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,UAAU,GAAG,EAAE;IACvD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,YAAY,CACpB,uBAAuB,EACvB,sDAAsD,CACvD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;IAEzC,YAAY,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAEtC,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACxD,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAClD,MAAM,IAAI,YAAY,CACpB,uBAAuB,EACvB,+DAA+D,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE3D,IAAI,MAAmB,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAC1E,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,IAAI,YAAY,CACpB,cAAc,EACd,oDAAoD,EACpD;YACE,KAAK,EAAE,KAAK;SACb,CACF,CAAC;IACJ,CAAC;IAED,OAAO,gBAAgB,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC;;;OAGG;IACH,MAAM,QAAQ,GAAG,yBAAyB,CAAC,EAAE,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAEtD,OAAO;QACL,QAAQ;QACR,SAAS;QACT,MAAM,EAAE,MAAM;KACf,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { NexAuthStorage } from './types.js';
2
+ export type NexAuthStorageEntry = 'session' | 'transaction';
3
+ export declare function getDefaultBrowserStorage(): NexAuthStorage;
4
+ export declare class NexAuthStorageManager {
5
+ private readonly storage;
6
+ private readonly namespace;
7
+ constructor(storage: NexAuthStorage, prefix: string, clientId: string);
8
+ get<T>(entry: NexAuthStorageEntry): T | null;
9
+ set<T>(entry: NexAuthStorageEntry, value: T): void;
10
+ remove(entry: NexAuthStorageEntry): void;
11
+ clear(): void;
12
+ private getKey;
13
+ }
14
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,aAAa,CAAC;AAY5D,wBAAgB,wBAAwB,IAAI,cAAc,CAYzD;AAED,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGjC,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;IAUX,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,mBAAmB,GAAG,CAAC,GAAG,IAAI;IAuC5C,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IA8BlD,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAcxC,KAAK,IAAI,IAAI;IAUpB,OAAO,CAAC,MAAM;CAGf"}