@better-auth-ui/core 1.6.31 → 1.6.32

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.
@@ -0,0 +1,5 @@
1
+ export declare const adminLocalization: {
2
+ /** @remarks `"Stop impersonating"` */
3
+ stopImpersonating: string;
4
+ };
5
+ export type AdminLocalization = typeof adminLocalization;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Mutation keys contributed by the admin plugin.
3
+ */
4
+ export declare const adminMutationKeys: {
5
+ /** Root key for every admin mutation. */
6
+ readonly all: readonly ["auth", "admin"];
7
+ /** Key for `admin.stopImpersonating`. */
8
+ readonly stopImpersonating: readonly ["auth", "admin", "stopImpersonating"];
9
+ };
@@ -0,0 +1,32 @@
1
+ import { AdminLocalization } from './admin-localization';
2
+ export type AdminPluginOptions = {
3
+ /**
4
+ * Override the plugin's default localization strings.
5
+ * @remarks `AdminLocalization`
6
+ */
7
+ localization?: Partial<AdminLocalization>;
8
+ };
9
+ export type ImpersonatingSession = {
10
+ session: {
11
+ impersonatedBy: string;
12
+ };
13
+ };
14
+ /**
15
+ * Check whether a Better Auth session belongs to an impersonated user.
16
+ */
17
+ export declare function isImpersonatingSession(session: unknown): session is ImpersonatingSession;
18
+ /**
19
+ * Adds UI integrations for Better Auth's admin plugin.
20
+ *
21
+ * Pair this UI plugin with Better Auth's `admin()` server plugin and
22
+ * `adminClient()` client plugin.
23
+ */
24
+ export declare const adminPlugin: ((options?: AdminPluginOptions | undefined) => {
25
+ localization: {
26
+ stopImpersonating: string;
27
+ };
28
+ } & {
29
+ id: "admin";
30
+ }) & {
31
+ id: "admin";
32
+ };
@@ -0,0 +1,25 @@
1
+ export declare const oauthProviderLocalization: {
2
+ /** @remarks `"Authorize {{client}}"` */
3
+ authorize: string;
4
+ /** @remarks `"{{client}} wants to access your account."` */
5
+ authorizationDescription: string;
6
+ /** @remarks `"This will allow {{client}} to:"` */
7
+ requestedPermissions: string;
8
+ /** @remarks `"Signed in as"` */
9
+ signedInAs: string;
10
+ /** @remarks `"Allow"` */
11
+ allow: string;
12
+ /** @remarks `"Cancel"` */
13
+ cancel: string;
14
+ /** @remarks `"Privacy policy"` */
15
+ privacyPolicy: string;
16
+ /** @remarks `"Terms of service"` */
17
+ termsOfService: string;
18
+ /** @remarks `"Invalid authorization request"` */
19
+ invalidRequest: string;
20
+ /** @remarks `"This authorization request is missing required information or is no longer valid."` */
21
+ invalidRequestDescription: string;
22
+ /** @remarks `"Application"` */
23
+ application: string;
24
+ };
25
+ export type OAuthProviderLocalization = typeof oauthProviderLocalization;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Mutation keys contributed by the OAuth provider plugin.
3
+ *
4
+ * All keys live under the shared `["auth"]` namespace so global auth
5
+ * mutation observers handle errors consistently.
6
+ */
7
+ export declare const oauthProviderMutationKeys: {
8
+ /** Prefix matching every OAuth provider mutation. */
9
+ readonly all: readonly ["auth", "oauthProvider"];
10
+ /** Key for accepting or denying an OAuth authorization request. */
11
+ readonly consent: readonly ["auth", "oauthProvider", "consent"];
12
+ };
@@ -0,0 +1,78 @@
1
+ import { OAuthProviderLocalization } from './oauth-provider-localization';
2
+ declare module "../../lib/view-paths" {
3
+ /** Widens `AuthViewPaths` with the OAuth consent path when this plugin is imported. */
4
+ interface AuthViewPaths {
5
+ /** @default "consent" */
6
+ oauthConsent?: string;
7
+ }
8
+ }
9
+ export type OAuthScopeMetadata = {
10
+ /** Short permission label displayed to the user. */
11
+ label: string;
12
+ /** Optional explanation of the data or access represented by the scope. */
13
+ description?: string;
14
+ };
15
+ export type OAuthScopeMetadataMap = Record<string, OAuthScopeMetadata>;
16
+ export declare const oauthProviderScopeMetadata: OAuthScopeMetadataMap;
17
+ export type OAuthAuthorizationRequest = {
18
+ clientId?: string;
19
+ scopes: string[];
20
+ };
21
+ /**
22
+ * Keep client-controlled links and images on browser-safe web protocols.
23
+ */
24
+ export declare function sanitizeOAuthClientUrl(value: string | null | undefined): string | undefined;
25
+ /**
26
+ * Read the display-safe parts of Better Auth's signed authorization query.
27
+ *
28
+ * The complete query string must remain in the browser URL so
29
+ * `oauthProviderClient()` can forward and verify it during consent.
30
+ */
31
+ export declare function parseOAuthAuthorizationRequest(search: string): OAuthAuthorizationRequest;
32
+ export type OAuthProviderPluginOptions = {
33
+ /**
34
+ * Override the plugin's default localization strings.
35
+ * @remarks `OAuthProviderLocalization`
36
+ */
37
+ localization?: Partial<OAuthProviderLocalization>;
38
+ /**
39
+ * URL segment for the OAuth consent view.
40
+ * @remarks `string`
41
+ * @default "consent"
42
+ */
43
+ path?: string;
44
+ /**
45
+ * Labels and descriptions for custom OAuth scopes.
46
+ *
47
+ * Entries override the built-in metadata for `openid`, `profile`, `email`,
48
+ * and `offline_access`. Unknown scopes remain visible using their raw value.
49
+ */
50
+ scopeMetadata?: OAuthScopeMetadataMap;
51
+ };
52
+ export declare const oauthProviderPlugin: ((options?: OAuthProviderPluginOptions | undefined) => {
53
+ localization: {
54
+ authorize: string;
55
+ authorizationDescription: string;
56
+ requestedPermissions: string;
57
+ signedInAs: string;
58
+ allow: string;
59
+ cancel: string;
60
+ privacyPolicy: string;
61
+ termsOfService: string;
62
+ invalidRequest: string;
63
+ invalidRequestDescription: string;
64
+ application: string;
65
+ };
66
+ scopeMetadata: {
67
+ [x: string]: OAuthScopeMetadata;
68
+ };
69
+ viewPaths: {
70
+ auth: {
71
+ oauthConsent: string;
72
+ };
73
+ };
74
+ } & {
75
+ id: "oauthProvider";
76
+ }) & {
77
+ id: "oauthProvider";
78
+ };
@@ -0,0 +1,9 @@
1
+ /** Query keys contributed by the OAuth provider plugin. */
2
+ export declare const oauthProviderQueryKeys: {
3
+ /** Prefix matching every OAuth provider query. */
4
+ readonly all: readonly ["auth", "oauthProvider"];
5
+ /** Prefix for public OAuth client metadata queries. */
6
+ readonly publicClients: readonly ["auth", "oauthProvider", "publicClient"];
7
+ /** Key for the public metadata of a specific OAuth client. */
8
+ readonly publicClient: (clientId: string | undefined) => readonly ["auth", "oauthProvider", "publicClient", string | null];
9
+ };
package/dist/plugins.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ export * from './plugins/admin/admin-localization';
2
+ export * from './plugins/admin/admin-mutation-keys';
3
+ export * from './plugins/admin/admin-plugin';
1
4
  export * from './plugins/api-key/api-key-localization';
