@netlify/identity 0.1.1 → 0.3.0-alpha.1

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.cjs CHANGED
@@ -30,12 +30,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AUTH_EVENTS: () => AUTH_EVENTS,
33
34
  AuthError: () => AuthError,
34
35
  MissingIdentityError: () => MissingIdentityError,
36
+ acceptInvite: () => acceptInvite,
37
+ admin: () => admin,
38
+ confirmEmail: () => confirmEmail,
35
39
  getIdentityConfig: () => getIdentityConfig,
36
40
  getSettings: () => getSettings,
37
41
  getUser: () => getUser,
38
- isAuthenticated: () => isAuthenticated
42
+ handleAuthCallback: () => handleAuthCallback,
43
+ hydrateSession: () => hydrateSession,
44
+ isAuthenticated: () => isAuthenticated,
45
+ login: () => login,
46
+ logout: () => logout,
47
+ oauthLogin: () => oauthLogin,
48
+ onAuthChange: () => onAuthChange,
49
+ recoverPassword: () => recoverPassword,
50
+ requestPasswordRecovery: () => requestPasswordRecovery,
51
+ signup: () => signup,
52
+ updateUser: () => updateUser,
53
+ verifyEmailChange: () => verifyEmailChange
39
54
  });
40
55
  module.exports = __toCommonJS(index_exports);
41
56
 
@@ -44,6 +59,26 @@ var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "sa
44
59
 
45
60
  // src/environment.ts
46
61
  var import_gotrue_js = __toESM(require("gotrue-js"), 1);
62
+
63
+ // src/errors.ts
64
+ var AuthError = class extends Error {
65
+ constructor(message, status, options) {
66
+ super(message);
67
+ this.name = "AuthError";
68
+ this.status = status;
69
+ if (options && "cause" in options) {
70
+ this.cause = options.cause;
71
+ }
72
+ }
73
+ };
74
+ var MissingIdentityError = class extends Error {
75
+ constructor(message = "Netlify Identity is not available.") {
76
+ super(message);
77
+ this.name = "MissingIdentityError";
78
+ }
79
+ };
80
+
81
+ // src/environment.ts
47
82
  var IDENTITY_PATH = "/.netlify/identity";
48
83
  var goTrueClient = null;
49
84
  var cachedApiUrl;
@@ -59,6 +94,8 @@ var discoverApiUrl = () => {
59
94
  cachedApiUrl = identityContext.url;
60
95
  } else if (globalThis.Netlify?.context?.url) {
61
96
  cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href;
97
+ } else if (process.env.URL) {
98
+ cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href;
62
99
  }
63
100
  }
64
101
  return cachedApiUrl ?? null;
@@ -75,9 +112,14 @@ var getGoTrueClient = () => {
75
112
  }
76
113
  return null;
77
114
  }
78
- goTrueClient = new import_gotrue_js.default({ APIUrl: apiUrl, setCookie: isBrowser() });
115
+ goTrueClient = new import_gotrue_js.default({ APIUrl: apiUrl, setCookie: false });
79
116
  return goTrueClient;
80
117
  };
