@netlify/identity 0.3.1-alpha.6 → 0.4.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.
- package/README.md +31 -15
- package/dist/index.cjs +93 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -47
- package/dist/index.d.ts +36 -47
- package/dist/index.js +93 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ This is NOT the Netlify Identity Widget. This library exports standalone async f
|
|
|
8
8
|
**Prerequisites:**
|
|
9
9
|
|
|
10
10
|
- [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) must be enabled on your Netlify project
|
|
11
|
+
- **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**
|
|
11
12
|
- For local development, use [`netlify dev`](https://docs.netlify.com/cli/local-development/) so the Identity endpoint is available
|
|
12
13
|
|
|
13
14
|
## How this library relates to other Netlify auth packages
|
|
@@ -37,6 +38,7 @@ This library provides a unified API that works in both browser and server contex
|
|
|
37
38
|
- [Password recovery](#password-recovery)
|
|
38
39
|
- [Invite acceptance](#invite-acceptance)
|
|
39
40
|
- [Session lifetime](#session-lifetime)
|
|
41
|
+
- [Caching and authenticated content](#caching-and-authenticated-content)
|
|
40
42
|
|
|
41
43
|
## Installation
|
|
42
44
|
|
|
@@ -301,10 +303,9 @@ Updates the current user's metadata or credentials. Requires an active session.
|
|
|
301
303
|
|
|
302
304
|
### Admin Operations
|
|
303
305
|
|
|
304
|
-
The `admin` namespace provides user management functions
|
|
306
|
+
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.
|
|
305
307
|
|
|
306
|
-
|
|
307
|
-
- **Browser:** Uses the logged-in user's JWT. The user must have an admin role.
|
|
308
|
+
Calling any admin method from a browser environment throws an `AuthError`.
|
|
308
309
|
|
|
309
310
|
```ts
|
|
310
311
|
import { admin } from '@netlify/identity'
|
|
@@ -340,9 +341,9 @@ export default async (req: Request, context: Context) => {
|
|
|
340
341
|
admin.listUsers(options?: ListUsersOptions): Promise<User[]>
|
|
341
342
|
```
|
|
342
343
|
|
|
343
|
-
Lists all users. Pagination options
|
|
344
|
+
Lists all users. Pagination options (`page`, `perPage`) are forwarded as query parameters.
|
|
344
345
|
|
|
345
|
-
**Throws:** `AuthError` if
|
|
346
|
+
**Throws:** `AuthError` if called from a browser, or if the operator token is missing.
|
|
346
347
|
|
|
347
348
|
#### `admin.getUser`
|
|
348
349
|
|
|
@@ -352,7 +353,7 @@ admin.getUser(userId: string): Promise<User>
|
|
|
352
353
|
|
|
353
354
|
Gets a single user by ID.
|
|
354
355
|
|
|
355
|
-
**Throws:** `AuthError` if the user is not found, the operator token is missing
|
|
356
|
+
**Throws:** `AuthError` if called from a browser, the user is not found, or the operator token is missing.
|
|
356
357
|
|
|
357
358
|
#### `admin.createUser`
|
|
358
359
|
|
|
@@ -360,9 +361,9 @@ Gets a single user by ID.
|
|
|
360
361
|
admin.createUser(params: CreateUserParams): Promise<User>
|
|
361
362
|
```
|
|
362
363
|
|
|
363
|
-
Creates a new user. The user is auto-confirmed. Optional `data`
|
|
364
|
+
Creates a new user. The user is auto-confirmed. Optional `data` forwards allowed fields (`role`, `aud`, `app_metadata`, `user_metadata`) to the request body. Other keys are silently ignored. `data` cannot override `email`, `password`, or `confirm`.
|
|
364
365
|
|
|
365
|
-
**Throws:** `AuthError`
|
|
366
|
+
**Throws:** `AuthError` if called from a browser, the email already exists, or the operator token is missing.
|
|
366
367
|
|
|
367
368
|
#### `admin.updateUser`
|
|
368
369
|
|
|
@@ -370,9 +371,9 @@ Creates a new user. The user is auto-confirmed. Optional `data` is spread into t
|
|
|
370
371
|
admin.updateUser(userId: string, attributes: AdminUserUpdates): Promise<User>
|
|
371
372
|
```
|
|
372
373
|
|
|
373
|
-
Updates an existing user by ID.
|
|
374
|
+
Updates an existing user by ID. Only typed `AdminUserUpdates` fields are forwarded (e.g., `{ email: 'new@example.com' }`, `{ role: 'editor' }`).
|
|
374
375
|
|
|
375
|
-
**Throws:** `AuthError` if the user is not found or the update fails.
|
|
376
|
+
**Throws:** `AuthError` if called from a browser, the user is not found, or the update fails.
|
|
376
377
|
|
|
377
378
|
#### `admin.deleteUser`
|
|
378
379
|
|
|
@@ -382,7 +383,7 @@ admin.deleteUser(userId: string): Promise<void>
|
|
|
382
383
|
|
|
383
384
|
Deletes a user by ID.
|
|
384
385
|
|
|
385
|
-
**Throws:** `AuthError` if the user is not found or the deletion fails.
|
|
386
|
+
**Throws:** `AuthError` if called from a browser, the user is not found, or the deletion fails.
|
|
386
387
|
|
|
387
388
|
### Types
|
|
388
389
|
|
|
@@ -400,6 +401,7 @@ interface User {
|
|
|
400
401
|
pictureUrl?: string
|
|
401
402
|
roles?: string[]
|
|
402
403
|
metadata?: Record<string, unknown>
|
|
404
|
+
appMetadata?: Record<string, unknown>
|
|
403
405
|
rawGoTrueData?: Record<string, unknown>
|
|
404
406
|
}
|
|
405
407
|
```
|
|
@@ -449,14 +451,14 @@ interface AdminUserUpdates {
|
|
|
449
451
|
email?: string
|
|
450
452
|
password?: string
|
|
451
453
|
role?: string
|
|
454
|
+
aud?: string
|
|
452
455
|
confirm?: boolean
|
|
453
456
|
app_metadata?: Record<string, unknown>
|
|
454
457
|
user_metadata?: Record<string, unknown>
|
|
455
|
-
[key: string]: unknown
|
|
456
458
|
}
|
|
457
459
|
```
|
|
458
460
|
|
|
459
|
-
Fields accepted by `admin.updateUser()`. Unlike `UserUpdates`, admin updates can set `role`, force-confirm a user, and write to `app_metadata`.
|
|
461
|
+
Fields accepted by `admin.updateUser()`. Unlike `UserUpdates`, admin updates can set `role`, `aud`, force-confirm a user, and write to `app_metadata`. Only these typed fields are forwarded.
|
|
460
462
|
|
|
461
463
|
#### `SignupData`
|
|
462
464
|
|
|
@@ -485,7 +487,7 @@ interface ListUsersOptions {
|
|
|
485
487
|
}
|
|
486
488
|
```
|
|
487
489
|
|
|
488
|
-
Pagination options for `admin.listUsers()`.
|
|
490
|
+
Pagination options for `admin.listUsers()`.
|
|
489
491
|
|
|
490
492
|
#### `CreateUserParams`
|
|
491
493
|
|
|
@@ -497,7 +499,7 @@ interface CreateUserParams {
|
|
|
497
499
|
}
|
|
498
500
|
```
|
|
499
501
|
|
|
500
|
-
Parameters for `admin.createUser()`. Optional `data`
|
|
502
|
+
Parameters for `admin.createUser()`. Optional `data` forwards allowed fields (`role`, `aud`, `app_metadata`, `user_metadata`) to the request body. Other keys are silently ignored.
|
|
501
503
|
|
|
502
504
|
#### `Admin`
|
|
503
505
|
|
|
@@ -1046,6 +1048,20 @@ Sessions are managed by Netlify Identity on the server side. The library stores
|
|
|
1046
1048
|
|
|
1047
1049
|
Session lifetime is configured in your Netlify Identity settings, not in this library.
|
|
1048
1050
|
|
|
1051
|
+
### Caching and authenticated content
|
|
1052
|
+
|
|
1053
|
+
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.
|
|
1054
|
+
|
|
1055
|
+
**Next.js App Router** has multiple caching layers that are active by default:
|
|
1056
|
+
|
|
1057
|
+
- **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.
|
|
1058
|
+
- **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.
|
|
1059
|
+
- **`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.
|
|
1060
|
+
|
|
1061
|
+
> **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.
|
|
1062
|
+
|
|
1063
|
+
**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.
|
|
1064
|
+
|
|
1049
1065
|
## License
|
|
1050
1066
|
|
|
1051
1067
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -227,6 +227,24 @@ var triggerNextjsDynamic = () => {
|
|
|
227
227
|
}
|
|
228
228
|
};
|
|
229
229
|
|
|
230
|
+
// src/fetch.ts
|
|
231
|
+
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
232
|
+
var fetchWithTimeout = async (url, options = {}, timeoutMs = DEFAULT_TIMEOUT_MS) => {
|
|
233
|
+
const controller = new AbortController();
|
|
234
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
235
|
+
try {
|
|
236
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
239
|
+
const pathname = new URL(url).pathname;
|
|
240
|
+
throw new AuthError(`Identity request to ${pathname} timed out after ${timeoutMs}ms`);
|
|
241
|
+
}
|
|
242
|
+
throw error;
|
|
243
|
+
} finally {
|
|
244
|
+
clearTimeout(timer);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
|
|
230
248
|
// src/events.ts
|
|
231
249
|
var AUTH_EVENTS = {
|
|
232
250
|
LOGIN: "login",
|
|
@@ -344,7 +362,7 @@ var refreshSession = async () => {
|
|
|
344
362
|
}
|
|
345
363
|
let res;
|
|
346
364
|
try {
|
|
347
|
-
res = await
|
|
365
|
+
res = await fetchWithTimeout(`${identityUrl}/token`, {
|
|
348
366
|
method: "POST",
|
|
349
367
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
350
368
|
body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: refreshToken }).toString()
|
|
@@ -398,7 +416,7 @@ var login = async (email, password) => {
|
|
|
398
416
|
});
|
|
399
417
|
let res;
|
|
400
418
|
try {
|
|
401
|
-
res = await
|
|
419
|
+
res = await fetchWithTimeout(`${identityUrl}/token`, {
|
|
402
420
|
method: "POST",
|
|
403
421
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
404
422
|
body: body.toString()
|
|
@@ -414,7 +432,7 @@ var login = async (email, password) => {
|
|
|
414
432
|
const accessToken = data.access_token;
|
|
415
433
|
let userRes;
|
|
416
434
|
try {
|
|
417
|
-
userRes = await
|
|
435
|
+
userRes = await fetchWithTimeout(`${identityUrl}/user`, {
|
|
418
436
|
headers: { Authorization: `Bearer ${accessToken}` }
|
|
419
437
|
});
|
|
420
438
|
} catch (error) {
|
|
@@ -448,7 +466,7 @@ var signup = async (email, password, data) => {
|
|
|
448
466
|
const cookies = getCookies();
|
|
449
467
|
let res;
|
|
450
468
|
try {
|
|
451
|
-
res = await
|
|
469
|
+
res = await fetchWithTimeout(`${identityUrl}/signup`, {
|
|
452
470
|
method: "POST",
|
|
453
471
|
headers: { "Content-Type": "application/json" },
|
|
454
472
|
body: JSON.stringify({ email, password, data })
|
|
@@ -495,7 +513,7 @@ var logout = async () => {
|
|
|
495
513
|
const jwt = cookies.get(NF_JWT_COOKIE);
|
|
496
514
|
if (jwt) {
|
|
497
515
|
try {
|
|
498
|
-
await
|
|
516
|
+
await fetchWithTimeout(`${identityUrl}/logout`, {
|
|
499
517
|
method: "POST",
|
|
500
518
|
headers: { Authorization: `Bearer ${jwt}` }
|
|
501
519
|
});
|
|
@@ -675,6 +693,7 @@ var toUser = (userData) => {
|
|
|
675
693
|
const appMeta = userData.app_metadata ?? {};
|
|
676
694
|
const name = userMeta.full_name || userMeta.name;
|
|
677
695
|
const pictureUrl = userMeta.avatar_url;
|
|
696
|
+
const { token: _token, ...safeUserData } = userData;
|
|
678
697
|
return {
|
|
679
698
|
id: userData.id,
|
|
680
699
|
email: userData.email,
|
|
@@ -686,7 +705,8 @@ var toUser = (userData) => {
|
|
|
686
705
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
687
706
|
roles: toRoles(appMeta),
|
|
688
707
|
metadata: userMeta,
|
|
689
|
-
|
|
708
|
+
appMetadata: appMeta,
|
|
709
|
+
rawGoTrueData: { ...safeUserData }
|
|
690
710
|
};
|
|
691
711
|
};
|
|
692
712
|
var claimsToUser = (claims) => {
|
|
@@ -701,7 +721,8 @@ var claimsToUser = (claims) => {
|
|
|
701
721
|
name: typeof name === "string" ? name : void 0,
|
|
702
722
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
703
723
|
roles: toRoles(appMeta),
|
|
704
|
-
metadata: userMeta
|
|
724
|
+
metadata: userMeta,
|
|
725
|
+
appMetadata: appMeta
|
|
705
726
|
};
|
|
706
727
|
};
|
|
707
728
|
var decodeJwtPayload = (token) => {
|
|
@@ -716,7 +737,7 @@ var decodeJwtPayload = (token) => {
|
|
|
716
737
|
};
|
|
717
738
|
var fetchFullUser = async (identityUrl, jwt) => {
|
|
718
739
|
try {
|
|
719
|
-
const res = await
|
|
740
|
+
const res = await fetchWithTimeout(`${identityUrl}/user`, {
|
|
720
741
|
headers: { Authorization: `Bearer ${jwt}` }
|
|
721
742
|
});
|
|
722
743
|
if (!res.ok) return null;
|
|
@@ -905,6 +926,19 @@ var updateUser = async (updates) => {
|
|
|
905
926
|
};
|
|
906
927
|
|
|
907
928
|
// src/admin.ts
|
|
929
|
+
var SERVER_ONLY_MESSAGE = "Admin operations are server-only. Call admin methods from a Netlify Function or Edge Function, not from browser code.";
|
|
930
|
+
var sanitizeUserId = (userId) => {
|
|
931
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
932
|
+
if (!uuidRegex.test(userId)) {
|
|
933
|
+
throw new AuthError("User ID is not a valid UUID");
|
|
934
|
+
}
|
|
935
|
+
return encodeURIComponent(userId);
|
|
936
|
+
};
|
|
937
|
+
var assertServer = () => {
|
|
938
|
+
if (isBrowser()) {
|
|
939
|
+
throw new AuthError(SERVER_ONLY_MESSAGE);
|
|
940
|
+
}
|
|
941
|
+
};
|
|
908
942
|
var getAdminAuth = () => {
|
|
909
943
|
const ctx = getIdentityContext();
|
|
910
944
|
if (!ctx?.url) {
|
|
@@ -919,7 +953,7 @@ var adminFetch = async (path, options = {}) => {
|
|
|
919
953
|
const { url, token } = getAdminAuth();
|
|
920
954
|
let res;
|
|
921
955
|
try {
|
|
922
|
-
res = await
|
|
956
|
+
res = await fetchWithTimeout(`${url}${path}`, {
|
|
923
957
|
...options,
|
|
924
958
|
headers: {
|
|
925
959
|
...options.headers,
|
|
@@ -936,105 +970,67 @@ var adminFetch = async (path, options = {}) => {
|
|
|
936
970
|
}
|
|
937
971
|
return res;
|
|
938
972
|
};
|
|
939
|
-
var getAdminUser = () => {
|
|
940
|
-
const client = getClient();
|
|
941
|
-
const user = client.currentUser();
|
|
942
|
-
if (!user) {
|
|
943
|
-
throw new AuthError("Admin operations require a logged-in user with admin role");
|
|
944
|
-
}
|
|
945
|
-
return user;
|
|
946
|
-
};
|
|
947
973
|
var listUsers = async (options) => {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
}
|
|
958
|
-
try {
|
|
959
|
-
const user = getAdminUser();
|
|
960
|
-
const users = await user.admin.listUsers("");
|
|
961
|
-
return users.map(toUser);
|
|
962
|
-
} catch (error) {
|
|
963
|
-
if (error instanceof AuthError) throw error;
|
|
964
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
965
|
-
}
|
|
974
|
+
assertServer();
|
|
975
|
+
const params = new URLSearchParams();
|
|
976
|
+
if (options?.page != null) params.set("page", String(options.page));
|
|
977
|
+
if (options?.perPage != null) params.set("per_page", String(options.perPage));
|
|
978
|
+
const query = params.toString();
|
|
979
|
+
const path = `/admin/users${query ? `?${query}` : ""}`;
|
|
980
|
+
const res = await adminFetch(path);
|
|
981
|
+
const body = await res.json();
|
|
982
|
+
return body.users.map(toUser);
|
|
966
983
|
};
|
|
967
984
|
var getUser2 = async (userId) => {
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
try {
|
|
974
|
-
const user = getAdminUser();
|
|
975
|
-
const userData = await user.admin.getUser({ id: userId });
|
|
976
|
-
return toUser(userData);
|
|
977
|
-
} catch (error) {
|
|
978
|
-
if (error instanceof AuthError) throw error;
|
|
979
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
980
|
-
}
|
|
985
|
+
assertServer();
|
|
986
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
987
|
+
const res = await adminFetch(`/admin/users/${sanitizedUserId}`);
|
|
988
|
+
const userData = await res.json();
|
|
989
|
+
return toUser(userData);
|
|
981
990
|
};
|
|
982
991
|
var createUser = async (params) => {
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
try {
|
|
997
|
-
const user = getAdminUser();
|
|
998
|
-
const userData = await user.admin.createUser(params.email, params.password, {
|
|
999
|
-
...params.data,
|
|
1000
|
-
confirm: true
|
|
1001
|
-
});
|
|
1002
|
-
return toUser(userData);
|
|
1003
|
-
} catch (error) {
|
|
1004
|
-
if (error instanceof AuthError) throw error;
|
|
1005
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
992
|
+
assertServer();
|
|
993
|
+
const body = {
|
|
994
|
+
email: params.email,
|
|
995
|
+
password: params.password,
|
|
996
|
+
confirm: true
|
|
997
|
+
};
|
|
998
|
+
if (params.data) {
|
|
999
|
+
const allowedKeys = ["role", "aud", "app_metadata", "user_metadata"];
|
|
1000
|
+
for (const key of allowedKeys) {
|
|
1001
|
+
if (key in params.data) {
|
|
1002
|
+
body[key] = params.data[key];
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1006
1005
|
}
|
|
1006
|
+
const res = await adminFetch("/admin/users", {
|
|
1007
|
+
method: "POST",
|
|
1008
|
+
body: JSON.stringify(body)
|
|
1009
|
+
});
|
|
1010
|
+
const userData = await res.json();
|
|
1011
|
+
return toUser(userData);
|
|
1007
1012
|
};
|
|
1008
1013
|
var updateUser2 = async (userId, attributes) => {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
try {
|
|
1018
|
-
const user = getAdminUser();
|
|
1019
|
-
const userData = await user.admin.updateUser({ id: userId }, attributes);
|
|
1020
|
-
return toUser(userData);
|
|
1021
|
-
} catch (error) {
|
|
1022
|
-
if (error instanceof AuthError) throw error;
|
|
1023
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
1014
|
+
assertServer();
|
|
1015
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
1016
|
+
const body = {};
|
|
1017
|
+
const allowedKeys = ["email", "password", "role", "aud", "confirm", "app_metadata", "user_metadata"];
|
|
1018
|
+
for (const key of allowedKeys) {
|
|
1019
|
+
if (key in attributes) {
|
|
1020
|
+
body[key] = attributes[key];
|
|
1021
|
+
}
|
|
1024
1022
|
}
|
|
1023
|
+
const res = await adminFetch(`/admin/users/${sanitizedUserId}`, {
|
|
1024
|
+
method: "PUT",
|
|
1025
|
+
body: JSON.stringify(body)
|
|
1026
|
+
});
|
|
1027
|
+
const userData = await res.json();
|
|
1028
|
+
return toUser(userData);
|
|
1025
1029
|
};
|
|
1026
1030
|
var deleteUser = async (userId) => {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
}
|
|
1031
|
-
try {
|
|
1032
|
-
const user = getAdminUser();
|
|
1033
|
-
await user.admin.deleteUser({ id: userId });
|
|
1034
|
-
} catch (error) {
|
|
1035
|
-
if (error instanceof AuthError) throw error;
|
|
1036
|
-
throw new AuthError(error.message, void 0, { cause: error });
|
|
1037
|
-
}
|
|
1031
|
+
assertServer();
|
|
1032
|
+
const sanitizedUserId = sanitizeUserId(userId);
|
|
1033
|
+
await adminFetch(`/admin/users/${sanitizedUserId}`, { method: "DELETE" });
|
|
1038
1034
|
};
|
|
1039
1035
|
var admin = { listUsers, getUser: getUser2, createUser, updateUser: updateUser2, deleteUser };
|
|
1040
1036
|
// Annotate the CommonJS export names for ESM import in node:
|