2
5
  export * from './plugins/api-key/api-key-mutation-keys';
3
6
  export * from './plugins/api-key/api-key-plugin';
@@ -17,6 +20,10 @@ export * from './plugins/multi-session/multi-session-localization';
17
20
  export * from './plugins/multi-session/multi-session-mutation-keys';
18
21
  export * from './plugins/multi-session/multi-session-plugin';
19
22
  export * from './plugins/multi-session/multi-session-query-keys';
23
+ export * from './plugins/oauth-provider/oauth-provider-localization';
24
+ export * from './plugins/oauth-provider/oauth-provider-mutation-keys';
25
+ export * from './plugins/oauth-provider/oauth-provider-plugin';
26
+ export * from './plugins/oauth-provider/oauth-provider-query-keys';
20
27
  export * from './plugins/organization/organization-localization';
21
28
  export * from './plugins/organization/organization-mutation-keys';
22
29
  export * from './plugins/organization/organization-plugin';
package/dist/plugins.js CHANGED
@@ -1,6 +1,22 @@
1
1
  import { n as e, r as t, t as n } from "./create-auth-plugin-D4wsYnHD.js";
2
- //#region src/plugins/api-key/api-key-localization.ts
3
- var r = {
2
+ //#region src/plugins/admin/admin-localization.ts
3
+ var r = { stopImpersonating: "Stop impersonating" }, i = {
4
+ all: ["auth", "admin"],
5
+ stopImpersonating: [
6
+ "auth",
7
+ "admin",
8
+ "stopImpersonating"
9
+ ]
10
+ };
11
+ //#endregion
12
+ //#region src/plugins/admin/admin-plugin.ts
13
+ function a(e) {
14
+ return !e || typeof e != "object" || !("session" in e) || !e.session || typeof e.session != "object" || !("impersonatedBy" in e.session) ? !1 : typeof e.session.impersonatedBy == "string" && e.session.impersonatedBy.length > 0;
15
+ }
16
+ var o = n("admin", (e = {}) => ({ localization: {
17
+ ...r,
18
+ ...e.localization
19
+ } })), s = {
4
20
  apiKey: "API key",
5
21
  apiKeys: "API keys",
6
22
  apiKeysDescription: "Create an API key for programmatic access to your account.",
@@ -12,7 +28,7 @@ var r = {
12
28
  deleteApiKey: "Delete API key",
13
29
  deleteApiKeyWarning: "This action cannot be undone. Any service using this API key will stop working immediately.",
14
30
  dismissNewKey: "I've saved my key"
15
- }, i = {
31
+ }, c = {
16
32
  all: ["auth", "apiKey"],
17
33
  create: [
18
34
  "auth",
@@ -24,28 +40,28 @@ var r = {
24
40
  "apiKey",
25
41
  "delete"
26
42
  ]
27
- }, a = n("apiKey", (e = {}) => ({
43
+ }, l = n("apiKey", (e = {}) => ({
28
44
  localization: {
29
- ...r,
45
+ ...s,
30
46
  ...e.localization
31
47
  },
32
48
  organization: e.organization ?? !1
33
- })), o = {
49
+ })), u = {
34
50
  all: (t) => [...e.user(t), "apiKey"],
35
- lists: (e) => [...o.all(e), "list"],
36
- list: (e, t) => [...o.lists(e), t ?? null]
37
- }, s = {
51
+ lists: (e) => [...u.all(e), "list"],
52
+ list: (e, t) => [...u.lists(e), t ?? null]
53
+ }, d = {
38
54
  deleteAccount: "Delete account",
39
55
  deleteAccountDescription: "Permanently remove your account and all associated data. This cannot be undone.",
40
56
  deleteUserVerificationSent: "Check your email to confirm account deletion.",
41
57
  deleteUserSuccess: "Your account has been deleted."
42
- }, c = { deleteUser: ["auth", "deleteUser"] }, l = n("deleteUser", (e = {}) => ({
58
+ }, f = { deleteUser: ["auth", "deleteUser"] }, p = n("deleteUser", (e = {}) => ({
43
59
  localization: {
44
- ...s,
60
+ ...d,
45
61
  ...e.localization
46
62
  },
47
63
  sendDeleteAccountVerification: e.sendDeleteAccountVerification ?? !1
48
- })), u = {
64
+ })), m = {
49
65
  deviceAuthorization: "Device Authorization",
50
66
  deviceAuthorizationDescription: "Enter the code displayed on your device.",
51
67
  deviceCode: "Device code",
@@ -61,7 +77,7 @@ var r = {
61
77
  deviceDenied: "Device Denied",
62
78
  deviceDeniedDescription: "The device was not granted access to your account.",
63
79
  returnToApplication: "Return to application"
64
- }, d = {
80
+ }, h = {
65
81
  all: ["auth", "deviceAuthorization"],
66
82
  verify: [
67
83
  "auth",
@@ -78,47 +94,47 @@ var r = {
78
94
  "deviceAuthorization",
79
95
  "deny"
80
96
  ]
81
- }, f = 8;
82
- function p(e) {
83
- return e === void 0 || !Number.isFinite(e) ? f : Math.max(1, Math.floor(e));
97
+ }, g = 8;
98
+ function _(e) {
99
+ return e === void 0 || !Number.isFinite(e) ? g : Math.max(1, Math.floor(e));
84
100
  }
85
- var m = n("deviceAuthorization", (e = {}) => ({
101
+ var v = n("deviceAuthorization", (e = {}) => ({
86
102
  localization: {
87
- ...u,
103
+ ...m,
88
104
  ...e.localization
89
105
  },
90
- userCodeLength: p(e.userCodeLength),
106
+ userCodeLength: _(e.userCodeLength),
91
107
  viewPaths: { auth: { deviceAuthorization: e.path ?? "device" } }
92
- })), h = {
108
+ })), y = {
93
109
  lastUsed: "Last used",
94
110
  lastUsedShort: "Last"
95
- }, g = n("lastLoginMethod", (e = {}) => ({ localization: {
96
- ...h,
111
+ }, b = n("lastLoginMethod", (e = {}) => ({ localization: {
112
+ ...y,
97
113
  ...e.localization
98
- } })), _ = {
114
+ } })), x = {
99
115
  magicLink: "Magic Link",
100
116
  sendMagicLink: "Send Magic Link",
101
117
  magicLinkSent: "Check your email for the magic link",
102
118
  magicLinkSentTo: "We sent a magic link to {{email}}"
103
- }, v = { signIn: [
119
+ }, S = { signIn: [
104
120
  "auth",
105
121
  "signIn",
106
122
  "magicLink"
107
- ] }, y = n("magicLink", (e = {}) => ({
123
+ ] }, C = n("magicLink", (e = {}) => ({
108
124
  localization: {
109
- ..._,
125
+ ...x,
110
126
  ...e.localization
111
127
  },
112
128
  viewPaths: { auth: {
113
129
  magicLink: e.path ?? "magic-link",
114
130
  magicLinkSent: e.sentPath ?? "magic-link-sent"
115
131
  } }
116
- })), b = {
132
+ })), w = {
117
133
  switchAccount: "Switch Account",
118
134
  addAccount: "Add Account",
119
135
  manageAccounts: "Manage accounts",
120
136
  manageAccountsDescription: "Manage your accounts for secure access."
121
- }, x = {
137
+ }, T = {
122
138
  all: ["auth", "multiSession"],
123
139
  revoke: [
124
140
  "auth",
@@ -130,14 +146,84 @@ var m = n("deviceAuthorization", (e = {}) => ({
130
146
  "multiSession",
131
147
  "setActive"
132
148
  ]
133
- }, S = n("multiSession", (e = {}) => ({ localization: {
134
- ...b,
149
+ }, E = n("multiSession", (e = {}) => ({ localization: {
150
+ ...w,
135
151
  ...e.localization
136
- } })), C = {
152
+ } })), D = {
137
153
  all: (t) => [...e.user(t), "multiSession"],
138
- lists: (e) => [...C.all(e), "list"],
139
- list: (e, t) => [...C.lists(e), t ?? null]
140
- }, w = {
154
+ lists: (e) => [...D.all(e), "list"],
155
+ list: (e, t) => [...D.lists(e), t ?? null]
156
+ }, O = {
157
+ authorize: "Authorize {{client}}",
158
+ authorizationDescription: "{{client}} wants to access your account.",
159
+ requestedPermissions: "This will allow {{client}} to:",
160
+ signedInAs: "Signed in as",
161
+ allow: "Allow",
162
+ cancel: "Cancel",
163
+ privacyPolicy: "Privacy policy",
164
+ termsOfService: "Terms of service",
165
+ invalidRequest: "Invalid authorization request",
166
+ invalidRequestDescription: "This authorization request is missing required information or is no longer valid.",
167
+ application: "Application"
168
+ }, k = {
169
+ all: ["auth", "oauthProvider"],
170
+ consent: [
171
+ "auth",
172
+ "oauthProvider",
173
+ "consent"
174
+ ]
175
+ }, A = {
176
+ openid: {
177
+ label: "Verify your identity",
178
+ description: "Access your unique account identifier."
179
+ },
180
+ profile: {
181
+ label: "View your profile",
182
+ description: "View your name and profile picture."
183
+ },
184
+ email: {
185
+ label: "View your email address",
186
+ description: "View your email address and whether it is verified."
187
+ },
188
+ offline_access: {
189
+ label: "Maintain access",
190
+ description: "Access your data when you are not actively using the application."
191
+ }
192
+ };
193
+ function j(e) {
194
+ if (e) try {
195
+ let t = new URL(e);
196
+ return t.protocol === "https:" || t.protocol === "http:" ? t.href : void 0;
197
+ } catch {
198
+ return;
199
+ }
200
+ }
201
+ function M(e) {
202
+ let t = new URLSearchParams(e);
203
+ return {
204
+ clientId: t.get("client_id")?.trim() || void 0,
205
+ scopes: Array.from(new Set((t.get("scope") ?? "").split(/\s+/).map((e) => e.trim()).filter(Boolean)))
206
+ };
207
+ }
208
+ var N = n("oauthProvider", (e = {}) => ({
209
+ localization: {
210
+ ...O,
211
+ ...e.localization
212
+ },
213
+ scopeMetadata: {
214
+ ...A,
215
+ ...e.scopeMetadata
216
+ },
217
+ viewPaths: { auth: { oauthConsent: e.path ?? "consent" } }
218
+ })), P = {
219
+ all: ["auth", "oauthProvider"],
220
+ publicClients: [
221
+ "auth",
222
+ "oauthProvider",
223
+ "publicClient"
224
+ ],
225
+ publicClient: (e) => [...P.publicClients, e ?? null]
226
+ }, F = {
141
227
  accept: "Accept",
142
228
  accepted: "Accepted",
143
229
  actions: "Actions",
@@ -194,7 +280,7 @@ var m = n("deviceAuthorization", (e = {}) => ({
194
280
  status: "Status",
195
281
  uploadLogo: "Upload logo",
196
282
  userInvitationsEmptyDescription: "Invitations to join an organization will show up here."
197
- }, T = {
283
+ }, I = {
198
284
  all: ["auth", "organization"],
199
285
  create: [
200
286
  "auth",
@@ -256,9 +342,9 @@ var m = n("deviceAuthorization", (e = {}) => ({
256
342
  "organization",
257
343
  "checkSlug"
258
344
  ]
259
- }, E = n("organization", (e = {}) => {
345
+ }, L = n("organization", (e = {}) => {
260
346
  let n = {
261
- ...w,
347
+ ...F,
262
348
  ...e.localization
263
349
  };
264
350
  return {
@@ -286,38 +372,38 @@ var m = n("deviceAuthorization", (e = {}) => ({
286
372
  }
287
373
  }
288
374
  };
289
- }), D = {
375
+ }), R = {
290
376
  all: (t) => [...e.user(t), "organization"],
291
- lists: (e) => [...D.all(e), "list"],
292
- list: (e, t) => [...D.lists(e), t ?? null],
293
- fullDetails: (e) => [...D.all(e), "fullDetails"],
294
- fullDetail: (e, t) => [...D.fullDetails(e), t ?? null],
295
- activeOrganizations: (e) => [...D.all(e), "active"],
296
- activeOrganization: (e, t) => [...D.activeOrganizations(e), t ?? null],
377
+ lists: (e) => [...R.all(e), "list"],
378
+ list: (e, t) => [...R.lists(e), t ?? null],
379
+ fullDetails: (e) => [...R.all(e), "fullDetails"],
380
+ fullDetail: (e, t) => [...R.fullDetails(e), t ?? null],
381
+ activeOrganizations: (e) => [...R.all(e), "active"],
382
+ activeOrganization: (e, t) => [...R.activeOrganizations(e), t ?? null],
297
383
  members: {
298
- all: (e) => [...D.all(e), "members"],
299
- lists: (e) => [...D.members.all(e), "list"],
300
- list: (e, t) => [...D.members.lists(e), t ?? null]
384
+ all: (e) => [...R.all(e), "members"],
385
+ lists: (e) => [...R.members.all(e), "list"],
386
+ list: (e, t) => [...R.members.lists(e), t ?? null]
301
387
  },
302
388
  invitations: {
303
- all: (e) => [...D.all(e), "invitations"],
304
- lists: (e) => [...D.invitations.all(e), "list"],
305
- list: (e, t) => [...D.invitations.lists(e), t ?? null]
389
+ all: (e) => [...R.all(e), "invitations"],
390
+ lists: (e) => [...R.invitations.all(e), "list"],
391
+ list: (e, t) => [...R.invitations.lists(e), t ?? null]
306
392
  },
307
393
  userInvitations: {
308
- all: (e) => [...D.all(e), "userInvitations"],
309
- lists: (e) => [...D.userInvitations.all(e), "list"],
310
- list: (e, t) => [...D.userInvitations.lists(e), t ?? null]
394
+ all: (e) => [...R.all(e), "userInvitations"],
395
+ lists: (e) => [...R.userInvitations.all(e), "list"],
396
+ list: (e, t) => [...R.userInvitations.lists(e), t ?? null]
311
397
  },
312
398
  permissions: {
313
- all: (e) => [...D.all(e), "permissions"],
399
+ all: (e) => [...R.all(e), "permissions"],
314
400
  has: (e, t) => [
315
- ...D.permissions.all(e),
401
+ ...R.permissions.all(e),
316
402
  "has",
317
403
  t ?? null
318
404
  ]
319
405
  }
320
- }, O = {
406
+ }, z = {
321
407
  passkey: "Passkey",
322
408
  addPasskey: "Add passkey",
323
409
  deletePasskey: "Delete passkey {{name}}",
@@ -327,7 +413,7 @@ var m = n("deviceAuthorization", (e = {}) => ({
327
413
  passkeysDescription: "Create a passkey to securely access your account.",
328
414
  noPasskeys: "No passkeys",
329
415
  name: "Name"
330
- }, k = {
416
+ }, B = {
331
417
  signIn: [
332
418
  "auth",
333
419
  "signIn",
@@ -343,22 +429,22 @@ var m = n("deviceAuthorization", (e = {}) => ({
343
429
  "passkey",
344
430
  "deletePasskey"
345
431
  ]
346
- }, A = n("passkey", (e = {}) => ({ localization: {
347
- ...O,
432
+ }, V = n("passkey", (e = {}) => ({ localization: {
433
+ ...z,
348
434
  ...e.localization
349
- } })), j = {
435
+ } })), H = {
350
436
  all: (t) => [...e.user(t), "passkey"],
351
- lists: (e) => [...j.all(e), "list"],
352
- list: (e, t) => [...j.lists(e), t ?? null]
353
- }, M = {
437
+ lists: (e) => [...H.all(e), "list"],
438
+ list: (e, t) => [...H.lists(e), t ?? null]
439
+ }, U = {
354
440
  appearance: "Appearance",
355
441
  theme: "Theme",
356
442
  system: "System",
357
443
  light: "Light",
358
444
  dark: "Dark"
359
- }, N = n("theme", (e) => ({
445
+ }, W = n("theme", (e) => ({
360
446
  localization: {
361
- ...M,
447
+ ...U,
362
448
  ...e.localization
363
449
  },
364
450
  theme: e.theme ?? "system",
@@ -368,7 +454,7 @@ var m = n("deviceAuthorization", (e = {}) => ({
368
454
  "light",
369
455
  "dark"
370
456
  ]
371
- })), P = {
457
+ })), G = {
372
458
  username: "Username",
373
459
  usernamePlaceholder: "Username",
374
460
  usernameOrEmailPlaceholder: "Username or email",
@@ -376,16 +462,16 @@ var m = n("deviceAuthorization", (e = {}) => ({
376
462
  usernameTaken: "Username is already taken. Please try another.",
377
463
  displayUsername: "Display Username",
378
464
  displayUsernamePlaceholder: "Display Username"
379
- }, F = {
465
+ }, K = {
380
466
  signIn: [
381
467
  "auth",
382
468
  "signIn",
383
469
  "username"
384
470
  ],
385
471
  isUsernameAvailable: ["auth", "isUsernameAvailable"]
386
- }, I = n("username", (e = {}) => {
472
+ }, q = n("username", (e = {}) => {
387
473
  let t = e.minUsernameLength ?? 3, n = e.maxUsernameLength ?? 30, r = {
388
- ...P,
474
+ ...G,
389
475
  ...e.localization
390
476
  };
391
477
  return {
@@ -413,4 +499,4 @@ var m = n("deviceAuthorization", (e = {}) => ({
413
499
  };
414
500
  });
415
501
  //#endregion
416
- export { r as apiKeyLocalization, i as apiKeyMutationKeys, a as apiKeyPlugin, o as apiKeyQueryKeys, s as deleteUserLocalization, c as deleteUserMutationKeys, l as deleteUserPlugin, u as deviceAuthorizationLocalization, d as deviceAuthorizationMutationKeys, m as deviceAuthorizationPlugin, h as lastLoginMethodLocalization, g as lastLoginMethodPlugin, _ as magicLinkLocalization, v as magicLinkMutationKeys, y as magicLinkPlugin, b as multiSessionLocalization, x as multiSessionMutationKeys, S as multiSessionPlugin, C as multiSessionQueryKeys, w as organizationLocalization, T as organizationMutationKeys, E as organizationPlugin, D as organizationQueryKeys, O as passkeyLocalization, k as passkeyMutationKeys, A as passkeyPlugin, j as passkeyQueryKeys, M as themeLocalization, N as themePlugin, P as usernameLocalization, F as usernameMutationKeys, I as usernamePlugin };
502
+ export { r as adminLocalization, i as adminMutationKeys, o as adminPlugin, s as apiKeyLocalization, c as apiKeyMutationKeys, l as apiKeyPlugin, u as apiKeyQueryKeys, d as deleteUserLocalization, f as deleteUserMutationKeys, p as deleteUserPlugin, m as deviceAuthorizationLocalization, h as deviceAuthorizationMutationKeys, v as deviceAuthorizationPlugin, a as isImpersonatingSession, y as lastLoginMethodLocalization, b as lastLoginMethodPlugin, x as magicLinkLocalization, S as magicLinkMutationKeys, C as magicLinkPlugin, w as multiSessionLocalization, T as multiSessionMutationKeys, E as multiSessionPlugin, D as multiSessionQueryKeys, O as oauthProviderLocalization, k as oauthProviderMutationKeys, N as oauthProviderPlugin, P as oauthProviderQueryKeys, A as oauthProviderScopeMetadata, F as organizationLocalization, I as organizationMutationKeys, L as organizationPlugin, R as organizationQueryKeys, M as parseOAuthAuthorizationRequest, z as passkeyLocalization, B as passkeyMutationKeys, V as passkeyPlugin, H as passkeyQueryKeys, j as sanitizeOAuthClientUrl, U as themeLocalization, W as themePlugin, G as usernameLocalization, K as usernameMutationKeys, q as usernamePlugin };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth-ui/core",
3
- "version": "1.6.31",
3
+ "version": "1.6.32",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "vite build",
@@ -0,0 +1,6 @@
1
+ export const adminLocalization = {
2
+ /** @remarks `"Stop impersonating"` */
3
+ stopImpersonating: "Stop impersonating"
4
+ }
5
+
6
+ export type AdminLocalization = typeof adminLocalization
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Mutation keys contributed by the admin plugin.
3
+ */
4
+ export const adminMutationKeys = {
5
+ /** Root key for every admin mutation. */
6
+ all: ["auth", "admin"] as const,
7
+ /** Key for `admin.stopImpersonating`. */
8
+ stopImpersonating: ["auth", "admin", "stopImpersonating"] as const
9
+ } as const
@@ -0,0 +1,52 @@
1
+ import { createAuthPlugin } from "../../lib/create-auth-plugin"
2
+ import { type AdminLocalization, adminLocalization } from "./admin-localization"
3
+
4
+ export type AdminPluginOptions = {
5
+ /**
6
+ * Override the plugin's default localization strings.
7
+ * @remarks `AdminLocalization`
8
+ */
9
+ localization?: Partial<AdminLocalization>
10
+ }
11
+
12
+ export type ImpersonatingSession = {
13
+ session: {
14
+ impersonatedBy: string
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Check whether a Better Auth session belongs to an impersonated user.
20
+ */
21
+ export function isImpersonatingSession(
22
+ session: unknown
23
+ ): session is ImpersonatingSession {
24
+ if (
25
+ !session ||
26
+ typeof session !== "object" ||
27
+ !("session" in session) ||
28
+ !session.session ||
29
+ typeof session.session !== "object" ||
30
+ !("impersonatedBy" in session.session)
31
+ ) {
32
+ return false
33
+ }
34
+
35
+ return (
36
+ typeof session.session.impersonatedBy === "string" &&
37
+ session.session.impersonatedBy.length > 0
38
+ )
39
+ }
40
+
41
+ /**
42
+ * Adds UI integrations for Better Auth's admin plugin.
43
+ *
44
+ * Pair this UI plugin with Better Auth's `admin()` server plugin and
45
+ * `adminClient()` client plugin.
46
+ */
47
+ export const adminPlugin = createAuthPlugin(
48
+ "admin",
49
+ (options: AdminPluginOptions = {}) => ({
50
+ localization: { ...adminLocalization, ...options.localization }
51
+ })
52
+ )
@@ -0,0 +1,27 @@
1
+ export const oauthProviderLocalization = {
2
+ /** @remarks `"Authorize {{client}}"` */
3
+ authorize: "Authorize {{client}}",
4
+ /** @remarks `"{{client}} wants to access your account."` */
5
+ authorizationDescription: "{{client}} wants to access your account.",
6
+ /** @remarks `"This will allow {{client}} to:"` */
7
+ requestedPermissions: "This will allow {{client}} to:",
8
+ /** @remarks `"Signed in as"` */
9
+ signedInAs: "Signed in as",
10
+ /** @remarks `"Allow"` */
11
+ allow: "Allow",
12
+ /** @remarks `"Cancel"` */
13
+ cancel: "Cancel",
14
+ /** @remarks `"Privacy policy"` */
15
+ privacyPolicy: "Privacy policy",
16
+ /** @remarks `"Terms of service"` */
17
+ termsOfService: "Terms of service",
18
+ /** @remarks `"Invalid authorization request"` */
19
+ invalidRequest: "Invalid authorization request",
20
+ /** @remarks `"This authorization request is missing required information or is no longer valid."` */
21
+ invalidRequestDescription:
22
+ "This authorization request is missing required information or is no longer valid.",
23
+ /** @remarks `"Application"` */
24
+ application: "Application"
25
+ }
26
+
27
+ export type OAuthProviderLocalization = typeof oauthProviderLocalization
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Mutation keys contributed by the OAuth provider plugin.
3
+ *
4
+ * All keys live under the shared `["auth"]` namespace so global auth
5
+ * mutation observers handle errors consistently.
6
+ */
7
+ export const oauthProviderMutationKeys = {
8
+ /** Prefix matching every OAuth provider mutation. */
9
+ all: ["auth", "oauthProvider"] as const,
10
+ /** Key for accepting or denying an OAuth authorization request. */
11
+ consent: ["auth", "oauthProvider", "consent"] as const
12
+ } as const
@@ -0,0 +1,132 @@
1
+ import { createAuthPlugin } from "../../lib/create-auth-plugin"
2
+ // Side-effect import so this file participates in declaration merging on the
3
+ // same module instance that external consumers reach via `@better-auth-ui/core`.
4
+ import type {} from "../../lib/view-paths"
5
+ import {
6
+ type OAuthProviderLocalization,
7
+ oauthProviderLocalization
8
+ } from "./oauth-provider-localization"
9
+
10
+ declare module "../../lib/view-paths" {
11
+ /** Widens `AuthViewPaths` with the OAuth consent path when this plugin is imported. */
12
+ interface AuthViewPaths {
13
+ /** @default "consent" */
14
+ oauthConsent?: string
15
+ }
16
+ }
17
+
18
+ export type OAuthScopeMetadata = {
19
+ /** Short permission label displayed to the user. */
20
+ label: string
21
+ /** Optional explanation of the data or access represented by the scope. */
22
+ description?: string
23
+ }
24
+
25
+ export type OAuthScopeMetadataMap = Record<string, OAuthScopeMetadata>
26
+
27
+ export const oauthProviderScopeMetadata: OAuthScopeMetadataMap = {
28
+ openid: {
29
+ label: "Verify your identity",
30
+ description: "Access your unique account identifier."
31
+ },
32
+ profile: {
33
+ label: "View your profile",
34
+ description: "View your name and profile picture."
35
+ },
36
+ email: {
37
+ label: "View your email address",
38
+ description: "View your email address and whether it is verified."
39
+ },
40
+ offline_access: {
41
+ label: "Maintain access",
42
+ description:
43
+ "Access your data when you are not actively using the application."
44
+ }
45
+ }
46
+
47
+ export type OAuthAuthorizationRequest = {
48
+ clientId?: string
49
+ scopes: string[]
50
+ }
51
+
52
+ /**
53
+ * Keep client-controlled links and images on browser-safe web protocols.
54
+ */
55
+ export function sanitizeOAuthClientUrl(
56
+ value: string | null | undefined
57
+ ): string | undefined {
58
+ if (!value) return undefined
59
+
60
+ try {
61
+ const url = new URL(value)
62
+
63
+ return url.protocol === "https:" || url.protocol === "http:"
64
+ ? url.href
65
+ : undefined
66
+ } catch {
67
+ return undefined
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Read the display-safe parts of Better Auth's signed authorization query.
73
+ *
74
+ * The complete query string must remain in the browser URL so
75
+ * `oauthProviderClient()` can forward and verify it during consent.
76
+ */
77
+ export function parseOAuthAuthorizationRequest(
78
+ search: string
79
+ ): OAuthAuthorizationRequest {
80
+ const params = new URLSearchParams(search)
81
+ const clientId = params.get("client_id")?.trim() || undefined
82
+ const scopes = Array.from(
83
+ new Set(
84
+ (params.get("scope") ?? "")
85
+ .split(/\s+/)
86
+ .map((scope) => scope.trim())
87
+ .filter(Boolean)
88
+ )
89
+ )
90
+
91
+ return { clientId, scopes }
92
+ }
93
+
94
+ export type OAuthProviderPluginOptions = {
95
+ /**
96
+ * Override the plugin's default localization strings.
97
+ * @remarks `OAuthProviderLocalization`
98
+ */
99
+ localization?: Partial<OAuthProviderLocalization>
100
+ /**
101
+ * URL segment for the OAuth consent view.
102
+ * @remarks `string`
103
+ * @default "consent"
104
+ */
105
+ path?: string
106
+ /**
107
+ * Labels and descriptions for custom OAuth scopes.
108
+ *
109
+ * Entries override the built-in metadata for `openid`, `profile`, `email`,
110
+ * and `offline_access`. Unknown scopes remain visible using their raw value.
111
+ */
112
+ scopeMetadata?: OAuthScopeMetadataMap
113
+ }
114
+
115
+ export const oauthProviderPlugin = createAuthPlugin(
116
+ "oauthProvider",
117
+ (options: OAuthProviderPluginOptions = {}) => ({
118
+ localization: {
119
+ ...oauthProviderLocalization,
120
+ ...options.localization
121
+ },
122
+ scopeMetadata: {
123
+ ...oauthProviderScopeMetadata,
124
+ ...options.scopeMetadata
125
+ },
126
+ viewPaths: {
127
+ auth: {
128
+ oauthConsent: options.path ?? "consent"
129
+ }
130
+ }
131
+ })
132
+ )
@@ -0,0 +1,10 @@
1
+ /** Query keys contributed by the OAuth provider plugin. */
2
+ export const oauthProviderQueryKeys = {
3
+ /** Prefix matching every OAuth provider query. */
4
+ all: ["auth", "oauthProvider"] as const,
5
+ /** Prefix for public OAuth client metadata queries. */
6
+ publicClients: ["auth", "oauthProvider", "publicClient"] as const,
7
+ /** Key for the public metadata of a specific OAuth client. */
8
+ publicClient: (clientId: string | undefined) =>
9
+ [...oauthProviderQueryKeys.publicClients, clientId ?? null] as const
10
+ } as const
package/src/plugins.ts CHANGED
@@ -1,3 +1,6 @@
1
+ export * from "./plugins/admin/admin-localization"
2
+ export * from "./plugins/admin/admin-mutation-keys"
3
+ export * from "./plugins/admin/admin-plugin"
1
4
  export * from "./plugins/api-key/api-key-localization"
2
5
  export * from "./plugins/api-key/api-key-mutation-keys"
3
6
  export * from "./plugins/api-key/api-key-plugin"
@@ -17,6 +20,10 @@ export * from "./plugins/multi-session/multi-session-localization"
17
20
  export * from "./plugins/multi-session/multi-session-mutation-keys"
18
21
  export * from "./plugins/multi-session/multi-session-plugin"
19
22
  export * from "./plugins/multi-session/multi-session-query-keys"
23
+ export * from "./plugins/oauth-provider/oauth-provider-localization"
24
+ export * from "./plugins/oauth-provider/oauth-provider-mutation-keys"
25
+ export * from "./plugins/oauth-provider/oauth-provider-plugin"
26
+ export * from "./plugins/oauth-provider/oauth-provider-query-keys"
20
27
  export * from "./plugins/organization/organization-localization"
21
28
  export * from "./plugins/organization/organization-mutation-keys"
22
29
  export * from "./plugins/organization/organization-plugin"