@netlify/identity 0.3.0-alpha.2 → 0.3.0-alpha.4
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/README.md +49 -4
- package/dist/index.cjs +44 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +223 -49
- package/dist/index.d.ts +223 -49
- package/dist/index.js +44 -29
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ A lightweight, no-config headless authentication library for projects using Netl
|
|
|
9
9
|
- [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) must be enabled on your Netlify project
|
|
10
10
|
- For local development, use [`netlify dev`](https://docs.netlify.com/cli/local-development/) so the Identity endpoint is available
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## How this library relates to other Netlify auth packages
|
|
13
13
|
|
|
14
14
|
| Package | What it is | When to use it |
|
|
15
15
|
| ------------------------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
@@ -26,7 +26,7 @@ This library wraps `gotrue-js` in the browser and calls the GoTrue HTTP API dire
|
|
|
26
26
|
- [API](#api)
|
|
27
27
|
- [Functions](#functions) -- `getUser`, `login`, `signup`, `logout`, `oauthLogin`, `handleAuthCallback`, `onAuthChange`, `hydrateSession`, and more
|
|
28
28
|
- [Admin Operations](#admin-operations) -- `admin.listUsers`, `admin.getUser`, `admin.createUser`, `admin.updateUser`, `admin.deleteUser`
|
|
29
|
-
- [Types](#types) -- `User`, `AuthEvent`, `CallbackResult`, `Settings`, etc.
|
|
29
|
+
- [Types](#types) -- `User`, `AuthEvent`, `CallbackResult`, `Settings`, `Admin`, `ListUsersOptions`, `CreateUserParams`, etc.
|
|
30
30
|
- [Errors](#errors) -- `AuthError`, `MissingIdentityError`
|
|
31
31
|
- [Framework integration](#framework-integration) -- Next.js, Remix, TanStack Start, Astro, SvelteKit
|
|
32
32
|
- [Guides](#guides)
|
|
@@ -312,7 +312,7 @@ export default async (req: Request, context: Context) => {
|
|
|
312
312
|
#### `admin.listUsers`
|
|
313
313
|
|
|
314
314
|
```ts
|
|
315
|
-
admin.listUsers(options?:
|
|
315
|
+
admin.listUsers(options?: ListUsersOptions): Promise<User[]>
|
|
316
316
|
```
|
|
317
317
|
|
|
318
318
|
Lists all users. Pagination options are supported on the server; they are ignored in the browser (gotrue-js does not support pagination for this method).
|
|
@@ -332,7 +332,7 @@ Gets a single user by ID.
|
|
|
332
332
|
#### `admin.createUser`
|
|
333
333
|
|
|
334
334
|
```ts
|
|
335
|
-
admin.createUser(params:
|
|
335
|
+
admin.createUser(params: CreateUserParams): Promise<User>
|
|
336
336
|
```
|
|
337
337
|
|
|
338
338
|
Creates a new user. The user is auto-confirmed. Optional `data` is spread into the request body as additional attributes.
|
|
@@ -450,6 +450,43 @@ interface AppMetadata {
|
|
|
450
450
|
}
|
|
451
451
|
```
|
|
452
452
|
|
|
453
|
+
#### `ListUsersOptions`
|
|
454
|
+
|
|
455
|
+
```ts
|
|
456
|
+
interface ListUsersOptions {
|
|
457
|
+
page?: number
|
|
458
|
+
perPage?: number
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Pagination options for `admin.listUsers()`. Only used on the server; pagination is ignored in the browser (gotrue-js limitation).
|
|
463
|
+
|
|
464
|
+
#### `CreateUserParams`
|
|
465
|
+
|
|
466
|
+
```ts
|
|
467
|
+
interface CreateUserParams {
|
|
468
|
+
email: string
|
|
469
|
+
password: string
|
|
470
|
+
data?: Record<string, unknown>
|
|
471
|
+
}
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Parameters for `admin.createUser()`. Optional `data` is spread into the GoTrue request body as top-level attributes (use it to set `app_metadata`, `user_metadata`, `role`, etc.).
|
|
475
|
+
|
|
476
|
+
#### `Admin`
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
interface Admin {
|
|
480
|
+
listUsers: (options?: ListUsersOptions) => Promise<User[]>
|
|
481
|
+
getUser: (userId: string) => Promise<User>
|
|
482
|
+
createUser: (params: CreateUserParams) => Promise<User>
|
|
483
|
+
updateUser: (userId: string, attributes: AdminUserUpdates) => Promise<User>
|
|
484
|
+
deleteUser: (userId: string) => Promise<void>
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
The type of the `admin` export. Useful for passing the admin namespace as a dependency.
|
|
489
|
+
|
|
453
490
|
#### `AUTH_EVENTS`
|
|
454
491
|
|
|
455
492
|
```ts
|
|
@@ -464,6 +501,14 @@ const AUTH_EVENTS: {
|
|
|
464
501
|
|
|
465
502
|
Constants for auth event names. Use these instead of string literals for type safety and autocomplete.
|
|
466
503
|
|
|
504
|
+
| Event | When it fires |
|
|
505
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
506
|
+
| `LOGIN` | `login()`, `signup()` (with autoconfirm), `recoverPassword()`, `handleAuthCallback()` (OAuth/confirmation), `hydrateSession()` |
|
|
507
|
+
| `LOGOUT` | `logout()` |
|
|
508
|
+
| `TOKEN_REFRESH` | gotrue-js refreshes an expiring access token in the background |
|
|
509
|
+
| `USER_UPDATED` | `updateUser()`, `verifyEmailChange()`, `handleAuthCallback()` (email change) |
|
|
510
|
+
| `RECOVERY` | `handleAuthCallback()` (recovery token only). The user is authenticated but has **not** set a new password yet. Listen for this to redirect to a password reset form. `recoverPassword()` emits `LOGIN` instead because it completes both steps (token redemption + password change). |
|
|
511
|
+
|
|
467
512
|
#### `AuthEvent`
|
|
468
513
|
|
|
469
514
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -61,7 +61,7 @@ var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "sa
|
|
|
61
61
|
var import_gotrue_js = __toESM(require("gotrue-js"), 1);
|
|
62
62
|
|
|
63
63
|
// src/errors.ts
|
|
64
|
-
var AuthError = class extends Error {
|
|
64
|
+
var AuthError = class _AuthError extends Error {
|
|
65
65
|
constructor(message, status, options) {
|
|
66
66
|
super(message);
|
|
67
67
|
this.name = "AuthError";
|
|
@@ -70,6 +70,10 @@ var AuthError = class extends Error {
|
|
|
70
70
|
this.cause = options.cause;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
static from(error) {
|
|
74
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
75
|
+
return new _AuthError(message, void 0, { cause: error });
|
|
76
|
+
}
|
|
73
77
|
};
|
|
74
78
|
var MissingIdentityError = class extends Error {
|
|
75
79
|
constructor(message = "Netlify Identity is not available.") {
|
|
@@ -94,7 +98,7 @@ var discoverApiUrl = () => {
|
|
|
94
98
|
cachedApiUrl = identityContext.url;
|
|
95
99
|
} else if (globalThis.Netlify?.context?.url) {
|
|
96
100
|
cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href;
|
|
97
|
-
} else if (process.env
|
|
101
|
+
} else if (typeof process !== "undefined" && process.env?.URL) {
|
|
98
102
|
cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href;
|
|
99
103
|
}
|
|
100
104
|
}
|
|
@@ -131,7 +135,7 @@ var getIdentityContext = () => {
|
|
|
131
135
|
if (globalThis.Netlify?.context?.url) {
|
|
132
136
|
return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href };
|
|
133
137
|
}
|
|
134
|
-
const siteUrl = process.env
|
|
138
|
+
const siteUrl = typeof process !== "undefined" ? process.env?.URL : void 0;
|
|
135
139
|
if (siteUrl) {
|
|
136
140
|
return { url: new URL(IDENTITY_PATH, siteUrl).href };
|
|
137
141
|
}
|
|
@@ -143,7 +147,12 @@ var NF_JWT_COOKIE = "nf_jwt";
|
|
|
143
147
|
var NF_REFRESH_COOKIE = "nf_refresh";
|
|
144
148
|
var getCookie = (name) => {
|
|
145
149
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`));
|
|
146
|
-
|
|
150
|
+
if (!match) return null;
|
|
151
|
+
try {
|
|
152
|
+
return decodeURIComponent(match[1]);
|
|
153
|
+
} catch {
|
|
154
|
+
return match[1];
|
|
155
|
+
}
|
|
147
156
|
};
|
|
148
157
|
var setAuthCookies = (cookies, accessToken, refreshToken) => {
|
|
149
158
|
cookies.set({
|
|
@@ -428,7 +437,7 @@ var login = async (email, password) => {
|
|
|
428
437
|
body: body.toString()
|
|
429
438
|
});
|
|
430
439
|
} catch (error) {
|
|
431
|
-
throw
|
|
440
|
+
throw AuthError.from(error);
|
|
432
441
|
}
|
|
433
442
|
if (!res.ok) {
|
|
434
443
|
const errorBody = await res.json().catch(() => ({}));
|
|
@@ -442,7 +451,7 @@ var login = async (email, password) => {
|
|
|
442
451
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
443
452
|
});
|
|
444
453
|
} catch (error) {
|
|
445
|
-
throw
|
|
454
|
+
throw AuthError.from(error);
|
|
446
455
|
}
|
|
447
456
|
if (!userRes.ok) {
|
|
448
457
|
const errorBody = await userRes.json().catch(() => ({}));
|
|
@@ -462,7 +471,7 @@ var login = async (email, password) => {
|
|
|
462
471
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
463
472
|
return user;
|
|
464
473
|
} catch (error) {
|
|
465
|
-
throw
|
|
474
|
+
throw AuthError.from(error);
|
|
466
475
|
}
|
|
467
476
|
};
|
|
468
477
|
var signup = async (email, password, data) => {
|
|
@@ -477,7 +486,7 @@ var signup = async (email, password, data) => {
|
|
|
477
486
|
body: JSON.stringify({ email, password, data })
|
|
478
487
|
});
|
|
479
488
|
} catch (error) {
|
|
480
|
-
throw
|
|
489
|
+
throw AuthError.from(error);
|
|
481
490
|
}
|
|
482
491
|
if (!res.ok) {
|
|
483
492
|
const errorBody = await res.json().catch(() => ({}));
|
|
@@ -506,7 +515,7 @@ var signup = async (email, password, data) => {
|
|
|
506
515
|
}
|
|
507
516
|
return user;
|
|
508
517
|
} catch (error) {
|
|
509
|
-
throw
|
|
518
|
+
throw AuthError.from(error);
|
|
510
519
|
}
|
|
511
520
|
};
|
|
512
521
|
var logout = async () => {
|
|
@@ -535,7 +544,7 @@ var logout = async () => {
|
|
|
535
544
|
deleteBrowserAuthCookies();
|
|
536
545
|
emitAuthEvent(AUTH_EVENTS.LOGOUT, null);
|
|
537
546
|
} catch (error) {
|
|
538
|
-
throw
|
|
547
|
+
throw AuthError.from(error);
|
|
539
548
|
}
|
|
540
549
|
};
|
|
541
550
|
var oauthLogin = (provider) => {
|
|
@@ -566,7 +575,7 @@ var handleAuthCallback = async () => {
|
|
|
566
575
|
return null;
|
|
567
576
|
} catch (error) {
|
|
568
577
|
if (error instanceof AuthError) throw error;
|
|
569
|
-
throw
|
|
578
|
+
throw AuthError.from(error);
|
|
570
579
|
}
|
|
571
580
|
};
|
|
572
581
|
var handleOAuthCallback = async (client, params, accessToken) => {
|
|
@@ -651,16 +660,22 @@ var hydrateSession = async () => {
|
|
|
651
660
|
const decoded = decodeJwtPayload(accessToken);
|
|
652
661
|
const expiresAt = decoded?.exp ?? Math.floor(Date.now() / 1e3) + 3600;
|
|
653
662
|
const expiresIn = Math.max(0, expiresAt - Math.floor(Date.now() / 1e3));
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
663
|
+
let gotrueUser;
|
|
664
|
+
try {
|
|
665
|
+
gotrueUser = await client.createUser(
|
|
666
|
+
{
|
|
667
|
+
access_token: accessToken,
|
|
668
|
+
token_type: "bearer",
|
|
669
|
+
expires_in: expiresIn,
|
|
670
|
+
expires_at: expiresAt,
|
|
671
|
+
refresh_token: refreshToken
|
|
672
|
+
},
|
|
673
|
+
persistSession
|
|
674
|
+
);
|
|
675
|
+
} catch {
|
|
676
|
+
deleteBrowserAuthCookies();
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
664
679
|
const user = toUser(gotrueUser);
|
|
665
680
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
666
681
|
return user;
|
|
@@ -685,7 +700,7 @@ var requestPasswordRecovery = async (email) => {
|
|
|
685
700
|
try {
|
|
686
701
|
await client.requestPasswordRecovery(email);
|
|
687
702
|
} catch (error) {
|
|
688
|
-
throw
|
|
703
|
+
throw AuthError.from(error);
|
|
689
704
|
}
|
|
690
705
|
};
|
|
691
706
|
var recoverPassword = async (token, newPassword) => {
|
|
@@ -697,7 +712,7 @@ var recoverPassword = async (token, newPassword) => {
|
|
|
697
712
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
698
713
|
return user;
|
|
699
714
|
} catch (error) {
|
|
700
|
-
throw
|
|
715
|
+
throw AuthError.from(error);
|
|
701
716
|
}
|
|
702
717
|
};
|
|
703
718
|
var confirmEmail = async (token) => {
|
|
@@ -708,7 +723,7 @@ var confirmEmail = async (token) => {
|
|
|
708
723
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
709
724
|
return user;
|
|
710
725
|
} catch (error) {
|
|
711
|
-
throw
|
|
726
|
+
throw AuthError.from(error);
|
|
712
727
|
}
|
|
713
728
|
};
|
|
714
729
|
var acceptInvite = async (token, password) => {
|
|
@@ -719,15 +734,15 @@ var acceptInvite = async (token, password) => {
|
|
|
719
734
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
720
735
|
return user;
|
|
721
736
|
} catch (error) {
|
|
722
|
-
throw
|
|
737
|
+
throw AuthError.from(error);
|
|
723
738
|
}
|
|
724
739
|
};
|
|
725
740
|
var verifyEmailChange = async (token) => {
|
|
726
741
|
if (!isBrowser()) throw new AuthError("verifyEmailChange() is only available in the browser");
|
|
727
742
|
const currentUser = await resolveCurrentUser();
|
|
728
|
-
const jwt = await currentUser.jwt();
|
|
729
|
-
const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
730
743
|
try {
|
|
744
|
+
const jwt = await currentUser.jwt();
|
|
745
|
+
const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
731
746
|
const res = await fetch(`${identityUrl}/user`, {
|
|
732
747
|
method: "PUT",
|
|
733
748
|
headers: {
|
|
@@ -746,7 +761,7 @@ var verifyEmailChange = async (token) => {
|
|
|
746
761
|
return user;
|
|
747
762
|
} catch (error) {
|
|
748
763
|
if (error instanceof AuthError) throw error;
|
|
749
|
-
throw
|
|
764
|
+
throw AuthError.from(error);
|
|
750
765
|
}
|
|
751
766
|
};
|
|
752
767
|
var updateUser = async (updates) => {
|
|
@@ -757,7 +772,7 @@ var updateUser = async (updates) => {
|
|
|
757
772
|
emitAuthEvent(AUTH_EVENTS.USER_UPDATED, user);
|
|
758
773
|
return user;
|
|
759
774
|
} catch (error) {
|
|
760
|
-
throw
|
|
775
|
+
throw AuthError.from(error);
|
|
761
776
|
}
|
|
762
777
|
};
|
|
763
778
|
|