@netlify/identity 0.4.1 → 1.0.0
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 +50 -30
- package/dist/index.cjs +77 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -68
- package/dist/index.d.ts +73 -68
- package/dist/index.js +77 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,23 +3,24 @@
|
|
|
3
3
|
A lightweight, no-config headless authentication library for projects using Netlify Identity. Works in both browser and server contexts.
|
|
4
4
|
This is NOT the Netlify Identity Widget. This library exports standalone async functions (e.g., import { login, getUser } from '@netlify/identity'). There is no class to instantiate and no .init() call. Just import the functions you need and call them.
|
|
5
5
|
|
|
6
|
-
> **Status:** Beta. The API may change before 1.0.
|
|
7
|
-
|
|
8
6
|
**Prerequisites:**
|
|
9
7
|
|
|
10
|
-
- [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) must be enabled on your Netlify project
|
|
8
|
+
- [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) must be enabled on your Netlify project. This happens automatically when running within a [Netlify Agent Runner](https://docs.netlify.com/agent-runner/overview/)
|
|
11
9
|
- **Server-side** functions (`getUser`, `login`, `admin.*`, etc.) require [Netlify Functions](https://docs.netlify.com/build/functions/get-started/) (modern/v2, with `export default`) or [Edge Functions](https://docs.netlify.com/edge-functions/overview/). [Lambda-compatible functions](https://docs.netlify.com/build/functions/lambda-compatibility/) (v1, with `export { handler }`) are **not supported**
|
|
12
10
|
- For local development, use [`netlify dev`](https://docs.netlify.com/cli/local-development/) so the Identity endpoint is available
|
|
13
11
|
|
|
14
12
|
## How this library relates to other Netlify auth packages
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
|
14
|
+
`@netlify/identity` is the recommended library for all new projects. It works in both browser and server contexts, handles cookie management, and normalizes the user object.
|
|
15
|
+
|
|
16
|
+
You may encounter two older packages in existing code or documentation:
|
|
17
|
+
|
|
18
|
+
| Package | Status | What it was |
|
|
19
|
+
| ------------------------------------------------------------------------------- | -------------------------------- | --------------------------------------------- |
|
|
20
|
+
| [`netlify-identity-widget`](https://github.com/netlify/netlify-identity-widget) | Not recommended for new projects | Pre-built login/signup modal with built-in UI |
|
|
21
|
+
| [`gotrue-js`](https://github.com/netlify/gotrue-js) | Not recommended for new projects | Low-level GoTrue HTTP client (browser only) |
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
If you need a pre-built login UI, the widget still works. For everything else (custom UI, server-side auth, admin operations, framework integration), use `@netlify/identity`.
|
|
23
24
|
|
|
24
25
|
## Table of contents
|
|
25
26
|
|
|
@@ -38,6 +39,7 @@ This library provides a unified API that works in both browser and server contex
|
|
|
38
39
|
- [Password recovery](#password-recovery)
|
|
39
40
|
- [Invite acceptance](#invite-acceptance)
|
|
40
41
|
- [Session lifetime](#session-lifetime)
|
|
42
|
+
- [Caching and authenticated content](#caching-and-authenticated-content)
|
|
41
43
|
|
|
42
44
|
## Installation
|
|
43
45
|
|
|
@@ -96,7 +98,7 @@ export default async (req: Request, context: Context) => {
|
|
|
96
98
|
getUser(): Promise<User | null>
|
|
97
99
|
```
|
|
98
100
|
|
|
99
|
-
Returns the current authenticated user, or `null` if not logged in. Returns the best available normalized `User` from the current context.
|
|
101
|
+
Returns the current authenticated user, or `null` if not logged in. Returns the best available normalized `User` from the current context. When the Identity API is reachable, most persisted and profile fields are populated, but state-dependent fields (invite, recovery, email-change) may still be `undefined` if the user is not in that state. When falling back to JWT claims (e.g., Identity API unreachable), only `id`, `email`, `provider`, `name`, `pictureUrl`, `roles`, `userMetadata`, and `appMetadata` are available. Never throws.
|
|
100
102
|
|
|
101
103
|
> **Next.js note:** Calling `getUser()` in a Server Component opts the page into [dynamic rendering](https://nextjs.org/docs/app/building-your-application/rendering/server-components#dynamic-rendering) because it reads cookies. This is expected and correct for authenticated pages. Next.js handles the internal dynamic rendering signal automatically.
|
|
102
104
|
|
|
@@ -172,7 +174,7 @@ oauthLogin(provider: string): never
|
|
|
172
174
|
|
|
173
175
|
Redirects to an OAuth provider. The page navigates away, so this function never returns normally. Browser only.
|
|
174
176
|
|
|
175
|
-
The `provider` argument should be one of the `AuthProvider` values: `'google'`, `'github'`, `'gitlab'`, `'bitbucket'`,
|
|
177
|
+
The `provider` argument should be one of the `AuthProvider` values: `'google'`, `'github'`, `'gitlab'`, `'bitbucket'`, or `'facebook'`.
|
|
176
178
|
|
|
177
179
|
**Throws:** `MissingIdentityError` if Identity is not configured. `AuthError` if called on the server.
|
|
178
180
|
|
|
@@ -302,10 +304,9 @@ Updates the current user's metadata or credentials. Requires an active session.
|
|
|
302
304
|
|
|
303
305
|
### Admin Operations
|
|
304
306
|
|
|
305
|
-
The `admin` namespace provides user management functions
|
|
307
|
+
The `admin` namespace provides server-only user management functions. Admin methods use the operator token from the Netlify runtime, which is automatically available in Netlify Functions and Edge Functions.
|
|
306
308
|
|
|
307
|
-
|
|
308
|
-
- **Browser:** Uses the logged-in user's JWT. The user must have an admin role.
|
|
309
|
+
Calling any admin method from a browser environment throws an `AuthError`.
|
|
309
310
|
|
|
310
311
|
```ts
|
|
311
312
|
import { admin } from '@netlify/identity'
|
|
@@ -341,9 +342,9 @@ export default async (req: Request, context: Context) => {
|
|
|
341
342
|
admin.listUsers(options?: ListUsersOptions): Promise<User[]>
|
|
342
343
|
```
|
|
343
344
|
|
|
344
|
-
Lists all users. Pagination options
|
|
345
|
+
Lists all users. Pagination options (`page`, `perPage`) are forwarded as query parameters.
|
|
345
346
|
|
|
346
|
-
**Throws:** `AuthError` if
|
|
347
|
+
**Throws:** `AuthError` if called from a browser, or if the operator token is missing.
|
|
347
348
|
|
|
348
349
|
#### `admin.getUser`
|
|
349
350
|
|
|
@@ -353,7 +354,7 @@ admin.getUser(userId: string): Promise<User>
|
|
|
353
354
|
|
|
354
355
|
Gets a single user by ID.
|
|
355
356
|
|
|
356
|
-
**Throws:** `AuthError` if the user is not found, the operator token is missing
|
|
357
|
+
**Throws:** `AuthError` if called from a browser, the user is not found, or the operator token is missing.
|
|
357
358
|
|
|
358
359
|
#### `admin.createUser`
|
|
359
360
|
|
|
@@ -361,9 +362,9 @@ Gets a single user by ID.
|
|
|
361
362
|
admin.createUser(params: CreateUserParams): Promise<User>
|
|
362
363
|
```
|
|
363
364
|
|
|
364
|
-
Creates a new user. The user is auto-confirmed. Optional `data`
|
|
365
|
+
Creates a new user. The user is auto-confirmed. Optional `data` forwards allowed fields (`role`, `app_metadata`, `user_metadata`) to the request body. Other keys are silently ignored. `data` cannot override `email`, `password`, or `confirm`.
|
|
365
366
|
|
|
366
|
-
**Throws:** `AuthError`
|
|
367
|
+
**Throws:** `AuthError` if called from a browser, the email already exists, or the operator token is missing.
|
|
367
368
|
|
|
368
369
|
#### `admin.updateUser`
|
|
369
370
|
|
|
@@ -371,9 +372,9 @@ Creates a new user. The user is auto-confirmed. Optional `data` is spread into t
|
|
|
371
372
|
admin.updateUser(userId: string, attributes: AdminUserUpdates): Promise<User>
|
|
372
373
|
```
|
|
373
374
|
|
|
374
|
-
Updates an existing user by ID.
|
|
375
|
+
Updates an existing user by ID. Only typed `AdminUserUpdates` fields are forwarded (e.g., `{ email: 'new@example.com' }`, `{ role: 'editor' }`).
|
|
375
376
|
|
|
376
|
-
**Throws:** `AuthError` if the user is not found or the update fails.
|
|
377
|
+
**Throws:** `AuthError` if called from a browser, the user is not found, or the update fails.
|
|
377
378
|
|
|
378
379
|
#### `admin.deleteUser`
|
|
379
380
|
|
|
@@ -383,7 +384,7 @@ admin.deleteUser(userId: string): Promise<void>
|
|
|
383
384
|
|
|
384
385
|
Deletes a user by ID.
|
|
385
386
|
|
|
386
|
-
**Throws:** `AuthError` if the user is not found or the deletion fails.
|
|
387
|
+
**Throws:** `AuthError` if called from a browser, the user is not found, or the deletion fails.
|
|
387
388
|
|
|
388
389
|
### Types
|
|
389
390
|
|
|
@@ -393,16 +394,22 @@ Deletes a user by ID.
|
|
|
393
394
|
interface User {
|
|
394
395
|
id: string
|
|
395
396
|
email?: string
|
|
396
|
-
|
|
397
|
+
confirmedAt?: string
|
|
397
398
|
createdAt?: string
|
|
398
399
|
updatedAt?: string
|
|
400
|
+
role?: string
|
|
399
401
|
provider?: AuthProvider
|
|
400
402
|
name?: string
|
|
401
403
|
pictureUrl?: string
|
|
402
404
|
roles?: string[]
|
|
403
|
-
|
|
405
|
+
invitedAt?: string
|
|
406
|
+
confirmationSentAt?: string
|
|
407
|
+
recoverySentAt?: string
|
|
408
|
+
pendingEmail?: string
|
|
409
|
+
emailChangeSentAt?: string
|
|
410
|
+
lastSignInAt?: string
|
|
411
|
+
userMetadata?: Record<string, unknown>
|
|
404
412
|
appMetadata?: Record<string, unknown>
|
|
405
|
-
rawGoTrueData?: Record<string, unknown>
|
|
406
413
|
}
|
|
407
414
|
```
|
|
408
415
|
|
|
@@ -428,7 +435,7 @@ interface IdentityConfig {
|
|
|
428
435
|
#### `AuthProvider`
|
|
429
436
|
|
|
430
437
|
```ts
|
|
431
|
-
type AuthProvider = 'google' | 'github' | 'gitlab' | 'bitbucket' | 'facebook' | '
|
|
438
|
+
type AuthProvider = 'google' | 'github' | 'gitlab' | 'bitbucket' | 'facebook' | 'email'
|
|
432
439
|
```
|
|
433
440
|
|
|
434
441
|
#### `UserUpdates`
|
|
@@ -454,11 +461,10 @@ interface AdminUserUpdates {
|
|
|
454
461
|
confirm?: boolean
|
|
455
462
|
app_metadata?: Record<string, unknown>
|
|
456
463
|
user_metadata?: Record<string, unknown>
|
|
457
|
-
[key: string]: unknown
|
|
458
464
|
}
|
|
459
465
|
```
|
|
460
466
|
|
|
461
|
-
Fields accepted by `admin.updateUser()`. Unlike `UserUpdates`, admin updates can set `role`, force-confirm a user, and write to `app_metadata`.
|
|
467
|
+
Fields accepted by `admin.updateUser()`. Unlike `UserUpdates`, admin updates can set `role`, force-confirm a user, and write to `app_metadata`. Only these typed fields are forwarded.
|
|
462
468
|
|
|
463
469
|
#### `SignupData`
|
|
464
470
|
|
|
@@ -487,7 +493,7 @@ interface ListUsersOptions {
|
|
|
487
493
|
}
|
|
488
494
|
```
|
|
489
495
|
|
|
490
|
-
Pagination options for `admin.listUsers()`.
|
|
496
|
+
Pagination options for `admin.listUsers()`.
|
|
491
497
|
|
|
492
498
|
#### `CreateUserParams`
|
|
493
499
|
|
|
@@ -499,7 +505,7 @@ interface CreateUserParams {
|
|
|
499
505
|
}
|
|
500
506
|
```
|
|
501
507
|
|
|
502
|
-
Parameters for `admin.createUser()`. Optional `data`
|
|
508
|
+
Parameters for `admin.createUser()`. Optional `data` forwards allowed fields (`role`, `app_metadata`, `user_metadata`) to the request body. Other keys are silently ignored.
|
|
503
509
|
|
|
504
510
|
#### `Admin`
|
|
505
511
|
|
|
@@ -1048,6 +1054,20 @@ Sessions are managed by Netlify Identity on the server side. The library stores
|
|
|
1048
1054
|
|
|
1049
1055
|
Session lifetime is configured in your Netlify Identity settings, not in this library.
|
|
1050
1056
|
|
|
1057
|
+
### Caching and authenticated content
|
|
1058
|
+
|
|
1059
|
+
Pages that display user-specific data (names, emails, roles, account settings) should not be served from a shared cache. If a cache stores an authenticated response and serves it to a different user, that user sees someone else's data. This applies to any authentication system, not just Netlify Identity.
|
|
1060
|
+
|
|
1061
|
+
**Next.js App Router** has multiple caching layers that are active by default:
|
|
1062
|
+
|
|
1063
|
+
- **Static rendering:** Server Components are statically rendered at build time unless they call a [Dynamic API](https://nextjs.org/docs/app/guides/caching#dynamic-rendering) like `cookies()`. This library's `getUser()` already calls `headers()` internally to opt the route into dynamic rendering, but if you check auth state without calling `getUser()` (e.g., reading the `nf_jwt` cookie directly), the page may still be statically cached. Always use `getUser()` rather than reading cookies directly.
|
|
1064
|
+
- **ISR (Incremental Static Regeneration):** Do not use ISR for pages that display user-specific content. ISR regenerates the page for the first visitor after the revalidation window and caches the result for all subsequent visitors.
|
|
1065
|
+
- **`use cache` / `unstable_cache`:** These directives cannot access `cookies()` or `headers()` directly. If you need to cache part of an authenticated page, read cookies outside the cache scope and pass relevant values as arguments.
|
|
1066
|
+
|
|
1067
|
+
> **Note:** Next.js caching defaults have changed across versions. For example, [Next.js 15 changed `fetch` requests, `GET` Route Handlers, and the client Router Cache to be uncached by default](https://nextjs.org/blog/next-15#caching-semantics), reversing the previous opt-out model. Check the [caching guide](https://nextjs.org/docs/app/guides/caching) for your specific Next.js version.
|
|
1068
|
+
|
|
1069
|
+
**Other SSR frameworks (Remix, Astro, SvelteKit, TanStack Start):** These frameworks do not cache SSR responses by default. If you add caching headers to improve performance, exclude routes that call `getUser()` or read auth cookies.
|
|
1070
|
+
|
|
1051
1071
|
## License
|
|
1052
1072
|
|
|
1053
1073
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -56,7 +56,7 @@ __export(index_exports, {
|
|
|
56
56
|
module.exports = __toCommonJS(index_exports);
|
|
57
57
|
|
|
58
58
|
// src/types.ts
|
|
59
|
-
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "
|
|
59
|
+
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "email"];
|
|
60
60
|
|
|
61
61
|
// src/environment.ts
|
|
62
62
|
var import_gotrue_js = __toESM(require("gotrue-js"), 1);
|
|
@@ -681,6 +681,7 @@ var hydrateSession = async () => {
|
|
|
681
681
|
|
|
682
682
|
// src/user.ts
|
|
683
683
|
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
684
|
+
var toOptionalString = (value) => typeof value === "string" && value !== "" ? value : void 0;
|
|
684
685
|
var toRoles = (appMeta) => {
|
|
685
686
|
const roles = appMeta.roles;
|
|
686
687
|
if (Array.isArray(roles) && roles.every((r) => typeof r === "string")) {
|
|
@@ -693,20 +694,25 @@ var toUser = (userData) => {
|
|
|
693
694
|
const appMeta = userData.app_metadata ?? {};
|
|
694
695
|
const name = userMeta.full_name || userMeta.name;
|
|
695
696
|
const pictureUrl = userMeta.avatar_url;
|
|
696
|
-
const { token: _token, ...safeUserData } = userData;
|
|
697
697
|
return {
|
|
698
698
|
id: userData.id,
|
|
699
699
|
email: userData.email,
|
|
700
|
-
|
|
700
|
+
confirmedAt: toOptionalString(userData.confirmed_at),
|
|
701
701
|
createdAt: userData.created_at,
|
|
702
702
|
updatedAt: userData.updated_at,
|
|
703
|
+
role: toOptionalString(userData.role),
|
|
703
704
|
provider: toAuthProvider(appMeta.provider),
|
|
704
705
|
name: typeof name === "string" ? name : void 0,
|
|
705
706
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
706
707
|
roles: toRoles(appMeta),
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
708
|
+
invitedAt: toOptionalString(userData.invited_at),
|
|
709
|
+
confirmationSentAt: toOptionalString(userData.confirmation_sent_at),
|
|
710
|
+
recoverySentAt: toOptionalString(userData.recovery_sent_at),
|
|
711
|
+
pendingEmail: toOptionalString(userData.new_email),
|
|
712
|
+
emailChangeSentAt: toOptionalString(userData.email_change_sent_at),
|
|
713
|
+
lastSignInAt: toOptionalString(userData.last_sign_in_at),
|
|
714
|
+
userMetadata: userMeta,
|
|
715
|
+
appMetadata: appMeta
|
|
710
716
|
};
|
|
711
717
|
};
|
|
712
718
|
var claimsToUser = (claims) => {
|
|
@@ -721,7 +727,7 @@ var claimsToUser = (claims) => {
|
|
|
721
727
|
name: typeof name === "string" ? name : void 0,
|
|
722
728
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
723
729
|
roles: toRoles(appMeta),
|
|
724
|
-
|
|
730
|
+
userMetadata: userMeta,
|
|
725
731
|
appMetadata: appMeta
|
|
726
732
|
};
|
|
727
733
|
};
|
|
@@ -818,8 +824,7 @@ var getSettings = async () => {
|
|
|
818
824
|
gitlab: external.gitlab ?? false,
|
|
819
825
|
bitbucket: external.bitbucket ?? false,
|
|
820
826
|
facebook: external.facebook ?? false,
|
|
821
|
-
email: external.email ?? false
|
|
822
|
-
saml: external.saml ?? false
|
|
827
|
+
email: external.email ?? false
|
|
823
828
|
}
|
|
824
829
|
};
|
|
825
830
|
} catch (err) {
|
|
@@ -926,6 +931,19 @@ var updateUser = async (updates) => {
|
|
|
926
931
|
};
|
|
927
932
|
|
|
928
933
|
// src/admin.ts
|
|
934
|
+
var SERVER_ONLY_MESSAGE = "Admin operations are server-only. Call admin methods from a Netlify Function or Edge Function, not from browser code.";
|
|
935
|
+
var sanitizeUserId = (userId) => {
|
|
936
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
937
|
+
if (!uuidRegex.test(userId)) {
|
|
938
|
+
throw new AuthError("User ID is not a valid UUID");
|
|
939
|
+
}
|
|
940
|
+
return encodeURIComponent(userId);
|
|
941
|
+
};
|
|
942
|
+
var assertServer = () => {
|
|
943
|
+
if (isBrowser()) {
|
|
944
|
+
throw new AuthError(SERVER_ONLY_MESSAGE);
|
|
945
|
+
}
|
|
946
|
+
};
|
|
929
947
|
var getAdminAuth = () => {
|
|
930
948
|
const ctx = getIdentityContext();
|
|
931
949
|
if (!ctx?.url) {
|
|
@@ -957,105 +975,67 @@ var adminFetch = async (path, options = {}) => {
|
|
|
957
975
|
}
|
|
958
976
|
return res;
|
|
959
977
|
};
|
|
960
|
-
var getAdminUser = () => {
|
|
961
|
-
const client = getClient();
|
|
962
|
-
const user = client.currentUser();
|
|
963
|
-
if (!user) {
|
|
964
|
-
throw new AuthError("Admin operations require a logged-in user with admin role");
|
|
965
|
-
}
|
|
966
|
-
return user;
|
|
967
|
-
};
|
|
968
978
|
var listUsers = async (options) => {
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
}
|
|
979
|
-
try {
|
|
980
|
-
const user = getAdminUser();
|
|
981
|
-
const users = await user.admin.listUsers("");
|
|
982
|
-
return users.map(toUser);
|
|
983
|
-
} catch (error) {
|
|
984
|
-
if (error instanceof AuthError) throw error;
|
|
985
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
986
|
-
}
|
|
979
|
+
assertServer();
|
|
980
|
+
const params = new URLSearchParams();
|
|
981
|
+
if (options?.page != null) params.set("page", String(options.page));
|
|
982
|
+
if (options?.perPage != null) params.set("per_page", String(options.perPage));
|
|
983
|
+
const query = params.toString();
|
|
984
|
+
const path = `/admin/users${query ? `?${query}` : ""}`;
|
|
985
|
+
const res = await adminFetch(path);
|
|
986
|
+
const body = await res.json();
|
|
987
|
+
return body.users.map(toUser);
|
|
987
988
|
};
|
|
988
989
|
var getUser2 = async (userId) => {
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
try {
|
|
995
|
-
const user = getAdminUser();
|
|
996
|
-
const userData = await user.admin.getUser({ id: userId });
|
|
997
|
-
return toUser(userData);
|
|
998
|
-
} catch (error) {
|
|
999
|
-
if (error instanceof AuthError) throw error;
|
|
1000
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
1001
|
-
}
|
|
990
|
+
assertServer();
|
|
991
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
992
|
+
const res = await adminFetch(`/admin/users/${sanitizedUserId}`);
|
|
993
|
+
const userData = await res.json();
|
|
994
|
+
return toUser(userData);
|
|
1002
995
|
};
|
|
1003
996
|
var createUser = async (params) => {
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
try {
|
|
1018
|
-
const user = getAdminUser();
|
|
1019
|
-
const userData = await user.admin.createUser(params.email, params.password, {
|
|
1020
|
-
...params.data,
|
|
1021
|
-
confirm: true
|
|
1022
|
-
});
|
|
1023
|
-
return toUser(userData);
|
|
1024
|
-
} catch (error) {
|
|
1025
|
-
if (error instanceof AuthError) throw error;
|
|
1026
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
997
|
+
assertServer();
|
|
998
|
+
const body = {
|
|
999
|
+
email: params.email,
|
|
1000
|
+
password: params.password,
|
|
1001
|
+
confirm: true
|
|
1002
|
+
};
|
|
1003
|
+
if (params.data) {
|
|
1004
|
+
const allowedKeys = ["role", "app_metadata", "user_metadata"];
|
|
1005
|
+
for (const key of allowedKeys) {
|
|
1006
|
+
if (key in params.data) {
|
|
1007
|
+
body[key] = params.data[key];
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1027
1010
|
}
|
|
1011
|
+
const res = await adminFetch("/admin/users", {
|
|
1012
|
+
method: "POST",
|
|
1013
|
+
body: JSON.stringify(body)
|
|
1014
|
+
});
|
|
1015
|
+
const userData = await res.json();
|
|
1016
|
+
return toUser(userData);
|
|
1028
1017
|
};
|
|
1029
1018
|
var updateUser2 = async (userId, attributes) => {
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
try {
|
|
1039
|
-
const user = getAdminUser();
|
|
1040
|
-
const userData = await user.admin.updateUser({ id: userId }, attributes);
|
|
1041
|
-
return toUser(userData);
|
|
1042
|
-
} catch (error) {
|
|
1043
|
-
if (error instanceof AuthError) throw error;
|
|
1044
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
1019
|
+
assertServer();
|
|
1020
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
1021
|
+
const body = {};
|
|
1022
|
+
const allowedKeys = ["email", "password", "role", "confirm", "app_metadata", "user_metadata"];
|
|
1023
|
+
for (const key of allowedKeys) {
|
|
1024
|
+
if (key in attributes) {
|
|
1025
|
+
body[key] = attributes[key];
|
|
1026
|
+
}
|
|
1045
1027
|
}
|
|
1028
|
+
const res = await adminFetch(`/admin/users/${sanitizedUserId}`, {
|
|
1029
|
+
method: "PUT",
|
|
1030
|
+
body: JSON.stringify(body)
|
|
1031
|
+
});
|
|
1032
|
+
const userData = await res.json();
|
|
1033
|
+
return toUser(userData);
|
|
1046
1034
|
};
|
|
1047
1035
|
var deleteUser = async (userId) => {
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
try {
|
|
1053
|
-
const user = getAdminUser();
|
|
1054
|
-
await user.admin.deleteUser({ id: userId });
|
|
1055
|
-
} catch (error) {
|
|
1056
|
-
if (error instanceof AuthError) throw error;
|
|
1057
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
1058
|
-
}
|
|
1036
|
+
assertServer();
|
|
1037
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
1038
|
+
await adminFetch(`/admin/users/${sanitizedUserId}`, { method: "DELETE" });
|
|
1059
1039
|
};
|
|
1060
1040
|
var admin = { listUsers, getUser: getUser2, createUser, updateUser: updateUser2, deleteUser };
|
|
1061
1041
|
// Annotate the CommonJS export names for ESM import in node:
|