@netlify/identity 0.3.0-alpha.3 → 0.3.0-alpha.5

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.js CHANGED
@@ -12,7 +12,7 @@ var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "sa
12
12
  import GoTrue from "gotrue-js";
13
13
 
14
14
  // src/errors.ts
15
- var AuthError = class extends Error {
15
+ var AuthError = class _AuthError extends Error {
16
16
  constructor(message, status, options) {
17
17
  super(message);
18
18
  this.name = "AuthError";
@@ -21,6 +21,10 @@ var AuthError = class extends Error {
21
21
  this.cause = options.cause;
22
22
  }
23
23
  }
24
+ static from(error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ return new _AuthError(message, void 0, { cause: error });
27
+ }
24
28
  };
25
29
  var MissingIdentityError = class extends Error {
26
30
  constructor(message = "Netlify Identity is not available.") {
@@ -45,7 +49,7 @@ var discoverApiUrl = () => {
45
49
  cachedApiUrl = identityContext.url;
46
50
  } else if (globalThis.Netlify?.context?.url) {
47
51
  cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href;
48
- } else if (process.env.URL) {
52
+ } else if (typeof process !== "undefined" && process.env?.URL) {
49
53
  cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href;
50
54
  }
51
55
  }
@@ -82,7 +86,7 @@ var getIdentityContext = () => {
82
86
  if (globalThis.Netlify?.context?.url) {
83
87
  return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href };
84
88
  }
85
- const siteUrl = process.env.URL;
89
+ const siteUrl = typeof process !== "undefined" ? process.env?.URL : void 0;
86
90
  if (siteUrl) {
87
91
  return { url: new URL(IDENTITY_PATH, siteUrl).href };
88
92
  }
@@ -94,7 +98,12 @@ var NF_JWT_COOKIE = "nf_jwt";
94
98
  var NF_REFRESH_COOKIE = "nf_refresh";
95
99
  var getCookie = (name) => {
96
100
  const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`));
97
- return match ? decodeURIComponent(match[1]) : null;
101
+ if (!match) return null;
102
+ try {
103
+ return decodeURIComponent(match[1]);
104
+ } catch {
105
+ return match[1];
106
+ }
98
107
  };
99
108
  var setAuthCookies = (cookies, accessToken, refreshToken) => {
100
109
  cookies.set({
@@ -164,143 +173,6 @@ var triggerNextjsDynamic = () => {
164
173
  }
165
174
  };
166
175
 
167
- // src/user.ts
168
- var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
169
- var toUser = (userData) => {
170
- const userMeta = userData.user_metadata ?? {};
171
- const appMeta = userData.app_metadata ?? {};
172
- const name = userMeta.full_name || userMeta.name;
173
- const pictureUrl = userMeta.avatar_url;
174
- return {
175
- id: userData.id,
176
- email: userData.email,
177
- emailVerified: !!userData.confirmed_at,
178
- createdAt: userData.created_at,
179
- updatedAt: userData.updated_at,
180
- provider: toAuthProvider(appMeta.provider),
181
- name: typeof name === "string" ? name : void 0,
182
- pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
183
- metadata: userMeta,
184
- rawGoTrueData: { ...userData }
185
- };
186
- };
187
- var claimsToUser = (claims) => {
188
- const appMeta = claims.app_metadata ?? {};
189
- const userMeta = claims.user_metadata ?? {};
190
- const name = userMeta.full_name || userMeta.name;
191
- return {
192
- id: claims.sub ?? "",
193
- email: claims.email,
194
- provider: toAuthProvider(appMeta.provider),
195
- name: typeof name === "string" ? name : void 0,
196
- metadata: userMeta
197
- };
198
- };
199
- var hydrating = false;
200
- var backgroundHydrate = (accessToken) => {
201
- if (hydrating) return;
202
- hydrating = true;
203
- const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
204
- const decoded = decodeJwtPayload(accessToken);
205
- const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1e3) + 3600;
206
- const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1e3));
207
- setTimeout(() => {
208
- try {
209
- const client = getClient();
210
- client.createUser(
211
- {
212
- access_token: accessToken,
213
- token_type: "bearer",
214
- expires_in: expiresIn,
215
- expires_at: expiresAt,
216
- refresh_token: refreshToken
217
- },
218
- true
219
- ).catch(() => {
220
- }).finally(() => {
221
- hydrating = false;
222
- });
223
- } catch {
224
- hydrating = false;
225
- }
226
- }, 0);
227
- };
228
- var decodeJwtPayload = (token) => {
229
- try {
230
- const parts = token.split(".");
231
- if (parts.length !== 3) return null;
232
- const payload = atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"));
233
- return JSON.parse(payload);
234
- } catch {
235
- return null;
236
- }
237
- };
238
- var getUser = () => {
239
- if (isBrowser()) {
240
- const client = getGoTrueClient();
241
- const currentUser = client?.currentUser() ?? null;
242
- if (currentUser) {
243
- const jwt2 = getCookie(NF_JWT_COOKIE);
244
- if (!jwt2) {
245
- try {
246
- currentUser.clearSession();
247
- } catch {
248
- }
249
- return null;
250
- }
251
- return toUser(currentUser);
252
- }
253
- const jwt = getCookie(NF_JWT_COOKIE);
254
- if (!jwt) return null;
255
- const claims = decodeJwtPayload(jwt);
256
- if (!claims) return null;
257
- backgroundHydrate(jwt);
258
- return claimsToUser(claims);
259
- }
260
- triggerNextjsDynamic();
261
- const identityContext = globalThis.netlifyIdentityContext;
262
- if (identityContext?.user) {
263
- return claimsToUser(identityContext.user);
264
- }
265
- const serverJwt = getServerCookie(NF_JWT_COOKIE);
266
- if (serverJwt) {
267
- const claims = decodeJwtPayload(serverJwt);
268
- if (claims) return claimsToUser(claims);
269
- }
270
- return null;
271
- };
272
- var isAuthenticated = () => getUser() !== null;
273
-
274
- // src/config.ts
275
- var getIdentityConfig = () => {
276
- if (isBrowser()) {
277
- return { url: `${window.location.origin}${IDENTITY_PATH}` };
278
- }
279
- return getIdentityContext();
280
- };
281
- var getSettings = async () => {
282
- const client = getClient();
283
- try {
284
- const raw = await client.settings();
285
- const external = raw.external ?? {};
286
- return {
287
- autoconfirm: raw.autoconfirm,
288
- disableSignup: raw.disable_signup,
289
- providers: {
290
- google: external.google ?? false,
291
- github: external.github ?? false,
292
- gitlab: external.gitlab ?? false,
293
- bitbucket: external.bitbucket ?? false,
294
- facebook: external.facebook ?? false,
295
- email: external.email ?? false,
296
- saml: external.saml ?? false
297
- }
298
- };
299
- } catch (err) {
300
- throw new AuthError(err instanceof Error ? err.message : "Failed to fetch identity settings", 502, { cause: err });
301
- }
302
- };
303
-
304
176
  // src/events.ts
305
177
  var AUTH_EVENTS = {
306
178
  LOGIN: "login",
@@ -379,7 +251,7 @@ var login = async (email, password) => {
379
251
  body: body.toString()
380
252
  });
381
253
  } catch (error) {
382
- throw new AuthError(error.message, void 0, { cause: error });
254
+ throw AuthError.from(error);
383
255
  }
384
256
  if (!res.ok) {
385
257
  const errorBody = await res.json().catch(() => ({}));
@@ -393,7 +265,7 @@ var login = async (email, password) => {
393
265
  headers: { Authorization: `Bearer ${accessToken}` }
394
266
  });
395
267
  } catch (error) {
396
- throw new AuthError(error.message, void 0, { cause: error });
268
+ throw AuthError.from(error);
397
269
  }
398
270
  if (!userRes.ok) {
399
271
  const errorBody = await userRes.json().catch(() => ({}));
@@ -413,7 +285,7 @@ var login = async (email, password) => {
413
285
  emitAuthEvent(AUTH_EVENTS.LOGIN, user);
414
286
  return user;
415
287
  } catch (error) {
416
- throw new AuthError(error.message, void 0, { cause: error });
288
+ throw AuthError.from(error);
417
289
  }
418
290
  };
419
291
  var signup = async (email, password, data) => {
@@ -428,7 +300,7 @@ var signup = async (email, password, data) => {
428
300
  body: JSON.stringify({ email, password, data })
429
301
  });
430
302
  } catch (error) {
431
- throw new AuthError(error.message, void 0, { cause: error });
303
+ throw AuthError.from(error);
432
304
  }
433
305
  if (!res.ok) {
434
306
  const errorBody = await res.json().catch(() => ({}));
@@ -457,7 +329,7 @@ var signup = async (email, password, data) => {
457
329
  }
458
330
  return user;
459
331
  } catch (error) {
460
- throw new AuthError(error.message, void 0, { cause: error });
332
+ throw AuthError.from(error);
461
333
  }
462
334
  };
463
335
  var logout = async () => {
@@ -486,7 +358,7 @@ var logout = async () => {
486
358
  deleteBrowserAuthCookies();
487
359
  emitAuthEvent(AUTH_EVENTS.LOGOUT, null);
488
360
  } catch (error) {
489
- throw new AuthError(error.message, void 0, { cause: error });
361
+ throw AuthError.from(error);
490
362
  }
491
363
  };
492
364
  var oauthLogin = (provider) => {
@@ -517,7 +389,7 @@ var handleAuthCallback = async () => {
517
389
  return null;
518
390
  } catch (error) {
519
391
  if (error instanceof AuthError) throw error;
520
- throw new AuthError(error.message, void 0, { cause: error });
392
+ throw AuthError.from(error);
521
393
  }
522
394
  };
523
395
  var handleOAuthCallback = async (client, params, accessToken) => {
@@ -602,21 +474,172 @@ var hydrateSession = async () => {
602
474
  const decoded = decodeJwtPayload(accessToken);
603
475
  const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1e3) + 3600;
604
476
  const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1e3));
605
- const gotrueUser = await client.createUser(
606
- {
607
- access_token: accessToken,
608
- token_type: "bearer",
609
- expires_in: expiresIn,
610
- expires_at: expiresAt,
611
- refresh_token: refreshToken
612
- },
613
- persistSession
614
- );
477
+ let gotrueUser;
478
+ try {
479
+ gotrueUser = await client.createUser(
480
+ {
481
+ access_token: accessToken,
482
+ token_type: "bearer",
483
+ expires_in: expiresIn,
484
+ expires_at: expiresAt,
485
+ refresh_token: refreshToken
486
+ },
487
+ persistSession
488
+ );
489
+ } catch {
490
+ deleteBrowserAuthCookies();
491
+ return null;
492
+ }
615
493
  const user = toUser(gotrueUser);
616
494
  emitAuthEvent(AUTH_EVENTS.LOGIN, user);
617
495
  return user;
618
496
  };
619
497
 
498
+ // src/user.ts
499
+ var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
500
+ var toRoles = (appMeta) => {
501
+ const roles = appMeta.roles;
502
+ if (Array.isArray(roles) && roles.every((r) => typeof r === "string")) {
503
+ return roles;
504
+ }
505
+ return void 0;
506
+ };
507
+ var toUser = (userData) => {
508
+ const userMeta = userData.user_metadata ?? {};
509
+ const appMeta = userData.app_metadata ?? {};
510
+ const name = userMeta.full_name || userMeta.name;
511
+ const pictureUrl = userMeta.avatar_url;
512
+ return {
513
+ id: userData.id,
514
+ email: userData.email,
515
+ emailVerified: !!userData.confirmed_at,
516
+ createdAt: userData.created_at,
517
+ updatedAt: userData.updated_at,
518
+ provider: toAuthProvider(appMeta.provider),
519
+ name: typeof name === "string" ? name : void 0,
520
+ pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
521
+ roles: toRoles(appMeta),
522
+ metadata: userMeta,
523
+ rawGoTrueData: { ...userData }
524
+ };
525
+ };
526
+ var claimsToUser = (claims) => {
527
+ const appMeta = claims.app_metadata ?? {};
528
+ const userMeta = claims.user_metadata ?? {};
529
+ const name = userMeta.full_name || userMeta.name;
530
+ const pictureUrl = userMeta.avatar_url;
531
+ return {
532
+ id: claims.sub ?? "",
533
+ email: claims.email,
534
+ provider: toAuthProvider(appMeta.provider),
535
+ name: typeof name === "string" ? name : void 0,
536
+ pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
537
+ roles: toRoles(appMeta),
538
+ metadata: userMeta
539
+ };
540
+ };
541
+ var decodeJwtPayload = (token) => {
542
+ try {
543
+ const parts = token.split(".");
544
+ if (parts.length !== 3) return null;
545
+ const payload = atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"));
546
+ return JSON.parse(payload);
547
+ } catch {
548
+ return null;
549
+ }
550
+ };
551
+ var fetchFullUser = async (identityUrl, jwt) => {
552
+ try {
553
+ const res = await fetch(`${identityUrl}/user`, {
554
+ headers: { Authorization: `Bearer ${jwt}` }
555
+ });
556
+ if (!res.ok) return null;
557
+ const userData = await res.json();
558
+ return toUser(userData);
559
+ } catch {
560
+ return null;
561
+ }
562
+ };
563
+ var resolveIdentityUrl = () => {
564
+ const identityContext = getIdentityContext();
565
+ if (identityContext?.url) return identityContext.url;
566
+ if (globalThis.Netlify?.context?.url) {
567
+ return new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href;
568
+ }
569
+ const siteUrl = typeof process !== "undefined" ? process.env?.URL : void 0;
570
+ if (siteUrl) {
571
+ return new URL(IDENTITY_PATH, siteUrl).href;
572
+ }
573
+ return null;
574
+ };
575
+ var getUser = async () => {
576
+ if (isBrowser()) {
577
+ const client = getGoTrueClient();
578
+ const currentUser = client?.currentUser() ?? null;
579
+ if (currentUser) {
580
+ const jwt2 = getCookie(NF_JWT_COOKIE);
581
+ if (!jwt2) {
582
+ try {
583
+ currentUser.clearSession();
584
+ } catch {
585
+ }
586
+ return null;
587
+ }
588
+ return toUser(currentUser);
589
+ }
590
+ const jwt = getCookie(NF_JWT_COOKIE);
591
+ if (!jwt) return null;
592
+ const claims2 = decodeJwtPayload(jwt);
593
+ if (!claims2) return null;
594
+ const hydrated = await hydrateSession();
595
+ if (hydrated) return hydrated;
596
+ return claimsToUser(claims2);
597
+ }
598
+ triggerNextjsDynamic();
599
+ const identityContext = globalThis.netlifyIdentityContext;
600
+ const serverJwt = identityContext?.token || getServerCookie(NF_JWT_COOKIE);
601
+ if (serverJwt) {
602
+ const identityUrl = resolveIdentityUrl();
603
+ if (identityUrl) {
604
+ const fullUser = await fetchFullUser(identityUrl, serverJwt);
605
+ if (fullUser) return fullUser;
606
+ }
607
+ }
608
+ const claims = identityContext?.user ?? (serverJwt ? decodeJwtPayload(serverJwt) : null);
609
+ return claims ? claimsToUser(claims) : null;
610
+ };
611
+ var isAuthenticated = async () => await getUser() !== null;
612
+
613
+ // src/config.ts
614
+ var getIdentityConfig = () => {
615
+ if (isBrowser()) {
616
+ return { url: `${window.location.origin}${IDENTITY_PATH}` };
617
+ }
618
+ return getIdentityContext();
619
+ };
620
+ var getSettings = async () => {
621
+ const client = getClient();
622
+ try {
623
+ const raw = await client.settings();
624
+ const external = raw.external ?? {};
625
+ return {
626
+ autoconfirm: raw.autoconfirm,
627
+ disableSignup: raw.disable_signup,
628
+ providers: {
629
+ google: external.google ?? false,
630
+ github: external.github ?? false,
631
+ gitlab: external.gitlab ?? false,
632
+ bitbucket: external.bitbucket ?? false,
633
+ facebook: external.facebook ?? false,
634
+ email: external.email ?? false,
635
+ saml: external.saml ?? false
636
+ }
637
+ };
638
+ } catch (err) {
639
+ throw new AuthError(err instanceof Error ? err.message : "Failed to fetch identity settings", 502, { cause: err });
640
+ }
641
+ };
642
+
620
643
  // src/account.ts
621
644
  var resolveCurrentUser = async () => {
622
645
  const client = getClient();
@@ -636,7 +659,7 @@ var requestPasswordRecovery = async (email) => {
636
659
  try {
637
660
  await client.requestPasswordRecovery(email);
638
661
  } catch (error) {
639
- throw new AuthError(error.message, void 0, { cause: error });
662
+ throw AuthError.from(error);
640
663
  }
641
664
  };
642
665
  var recoverPassword = async (token, newPassword) => {
@@ -648,7 +671,7 @@ var recoverPassword = async (token, newPassword) => {
648
671
  emitAuthEvent(AUTH_EVENTS.LOGIN, user);
649
672
  return user;
650
673
  } catch (error) {
651
- throw new AuthError(error.message, void 0, { cause: error });
674
+ throw AuthError.from(error);
652
675
  }
653
676
  };
654
677
  var confirmEmail = async (token) => {
@@ -659,7 +682,7 @@ var confirmEmail = async (token) => {
659
682
  emitAuthEvent(AUTH_EVENTS.LOGIN, user);
660
683
  return user;
661
684
  } catch (error) {
662
- throw new AuthError(error.message, void 0, { cause: error });
685
+ throw AuthError.from(error);
663
686
  }
664
687
  };
665
688
  var acceptInvite = async (token, password) => {
@@ -670,15 +693,15 @@ var acceptInvite = async (token, password) => {
670
693
  emitAuthEvent(AUTH_EVENTS.LOGIN, user);
671
694
  return user;
672
695
  } catch (error) {
673
- throw new AuthError(error.message, void 0, { cause: error });
696
+ throw AuthError.from(error);
674
697
  }
675
698
  };
676
699
  var verifyEmailChange = async (token) => {
677
700
  if (!isBrowser()) throw new AuthError("verifyEmailChange() is only available in the browser");
678
701
  const currentUser = await resolveCurrentUser();
679
- const jwt = await currentUser.jwt();
680
- const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
681
702
  try {
703
+ const jwt = await currentUser.jwt();
704
+ const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
682
705
  const res = await fetch(`${identityUrl}/user`, {
683
706
  method: "PUT",
684
707
  headers: {
@@ -697,7 +720,7 @@ var verifyEmailChange = async (token) => {
697
720
  return user;
698
721
  } catch (error) {
699
722
  if (error instanceof AuthError) throw error;
700
- throw new AuthError(error.message, void 0, { cause: error });
723
+ throw AuthError.from(error);
701
724
  }
702
725
  };
703
726
  var updateUser = async (updates) => {
@@ -708,7 +731,7 @@ var updateUser = async (updates) => {
708
731
  emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user);
709
732
  return user;
710
733
  } catch (error) {
711
- throw new AuthError(error.message, void 0, { cause: error });
734
+ throw AuthError.from(error);
712
735
  }
713
736
  };
714
737