118
+ var getClient = () => {
119
+ const client = getGoTrueClient();
120
+ if (!client) throw new MissingIdentityError();
121
+ return client;
122
+ };
81
123
  var getIdentityContext = () => {
82
124
  const identityContext = globalThis.netlifyIdentityContext;
83
125
  if (identityContext?.url) {
@@ -89,9 +131,88 @@ var getIdentityContext = () => {
89
131
  if (globalThis.Netlify?.context?.url) {
90
132
  return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href };
91
133
  }
134
+ const siteUrl = process.env.URL;
135
+ if (siteUrl) {
136
+ return { url: new URL(IDENTITY_PATH, siteUrl).href };
137
+ }
92
138
  return null;
93
139
  };
94
140
 
141
+ // src/cookies.ts
142
+ var NF_JWT_COOKIE = "nf_jwt";
143
+ var NF_REFRESH_COOKIE = "nf_refresh";
144
+ var getCookie = (name) => {
145
+ const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`));
146
+ return match ? decodeURIComponent(match[1]) : null;
147
+ };
148
+ var setAuthCookies = (cookies, accessToken, refreshToken) => {
149
+ cookies.set({
150
+ name: NF_JWT_COOKIE,
151
+ value: accessToken,
152
+ httpOnly: false,
153
+ secure: true,
154
+ path: "/",
155
+ sameSite: "Lax"
156
+ });
157
+ if (refreshToken) {
158
+ cookies.set({
159
+ name: NF_REFRESH_COOKIE,
160
+ value: refreshToken,
161
+ httpOnly: false,
162
+ secure: true,
163
+ path: "/",
164
+ sameSite: "Lax"
165
+ });
166
+ }
167
+ };
168
+ var deleteAuthCookies = (cookies) => {
169
+ cookies.delete(NF_JWT_COOKIE);
170
+ cookies.delete(NF_REFRESH_COOKIE);
171
+ };
172
+ var setBrowserAuthCookies = (accessToken, refreshToken) => {
173
+ document.cookie = `${NF_JWT_COOKIE}=${encodeURIComponent(accessToken)}; path=/; secure; samesite=lax`;
174
+ if (refreshToken) {
175
+ document.cookie = `${NF_REFRESH_COOKIE}=${encodeURIComponent(refreshToken)}; path=/; secure; samesite=lax`;
176
+ }
177
+ };
178
+ var deleteBrowserAuthCookies = () => {
179
+ document.cookie = `${NF_JWT_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
180
+ document.cookie = `${NF_REFRESH_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
181
+ };
182
+ var getServerCookie = (name) => {
183
+ const cookies = globalThis.Netlify?.context?.cookies;
184
+ if (!cookies || typeof cookies.get !== "function") return null;
185
+ return cookies.get(name) ?? null;
186
+ };
187
+
188
+ // src/nextjs.ts
189
+ var nextHeadersFn;
190
+ var triggerNextjsDynamic = () => {
191
+ if (nextHeadersFn === null) return;
192
+ if (nextHeadersFn === void 0) {
193
+ try {
194
+ if (typeof require === "undefined") {
195
+ nextHeadersFn = null;
196
+ return;
197
+ }
198
+ const mod = require("next/headers");
199
+ nextHeadersFn = mod.headers;
200
+ } catch {
201
+ nextHeadersFn = null;
202
+ return;
203
+ }
204
+ }
205
+ const fn = nextHeadersFn;
206
+ if (!fn) return;
207
+ try {
208
+ fn();
209
+ } catch (e) {
210
+ if (e instanceof Error && ("digest" in e || /bail\s*out.*prerende/i.test(e.message))) {
211
+ throw e;
212
+ }
213
+ }
214
+ };
215
+
95
216
  // src/user.ts
96
217
  var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
97
218
  var toUser = (userData) => {
@@ -124,36 +245,80 @@ var claimsToUser = (claims) => {
124
245
  metadata: userMeta
125
246
  };
126
247
  };
248
+ var hydrating = false;
249
+ var backgroundHydrate = (accessToken) => {
250
+ if (hydrating) return;
251
+ hydrating = true;
252
+ const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
253
+ const decoded = decodeJwtPayload(accessToken);
254
+ const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1e3) + 3600;
255
+ const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1e3));
256
+ setTimeout(() => {
257
+ try {
258
+ const client = getClient();
259
+ client.createUser(
260
+ {
261
+ access_token: accessToken,
262
+ token_type: "bearer",
263
+ expires_in: expiresIn,
264
+ expires_at: expiresAt,
265
+ refresh_token: refreshToken
266
+ },
267
+ true
268
+ ).catch(() => {
269
+ }).finally(() => {
270
+ hydrating = false;
271
+ });
272
+ } catch {
273
+ hydrating = false;
274
+ }
275
+ }, 0);
276
+ };
277
+ var decodeJwtPayload = (token) => {
278
+ try {
279
+ const parts = token.split(".");
280
+ if (parts.length !== 3) return null;
281
+ const payload = atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"));
282
+ return JSON.parse(payload);
283
+ } catch {
284
+ return null;
285
+ }
286
+ };
127
287
  var getUser = () => {
128
288
  if (isBrowser()) {
129
289
  const client = getGoTrueClient();
130
290
  const currentUser = client?.currentUser() ?? null;
131
- if (!currentUser) return null;
132
- return toUser(currentUser);
291
+ if (currentUser) {
292
+ const jwt2 = getCookie(NF_JWT_COOKIE);
293
+ if (!jwt2) {
294
+ try {
295
+ currentUser.clearSession();
296
+ } catch {
297
+ }
298
+ return null;
299
+ }
300
+ return toUser(currentUser);
301
+ }
302
+ const jwt = getCookie(NF_JWT_COOKIE);
303
+ if (!jwt) return null;
304
+ const claims = decodeJwtPayload(jwt);
305
+ if (!claims) return null;
306
+ backgroundHydrate(jwt);
307
+ return claimsToUser(claims);
133
308
  }
309
+ triggerNextjsDynamic();
134
310
  const identityContext = globalThis.netlifyIdentityContext;
135
- if (!identityContext?.user) return null;
136
- return claimsToUser(identityContext.user);
137
- };
138
- var isAuthenticated = () => getUser() !== null;
139
-
140
- // src/errors.ts
141
- var AuthError = class extends Error {
142
- constructor(message, status, options) {
143
- super(message);
144
- this.name = "AuthError";
145
- this.status = status;
146
- if (options && "cause" in options) {
147
- this.cause = options.cause;
148
- }
311
+ if (identityContext?.user) {
312
+ return claimsToUser(identityContext.user);
149
313
  }
150
- };
151
- var MissingIdentityError = class extends Error {
152
- constructor(message = "Identity is not available in this environment") {
153
- super(message);
154
- this.name = "MissingIdentityError";
314
+ const serverJwt = getServerCookie(NF_JWT_COOKIE);
315
+ if (serverJwt) {
316
+ const claims = decodeJwtPayload(serverJwt);
317
+ if (claims) return claimsToUser(claims);
155
318
  }
319
+ return null;
156
320
  };
321
+ var isAuthenticated = () => getUser() !== null;
157
322
 
158
323
  // src/config.ts
159
324
  var getIdentityConfig = () => {
@@ -163,8 +328,7 @@ var getIdentityConfig = () => {
163
328
  return getIdentityContext();
164
329
  };
165
330
  var getSettings = async () => {
166
- const client = getGoTrueClient();
167
- if (!client) throw new MissingIdentityError();
331
+ const client = getClient();
168
332
  try {
169
333
  const raw = await client.settings();
170
334
  const external = raw.external ?? {};
@@ -185,13 +349,573 @@ var getSettings = async () => {
185
349
  throw new AuthError(err instanceof Error ? err.message : "Failed to fetch identity settings", 502, { cause: err });
186
350
  }
187
351
  };
352
+
353
+ // src/events.ts
354
+ var AUTH_EVENTS = {
355
+ LOGIN: "login",
356
+ LOGOUT: "logout",
357
+ TOKEN_REFRESH: "token_refresh",
358
+ USER_UPDATED: "user_updated",
359
+ RECOVERY: "recovery"
360
+ };
361
+ var GOTRUE_STORAGE_KEY = "gotrue.user";
362
+ var listeners = /* @__PURE__ */ new Set();
363
+ var emitAuthEvent = (event, user) => {
364
+ for (const listener of listeners) {
365
+ try {
366
+ listener(event, user);
367
+ } catch {
368
+ }
369
+ }
370
+ };
371
+ var storageListenerAttached = false;
372
+ var attachStorageListener = () => {
373
+ if (storageListenerAttached || !isBrowser()) return;
374
+ storageListenerAttached = true;
375
+ window.addEventListener("storage", (event) => {
376
+ if (event.key !== GOTRUE_STORAGE_KEY) return;
377
+ if (event.newValue) {
378
+ const client = getGoTrueClient();
379
+ const currentUser = client?.currentUser();
380
+ emitAuthEvent(AUTH_EVENTS.LOGIN, currentUser ? toUser(currentUser) : null);
381
+ } else {
382
+ emitAuthEvent(AUTH_EVENTS.LOGOUT, null);
383
+ }
384
+ });
385
+ };
386
+ var onAuthChange = (callback) => {
387
+ if (!isBrowser()) {
388
+ return () => {
389
+ };
390
+ }
391
+ listeners.add(callback);
392
+ attachStorageListener();
393
+ return () => {
394
+ listeners.delete(callback);
395
+ };
396
+ };
397
+
398
+ // src/auth.ts
399
+ var getCookies = () => {
400
+ const cookies = globalThis.Netlify?.context?.cookies;
401
+ if (!cookies) {
402
+ throw new AuthError("Server-side auth requires Netlify Functions runtime");
403
+ }
404
+ return cookies;
405
+ };
406
+ var getServerIdentityUrl = () => {
407
+ const ctx = getIdentityContext();
408
+ if (!ctx?.url) {
409
+ throw new AuthError("Could not determine the Identity endpoint URL on the server");
410
+ }
411
+ return ctx.url;
412
+ };
413
+ var persistSession = true;
414
+ var login = async (email, password) => {
415
+ if (!isBrowser()) {
416
+ const identityUrl = getServerIdentityUrl();
417
+ const cookies = getCookies();
418
+ const body = new URLSearchParams({
419
+ grant_type: "password",
420
+ username: email,
421
+ password
422
+ });
423
+ let res;
424
+ try {
425
+ res = await fetch(`${identityUrl}/token`, {
426
+ method: "POST",
427
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
428
+ body: body.toString()
429
+ });
430
+ } catch (error) {
431
+ throw new AuthError(error.message, void 0, { cause: error });
432
+ }
433
+ if (!res.ok) {
434
+ const errorBody = await res.json().catch(() => ({}));
435
+ throw new AuthError(errorBody.msg || errorBody.error_description || `Login failed (${res.status})`, res.status);
436
+ }
437
+ const data = await res.json();
438
+ const accessToken = data.access_token;
439
+ let userRes;
440
+ try {
441
+ userRes = await fetch(`${identityUrl}/user`, {
442
+ headers: { Authorization: `Bearer ${accessToken}` }
443
+ });
444
+ } catch (error) {
445
+ throw new AuthError(error.message, void 0, { cause: error });
446
+ }
447
+ if (!userRes.ok) {
448
+ const errorBody = await userRes.json().catch(() => ({}));
449
+ throw new AuthError(errorBody.msg || `Failed to fetch user data (${userRes.status})`, userRes.status);
450
+ }
451
+ const userData = await userRes.json();
452
+ const user = toUser(userData);
453
+ setAuthCookies(cookies, accessToken, data.refresh_token);
454
+ return user;
455
+ }
456
+ const client = getClient();
457
+ try {
458
+ const gotrueUser = await client.login(email, password, persistSession);
459
+ const jwt = await gotrueUser.jwt();
460
+ setBrowserAuthCookies(jwt);
461
+ const user = toUser(gotrueUser);
462
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
463
+ return user;
464
+ } catch (error) {
465
+ throw new AuthError(error.message, void 0, { cause: error });
466
+ }
467
+ };
468
+ var signup = async (email, password, data) => {
469
+ if (!isBrowser()) {
470
+ const identityUrl = getServerIdentityUrl();
471
+ const cookies = getCookies();
472
+ let res;
473
+ try {
474
+ res = await fetch(`${identityUrl}/signup`, {
475
+ method: "POST",
476
+ headers: { "Content-Type": "application/json" },
477
+ body: JSON.stringify({ email, password, data })
478
+ });
479
+ } catch (error) {
480
+ throw new AuthError(error.message, void 0, { cause: error });
481
+ }
482
+ if (!res.ok) {
483
+ const errorBody = await res.json().catch(() => ({}));
484
+ throw new AuthError(errorBody.msg || `Signup failed (${res.status})`, res.status);
485
+ }
486
+ const responseData = await res.json();
487
+ const user = toUser(responseData);
488
+ if (responseData.confirmed_at) {
489
+ const accessToken = responseData.access_token;
490
+ if (accessToken) {
491
+ setAuthCookies(cookies, accessToken, responseData.refresh_token);
492
+ }
493
+ }
494
+ return user;
495
+ }
496
+ const client = getClient();
497
+ try {
498
+ const response = await client.signup(email, password, data);
499
+ const user = toUser(response);
500
+ if (response.confirmed_at) {
501
+ const jwt = await response.jwt?.();
502
+ if (jwt) {
503
+ setBrowserAuthCookies(jwt);
504
+ }
505
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
506
+ }
507
+ return user;
508
+ } catch (error) {
509
+ throw new AuthError(error.message, void 0, { cause: error });
510
+ }
511
+ };
512
+ var logout = async () => {
513
+ if (!isBrowser()) {
514
+ const identityUrl = getServerIdentityUrl();
515
+ const cookies = getCookies();
516
+ const jwt = cookies.get(NF_JWT_COOKIE);
517
+ if (jwt) {
518
+ try {
519
+ await fetch(`${identityUrl}/logout`, {
520
+ method: "POST",
521
+ headers: { Authorization: `Bearer ${jwt}` }
522
+ });
523
+ } catch {
524
+ }
525
+ }
526
+ deleteAuthCookies(cookies);
527
+ return;
528
+ }
529
+ const client = getClient();
530
+ try {
531
+ const currentUser = client.currentUser();
532
+ if (currentUser) {
533
+ await currentUser.logout();
534
+ }
535
+ deleteBrowserAuthCookies();
536
+ emitAuthEvent(AUTH_EVENTS.LOGOUT, null);
537
+ } catch (error) {
538
+ throw new AuthError(error.message, void 0, { cause: error });
539
+ }
540
+ };
541
+ var oauthLogin = (provider) => {
542
+ if (!isBrowser()) {
543
+ throw new AuthError("oauthLogin() is only available in the browser");
544
+ }
545
+ const client = getClient();
546
+ window.location.href = client.loginExternalUrl(provider);
547
+ throw new AuthError("Redirecting to OAuth provider");
548
+ };
549
+ var handleAuthCallback = async () => {
550
+ if (!isBrowser()) return null;
551
+ const hash = window.location.hash.substring(1);
552
+ if (!hash) return null;
553
+ const client = getClient();
554
+ const params = new URLSearchParams(hash);
555
+ try {
556
+ const accessToken = params.get("access_token");
557
+ if (accessToken) return await handleOAuthCallback(client, params, accessToken);
558
+ const confirmationToken = params.get("confirmation_token");
559
+ if (confirmationToken) return await handleConfirmationCallback(client, confirmationToken);
560
+ const recoveryToken = params.get("recovery_token");
561
+ if (recoveryToken) return await handleRecoveryCallback(client, recoveryToken);
562
+ const inviteToken = params.get("invite_token");
563
+ if (inviteToken) return handleInviteCallback(inviteToken);
564
+ const emailChangeToken = params.get("email_change_token");
565
+ if (emailChangeToken) return await handleEmailChangeCallback(client, emailChangeToken);
566
+ return null;
567
+ } catch (error) {
568
+ if (error instanceof AuthError) throw error;
569
+ throw new AuthError(error.message, void 0, { cause: error });
570
+ }
571
+ };
572
+ var handleOAuthCallback = async (client, params, accessToken) => {
573
+ const refreshToken = params.get("refresh_token") ?? "";
574
+ const gotrueUser = await client.createUser(
575
+ {
576
+ access_token: accessToken,
577
+ token_type: params.get("token_type") ?? "bearer",
578
+ expires_in: Number(params.get("expires_in")),
579
+ expires_at: Number(params.get("expires_at")),
580
+ refresh_token: refreshToken
581
+ },
582
+ persistSession
583
+ );
584
+ setBrowserAuthCookies(accessToken, refreshToken || void 0);
585
+ const user = toUser(gotrueUser);
586
+ clearHash();
587
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
588
+ return { type: "oauth", user };
589
+ };
590
+ var handleConfirmationCallback = async (client, token) => {
591
+ const gotrueUser = await client.confirm(token, persistSession);
592
+ const jwt = await gotrueUser.jwt();
593
+ setBrowserAuthCookies(jwt);
594
+ const user = toUser(gotrueUser);
595
+ clearHash();
596
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
597
+ return { type: "confirmation", user };
598
+ };
599
+ var handleRecoveryCallback = async (client, token) => {
600
+ const gotrueUser = await client.recover(token, persistSession);
601
+ const jwt = await gotrueUser.jwt();
602
+ setBrowserAuthCookies(jwt);
603
+ const user = toUser(gotrueUser);
604
+ clearHash();
605
+ emitAuthEvent(AUTH_EVENTS.RECOVERY, user);
606
+ return { type: "recovery", user };
607
+ };
608
+ var handleInviteCallback = (token) => {
609
+ clearHash();
610
+ return { type: "invite", user: null, token };
611
+ };
612
+ var handleEmailChangeCallback = async (client, emailChangeToken) => {
613
+ const currentUser = client.currentUser();
614
+ if (!currentUser) {
615
+ throw new AuthError("Email change verification requires an active browser session");
616
+ }
617
+ const jwt = await currentUser.jwt();
618
+ const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
619
+ const emailChangeRes = await fetch(`${identityUrl}/user`, {
620
+ method: "PUT",
621
+ headers: {
622
+ "Content-Type": "application/json",
623
+ Authorization: `Bearer ${jwt}`
624
+ },
625
+ body: JSON.stringify({ email_change_token: emailChangeToken })
626
+ });
627
+ if (!emailChangeRes.ok) {
628
+ const errorBody = await emailChangeRes.json().catch(() => ({}));
629
+ throw new AuthError(
630
+ errorBody.msg || `Email change verification failed (${emailChangeRes.status})`,
631
+ emailChangeRes.status
632
+ );
633
+ }
634
+ const emailChangeData = await emailChangeRes.json();
635
+ const user = toUser(emailChangeData);
636
+ clearHash();
637
+ emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user);
638
+ return { type: "email_change", user };
639
+ };
640
+ var clearHash = () => {
641
+ history.replaceState(null, "", window.location.pathname + window.location.search);
642
+ };
643
+ var hydrateSession = async () => {
644
+ if (!isBrowser()) return null;
645
+ const client = getClient();
646
+ const currentUser = client.currentUser();
647
+ if (currentUser) return toUser(currentUser);
648
+ const accessToken = getCookie(NF_JWT_COOKIE);
649
+ if (!accessToken) return null;
650
+ const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
651
+ const decoded = decodeJwtPayload(accessToken);
652
+ const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1e3) + 3600;
653
+ const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1e3));
654
+ const gotrueUser = await client.createUser(
655
+ {
656
+ access_token: accessToken,
657
+ token_type: "bearer",
658
+ expires_in: expiresIn,
659
+ expires_at: expiresAt,
660
+ refresh_token: refreshToken
661
+ },
662
+ persistSession
663
+ );
664
+ const user = toUser(gotrueUser);
665
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
666
+ return user;
667
+ };
668
+
669
+ // src/account.ts
670
+ var resolveCurrentUser = async () => {
671
+ const client = getClient();
672
+ let currentUser = client.currentUser();
673
+ if (!currentUser && isBrowser()) {
674
+ try {
675
+ await hydrateSession();
676
+ } catch {
677
+ }
678
+ currentUser = client.currentUser();
679
+ }
680
+ if (!currentUser) throw new AuthError("No user is currently logged in");
681
+ return currentUser;
682
+ };
683
+ var requestPasswordRecovery = async (email) => {
684
+ const client = getClient();
685
+ try {
686
+ await client.requestPasswordRecovery(email);
687
+ } catch (error) {
688
+ throw new AuthError(error.message, void 0, { cause: error });
689
+ }
690
+ };
691
+ var recoverPassword = async (token, newPassword) => {
692
+ const client = getClient();
693
+ try {
694
+ const gotrueUser = await client.recover(token, persistSession);
695
+ const updatedUser = await gotrueUser.update({ password: newPassword });
696
+ const user = toUser(updatedUser);
697
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
698
+ return user;
699
+ } catch (error) {
700
+ throw new AuthError(error.message, void 0, { cause: error });
701
+ }
702
+ };
703
+ var confirmEmail = async (token) => {
704
+ const client = getClient();
705
+ try {
706
+ const gotrueUser = await client.confirm(token, persistSession);
707
+ const user = toUser(gotrueUser);
708
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
709
+ return user;
710
+ } catch (error) {
711
+ throw new AuthError(error.message, void 0, { cause: error });
712
+ }
713
+ };
714
+ var acceptInvite = async (token, password) => {
715
+ const client = getClient();
716
+ try {
717
+ const gotrueUser = await client.acceptInvite(token, password, persistSession);
718
+ const user = toUser(gotrueUser);
719
+ emitAuthEvent(AUTH_EVENTS.LOGIN, user);
720
+ return user;
721
+ } catch (error) {
722
+ throw new AuthError(error.message, void 0, { cause: error });
723
+ }
724
+ };
725
+ var verifyEmailChange = async (token) => {
726
+ if (!isBrowser()) throw new AuthError("verifyEmailChange() is only available in the browser");
727
+ const currentUser = await resolveCurrentUser();
728
+ const jwt = await currentUser.jwt();
729
+ const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
730
+ try {
731
+ const res = await fetch(`${identityUrl}/user`, {
732
+ method: "PUT",
733
+ headers: {
734
+ "Content-Type": "application/json",
735
+ Authorization: `Bearer ${jwt}`
736
+ },
737
+ body: JSON.stringify({ email_change_token: token })
738
+ });
739
+ if (!res.ok) {
740
+ const errorBody = await res.json().catch(() => ({}));
741
+ throw new AuthError(errorBody.msg || `Email change verification failed (${res.status})`, res.status);
742
+ }
743
+ const userData = await res.json();
744
+ const user = toUser(userData);
745
+ emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user);
746
+ return user;
747
+ } catch (error) {
748
+ if (error instanceof AuthError) throw error;
749
+ throw new AuthError(error.message, void 0, { cause: error });
750
+ }
751
+ };
752
+ var updateUser = async (updates) => {
753
+ const currentUser = await resolveCurrentUser();
754
+ try {
755
+ const updatedUser = await currentUser.update(updates);
756
+ const user = toUser(updatedUser);
757
+ emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user);
758
+ return user;
759
+ } catch (error) {
760
+ throw new AuthError(error.message, void 0, { cause: error });
761
+ }
762
+ };
763
+
764
+ // src/admin.ts
765
+ var getAdminAuth = () => {
766
+ const ctx = getIdentityContext();
767
+ if (!ctx?.url) {
768
+ throw new AuthError("Could not determine the Identity endpoint URL on the server");
769
+ }
770
+ if (!ctx.token) {
771
+ throw new AuthError("Admin operations require an operator token (only available in Netlify Functions)");
772
+ }
773
+ return { url: ctx.url, token: ctx.token };
774
+ };
775
+ var adminFetch = async (path, options = {}) => {
776
+ const { url, token } = getAdminAuth();
777
+ let res;
778
+ try {
779
+ res = await fetch(`${url}${path}`, {
780
+ ...options,
781
+ headers: {
782
+ ...options.headers,
783
+ Authorization: `Bearer ${token}`,
784
+ "Content-Type": "application/json"
785
+ }
786
+ });
787
+ } catch (error) {
788
+ throw new AuthError(error.message, void 0, { cause: error });
789
+ }
790
+ if (!res.ok) {
791
+ const errorBody = await res.json().catch(() => ({}));
792
+ throw new AuthError(errorBody.msg || `Admin request failed (${res.status})`, res.status);
793
+ }
794
+ return res;
795
+ };
796
+ var getAdminUser = () => {
797
+ const client = getClient();
798
+ const user = client.currentUser();
799
+ if (!user) {
800
+ throw new AuthError("Admin operations require a logged-in user with admin role");
801
+ }
802
+ return user;
803
+ };
804
+ var listUsers = async (options) => {
805
+ if (!isBrowser()) {
806
+ const params = new URLSearchParams();
807
+ if (options?.page != null) params.set("page", String(options.page));
808
+ if (options?.perPage != null) params.set("per_page", String(options.perPage));
809
+ const query = params.toString();
810
+ const path = `/admin/users${query ? `?${query}` : ""}`;
811
+ const res = await adminFetch(path);
812
+ const body = await res.json();
813
+ return body.users.map(toUser);
814
+ }
815
+ try {
816
+ const user = getAdminUser();
817
+ const users = await user.admin.listUsers("");
818
+ return users.map(toUser);
819
+ } catch (error) {
820
+ if (error instanceof AuthError) throw error;
821
+ throw new AuthError(error.message, void 0, { cause: error });
822
+ }
823
+ };
824
+ var getUser2 = async (userId) => {
825
+ if (!isBrowser()) {
826
+ const res = await adminFetch(`/admin/users/${userId}`);
827
+ const userData = await res.json();
828
+ return toUser(userData);
829
+ }
830
+ try {
831
+ const user = getAdminUser();
832
+ const userData = await user.admin.getUser({ id: userId });
833
+ return toUser(userData);
834
+ } catch (error) {
835
+ if (error instanceof AuthError) throw error;
836
+ throw new AuthError(error.message, void 0, { cause: error });
837
+ }
838
+ };
839
+ var createUser = async (params) => {
840
+ if (!isBrowser()) {
841
+ const res = await adminFetch("/admin/users", {
842
+ method: "POST",
843
+ body: JSON.stringify({
844
+ email: params.email,
845
+ password: params.password,
846
+ ...params.data,
847
+ confirm: true
848
+ })
849
+ });
850
+ const userData = await res.json();
851
+ return toUser(userData);
852
+ }
853
+ try {
854
+ const user = getAdminUser();
855
+ const userData = await user.admin.createUser(params.email, params.password, {
856
+ ...params.data,
857
+ confirm: true
858
+ });
859
+ return toUser(userData);
860
+ } catch (error) {
861
+ if (error instanceof AuthError) throw error;
862
+ throw new AuthError(error.message, void 0, { cause: error });
863
+ }
864
+ };
865
+ var updateUser2 = async (userId, attributes) => {
866
+ if (!isBrowser()) {
867
+ const res = await adminFetch(`/admin/users/${userId}`, {
868
+ method: "PUT",
869
+ body: JSON.stringify(attributes)
870
+ });
871
+ const userData = await res.json();
872
+ return toUser(userData);
873
+ }
874
+ try {
875
+ const user = getAdminUser();
876
+ const userData = await user.admin.updateUser({ id: userId }, attributes);
877
+ return toUser(userData);
878
+ } catch (error) {
879
+ if (error instanceof AuthError) throw error;
880
+ throw new AuthError(error.message, void 0, { cause: error });
881
+ }
882
+ };
883
+ var deleteUser = async (userId) => {
884
+ if (!isBrowser()) {
885
+ await adminFetch(`/admin/users/${userId}`, { method: "DELETE" });
886
+ return;
887
+ }
888
+ try {
889
+ const user = getAdminUser();
890
+ await user.admin.deleteUser({ id: userId });
891
+ } catch (error) {
892
+ if (error instanceof AuthError) throw error;
893
+ throw new AuthError(error.message, void 0, { cause: error });
894
+ }
895
+ };
896
+ var admin = { listUsers, getUser: getUser2, createUser, updateUser: updateUser2, deleteUser };
188
897
  // Annotate the CommonJS export names for ESM import in node:
189
898
  0 && (module.exports = {
899
+ AUTH_EVENTS,
190
900
  AuthError,
191
901
  MissingIdentityError,
902
+ acceptInvite,
903
+ admin,
904
+ confirmEmail,
192
905
  getIdentityConfig,
193
906
  getSettings,
194
907
  getUser,
195
- isAuthenticated
908
+ handleAuthCallback,
909
+ hydrateSession,
910
+ isAuthenticated,
911
+ login,
912
+ logout,
913
+ oauthLogin,
914
+ onAuthChange,
915
+ recoverPassword,
916
+ requestPasswordRecovery,
917
+ signup,
918
+ updateUser,
919
+ verifyEmailChange
196
920
  });
197
921
  //# sourceMappingURL=index.cjs.map