@protobase/server 0.47.1 → 0.49.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.
Files changed (105) hide show
  1. package/dist/admin-options.d.ts +2 -2
  2. package/dist/app-identity.d.ts +2 -2
  3. package/dist/app-name.d.ts +2 -0
  4. package/dist/auth-store.d.ts +3 -0
  5. package/dist/auth-store.js +3 -0
  6. package/dist/better-auth/auth-schema.d.ts +7 -8
  7. package/dist/better-auth/auth-schema.js +40 -42
  8. package/dist/better-auth/auth-settings.d.ts +8754 -0
  9. package/dist/better-auth/auth-settings.js +43 -0
  10. package/dist/better-auth/auth-tables.d.ts +1 -1
  11. package/dist/better-auth/auth-tables.js +11 -9
  12. package/dist/better-auth/authenticate-settings.d.ts +15 -0
  13. package/dist/better-auth/authenticate-settings.js +12 -0
  14. package/dist/better-auth/authenticator.d.ts +1 -1
  15. package/dist/better-auth/create-auth.d.ts +34 -14
  16. package/dist/better-auth/create-auth.js +27 -10
  17. package/dist/better-auth/mcp/mcp-auth-plugins.d.ts +2719 -0
  18. package/dist/better-auth/mcp/mcp-auth-plugins.js +68 -0
  19. package/dist/better-auth/mcp/mcp-plugins.d.ts +7 -2
  20. package/dist/better-auth/mcp/mcp-plugins.js +3 -68
  21. package/dist/better-auth/mcp/mcp-token-claims.js +1 -1
  22. package/dist/better-auth/organizations/store.d.ts +1 -0
  23. package/dist/better-auth/saml-plugin.d.ts +993 -0
  24. package/dist/better-auth/saml-plugin.js +36 -0
  25. package/dist/better-auth/saml-sign-in.d.ts +27 -1
  26. package/dist/better-auth/saml-sign-in.js +1 -33
  27. package/dist/better-auth/store/adoption.js +87 -0
  28. package/dist/better-auth/store/ddl.js +18 -0
  29. package/dist/better-auth/store/drift.d.ts +9 -0
  30. package/dist/better-auth/store/drift.js +18 -0
  31. package/dist/better-auth/store/migration-sql.js +15 -0
  32. package/dist/better-auth/store/migrations/001-core.js +80 -0
  33. package/dist/better-auth/store/migrations/002-two-factor.js +25 -0
  34. package/dist/better-auth/store/migrations/003-passkeys.js +29 -0
  35. package/dist/better-auth/store/migrations/004-sign-in-policy.js +22 -0
  36. package/dist/better-auth/store/migrations/005-staff-sign-in.js +25 -0
  37. package/dist/better-auth/store/migrations/006-organizations.js +50 -0
  38. package/dist/better-auth/store/migrations/007-mcp.js +150 -0
  39. package/dist/better-auth/store/migrations/index.js +22 -0
  40. package/dist/better-auth/store/migrations/migration.d.ts +3 -0
  41. package/dist/better-auth/store/migrations/migration.js +14 -0
  42. package/dist/better-auth/store/migrations-table.d.ts +7 -0
  43. package/dist/better-auth/store/migrations-table.js +23 -0
  44. package/dist/better-auth/store/resources-outside.d.ts +7 -0
  45. package/dist/better-auth/store/resources-outside.js +20 -0
  46. package/dist/better-auth/store/store-db.js +13 -0
  47. package/dist/better-auth/store/store-names.d.ts +2 -0
  48. package/dist/better-auth/store/store-names.js +14 -0
  49. package/dist/better-auth/store/table-names.d.ts +7 -0
  50. package/dist/better-auth/store/table-names.js +10 -0
  51. package/dist/better-auth/user-table.js +1 -1
  52. package/dist/better-auth/users.d.ts +2 -2
  53. package/dist/comments/comment-users.d.ts +1 -1
  54. package/dist/config-exports.d.ts +2 -0
  55. package/dist/config-exports.js +2 -0
  56. package/dist/create-admin.d.ts +6 -4
  57. package/dist/create-admin.js +3 -1
  58. package/dist/encryption/keyring.js +1 -1
  59. package/dist/files/options.d.ts +5 -8
  60. package/dist/files/provider-settings.d.ts +16 -0
  61. package/dist/files/provider-settings.js +17 -0
  62. package/dist/files/runtime.js +4 -4
  63. package/dist/forms/runtime.js +3 -3
  64. package/dist/index.d.ts +22 -19
  65. package/dist/index.js +11 -11
  66. package/dist/internal.d.ts +13 -0
  67. package/dist/internal.js +13 -0
  68. package/dist/jobs/declared-job.d.ts +24 -0
  69. package/dist/jobs/declared-job.js +26 -0
  70. package/dist/jobs/job-types.d.ts +2 -2
  71. package/dist/mcp/mcp-authenticator.js +3 -3
  72. package/dist/notifications/device-store-of.d.ts +2 -2
  73. package/dist/notifications/device-store-of.js +1 -1
  74. package/dist/notifications/device-store.d.ts +1 -1
  75. package/dist/notifications/device-store.js +1 -1
  76. package/dist/notifications/history-store-of.d.ts +2 -2
  77. package/dist/notifications/history-store-of.js +1 -1
  78. package/dist/notifications/history-store.d.ts +1 -1
  79. package/dist/notifications/history-store.js +1 -1
  80. package/dist/notifications/options.d.ts +3 -1
  81. package/dist/notifications/options.js +1 -1
  82. package/dist/notifications/schema.d.ts +3 -3
  83. package/dist/notifications/schema.js +8 -8
  84. package/dist/notifications/send-notification.js +1 -1
  85. package/dist/notifications/sender.d.ts +1 -1
  86. package/dist/notifications/sender.js +2 -2
  87. package/dist/notifications/senders-of.d.ts +1 -1
  88. package/dist/notifications/senders-of.js +1 -1
  89. package/dist/package.js +1 -1
  90. package/dist/webhooks/subscription.d.ts +1 -0
  91. package/dist/webhooks/table/options.d.ts +1 -1
  92. package/dist/webhooks/table/schema.d.ts +2 -2
  93. package/dist/webhooks/table/schema.js +2 -2
  94. package/dist/webhooks/table/webhook-table.js +2 -2
  95. package/dist/webhooks/table/webhooks-module.d.ts +108 -0
  96. package/dist/webhooks/table/webhooks-module.js +11 -0
  97. package/package.json +8 -5
  98. package/dist/better-auth/mcp/mcp-tables.js +0 -32
  99. package/dist/better-auth/snake-case-migration.js +0 -122
  100. package/dist/notifications/plugin.d.ts +0 -13
  101. package/dist/notifications/plugin.js +0 -16
  102. package/dist/project-config.d.ts +0 -54
  103. package/dist/project-config.js +0 -182
  104. package/dist/webhooks/table/plugin.d.ts +0 -10
  105. package/dist/webhooks/table/plugin.js +0 -18
@@ -0,0 +1,43 @@
1
+ import { buildAuth } from "./create-auth.js";
2
+ import { PostgresDialect } from "kysely";
3
+ //#region src/better-auth/auth-settings.ts
4
+ const organizationOptions = (organizations, hooks, app) => {
5
+ if (!organizations) return void 0;
6
+ const own = hooks.organizationHooks ?? {};
7
+ const betterAuthHooks = Object.fromEntries(Object.entries(own).map(([name, hook]) => [name, (input) => hook(input, app)]));
8
+ return {
9
+ ...organizations === true ? {} : organizations,
10
+ ...hooks.generateOrganizationId && { generateId: () => hooks.generateOrganizationId(app) },
11
+ ...hooks.onOrganizationCreated && { onCreated: (input) => hooks.onOrganizationCreated(input, app) },
12
+ ...hooks.beforeOrganizationDeleted && { beforeDelete: (organization) => hooks.beforeOrganizationDeleted(organization, app) },
13
+ ...Object.keys(betterAuthHooks).length > 0 && { hooks: betterAuthHooks }
14
+ };
15
+ };
16
+ /** createAuth's options for the `auth` settings, the store in the app's own database. */
17
+ const appAuthOptions = (settings, { pool, db, hooks = {}, mailer }) => {
18
+ const { schema = "auth", secret, generateUserId, mailer: mail, organizations, mcp, ...rest } = settings;
19
+ if (!secret) throw new Error("the auth secret is not set: give it the app's secret, PROTOBASE_SECRET, made with `openssl rand -base64 32`");
20
+ const app = { db };
21
+ const organizationsOptions = organizationOptions(organizations, hooks, app);
22
+ const userId = hooks.generateUserId ? () => hooks.generateUserId(app) : generateUserId;
23
+ const onUserCreated = hooks.onUserCreated && ((user, context) => hooks.onUserCreated(user, context, app));
24
+ return {
25
+ ...rest,
26
+ database: {
27
+ dialect: new PostgresDialect({ pool }),
28
+ type: "postgres",
29
+ schemaName: schema,
30
+ transaction: true
31
+ },
32
+ secret,
33
+ ...userId && { generateUserId: userId },
34
+ ...onUserCreated && { onUserCreated },
35
+ ...mail === false ? { mailer: false } : mailer && { mailer },
36
+ ...organizationsOptions && { organizations: organizationsOptions },
37
+ ...mcp && { mcp }
38
+ };
39
+ };
40
+ /** The app's Better Auth from its `auth` settings, built at serve time with only the plugins they turn on. */
41
+ const buildAppAuth = (settings, input) => buildAuth(appAuthOptions(settings, input));
42
+ //#endregion
43
+ export { appAuthOptions, buildAppAuth };
@@ -1,6 +1,6 @@
1
1
  import { AdminAuth } from "./create-auth.js";
2
2
  //#region src/better-auth/auth-tables.d.ts
3
- /** The admin store's tables with every plugin the project's auth has, which the assistant's queries must never read. */
3
+ /** The admin store's tables, which the assistant's queries and the app's resources must never read: the user table and `storeTableNames`. */
4
4
  export declare const authStoreTables: (auth: AdminAuth) => {
5
5
  schema: string | undefined;
6
6
  name: string;
@@ -1,11 +1,13 @@
1
- import { getSchema } from "better-auth/db";
1
+ import { storeNames } from "./store/store-names.js";
2
+ import { storeTableNames } from "./store/table-names.js";
2
3
  //#region src/better-auth/auth-tables.ts
3
- /** The schema the admin store lives in; the search path decides when its options name none. */
4
- const storeSchema = ({ options: { database } }) => database && "schemaName" in database ? database.schemaName : void 0;
5
- /** The admin store's tables with every plugin the project's auth has, which the assistant's queries must never read. */
6
- const authStoreTables = (auth) => Object.keys(getSchema(auth.options)).map((name) => ({
7
- schema: storeSchema(auth),
8
- name
9
- }));
4
+ /** The admin store's tables, which the assistant's queries and the app's resources must never read: the user table and `storeTableNames`. */
5
+ const authStoreTables = (auth) => {
6
+ const { schema, users } = storeNames(auth);
7
+ return [users.modelName, ...storeTableNames].map((name) => ({
8
+ schema,
9
+ name
10
+ }));
11
+ };
10
12
  //#endregion
11
- export { authStoreTables, storeSchema };
13
+ export { authStoreTables };
@@ -0,0 +1,15 @@
1
+ import { TenantValue } from "../types.js";
2
+ import { BetterAuthAuthenticator, BetterAuthAuthenticatorOptions } from "./authenticator.js";
3
+ import { AdminAuth } from "./create-auth.js";
4
+ //#region src/better-auth/authenticate-settings.d.ts
5
+ /**
6
+ * `authenticate` in `protobase.config.ts`: how the API verifies the app's tokens, as data. Without it, the tokens of
7
+ * the app's own `auth`; `jwksUrl` and `issuer` verify those of an auth server elsewhere instead.
8
+ */
9
+ export type AuthenticateSettings = Omit<BetterAuthAuthenticatorOptions, 'auth' | 'tenant'> & {
10
+ /** The one tenant everyone works in, for an app without organizations; never read from the token. */
11
+ tenant?: TenantValue;
12
+ };
13
+ /** The authenticator of the `authenticate` settings, over the app's Better Auth when it has one. */
14
+ export declare const buildAuthenticator: (settings?: AuthenticateSettings, auth?: AdminAuth) => BetterAuthAuthenticator;
15
+ //#endregion
@@ -0,0 +1,12 @@
1
+ import { betterAuthAuthenticator } from "./authenticator.js";
2
+ //#region src/better-auth/authenticate-settings.ts
3
+ /** The authenticator of the `authenticate` settings, over the app's Better Auth when it has one. */
4
+ const buildAuthenticator = (settings = {}, auth) => {
5
+ if (!auth && !settings.jwksUrl) throw new Error("No authenticator: give the config `auth`, or `authenticate.jwksUrl` and `issuer` for an auth server elsewhere; see https://docs.protobase.net/reference/auth/");
6
+ return betterAuthAuthenticator({
7
+ ...settings,
8
+ ...auth && { auth }
9
+ });
10
+ };
11
+ //#endregion
12
+ export { buildAuthenticator };
@@ -1,8 +1,8 @@
1
- import { AdminAuth } from "./create-auth.js";
2
1
  import { Authenticator, TenantValue } from "../types.js";
3
2
  import { JwtVerifyOptions } from "../auth/jwt.js";
4
3
  import { TrustedApp } from "./app-tokens.js";
5
4
  import { JwksCacheOptions } from "./jwks-cache.js";
5
+ import { AdminAuth } from "./create-auth.js";
6
6
  //#region src/better-auth/authenticator.d.ts
7
7
  export type BetterAuthAuthenticatorOptions = {
8
8
  /** The Better Auth instance of this process: keys are read from it directly, no HTTP round trip. */
@@ -1,21 +1,23 @@
1
+ import { UserColumn, UserTableOptions } from "./user-table.js";
2
+ import { Mailer } from "../mail/smtp-mailer.js";
3
+ import { SignInPolicy } from "./sign-in-policy.js";
1
4
  import { StaffSignIn } from "./staff-log.js";
2
5
  import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
3
6
  import { ConnectedApp } from "./mcp/connected-apps.js";
4
7
  import { ReplacingContext } from "./end-replaced-session.js";
5
8
  import { UserDeletionListener } from "./user-deletion.js";
6
- import "./auth-base-path.js";
7
- import { Mailer } from "../mail/smtp-mailer.js";
8
- import { OperatorProvider } from "./operator-provider.js";
9
9
  import { OrganizationRole } from "./organizations/store.js";
10
- import { SignInPolicy } from "./sign-in-policy.js";
11
- import { McpAuthOptions } from "./mcp/mcp-plugins.js";
12
10
  import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
11
+ import { McpAuthOptions } from "./mcp/mcp-plugins.js";
12
+ import { OperatorProvider } from "./operator-provider.js";
13
13
  import { PlatformSignIn } from "./platform-sign-in.js";
14
+ import "../index.js";
15
+ import "./auth-base-path.js";
16
+ import { mcpAuthPlugins } from "./mcp/mcp-auth-plugins.js";
14
17
  import { SsoOptions } from "./saml-sign-in.js";
18
+ import { samlPlugin } from "./saml-plugin.js";
15
19
  import { signUpPaths } from "./sign-up/sign-up-plugin.js";
16
20
  import { PasswordHash } from "./password-hashes.js";
17
- import { UserTableOptions } from "./user-table.js";
18
- import "../index.js";
19
21
  import { BetterAuthOptions } from "better-auth";
20
22
  import { JwtOptions } from "better-auth/plugins";
21
23
  //#region src/better-auth/create-auth.d.ts
@@ -169,7 +171,17 @@ export type UserCreatedHook = NonNullable<UserCreateHooks['after']>;
169
171
  */
170
172
  /** The configured roles with `admin` first; `admin` is added when missing. */
171
173
  export declare const normalizeRoles: (roles?: RolesInput) => string[];
172
- export declare const createAuth: (options: CreateAuthOptions) => import("better-auth").Auth<{
174
+ /**
175
+ * The plugins only some apps use, which `loadAuthPlugins` imports when the options turn them on: the SSO plugin of
176
+ * `sso.saml` and the OAuth provider of `mcp`.
177
+ */
178
+ export type AuthPlugins = {
179
+ samlPlugin?: typeof samlPlugin;
180
+ mcpAuthPlugins?: typeof mcpAuthPlugins;
181
+ };
182
+ /** The optional plugins `options` turns on, imported: an app without SAML or MCP loads neither. */
183
+ export declare const loadAuthPlugins: (options: Pick<CreateAuthOptions, "sso" | "mcp">) => Promise<AuthPlugins>;
184
+ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlugins) => import("better-auth").Auth<{
173
185
  user: {
174
186
  modelName: string;
175
187
  fields: {
@@ -473,9 +485,7 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
473
485
  expiresAt: Date;
474
486
  token: string;
475
487
  ipAddress?: string | null | undefined;
476
- userAgent?
477
- /** Sign-in attempts allowed per minute and client, default 5; also the sign-up requests allowed. */
478
- /** Sign-in attempts allowed per minute and client, default 5; also the sign-up requests allowed. */ : string | null | undefined;
488
+ userAgent?: string | null | undefined;
479
489
  };
480
490
  };
481
491
  }>>[];
@@ -8752,9 +8762,6 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
8752
8762
  };
8753
8763
  };
8754
8764
  advanced: {
8755
- database?: {
8756
- generateId: "uuid";
8757
- } | undefined;
8758
8765
  useSecureCookies: boolean;
8759
8766
  cookiePrefix: string;
8760
8767
  defaultCookieAttributes: {
@@ -8764,6 +8771,10 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
8764
8771
  backgroundTasks: {
8765
8772
  handler: () => void;
8766
8773
  };
8774
+ database: {
8775
+ generateId?: "uuid" | undefined;
8776
+ validateSchema: false;
8777
+ };
8767
8778
  };
8768
8779
  socialProviders?: import("better-auth").SocialProviders | undefined;
8769
8780
  appName: string;
@@ -8839,6 +8850,13 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
8839
8850
  signUpRole: string | undefined;
8840
8851
  /** The app keeps each user's metadata, in the column `users.metadata` names. */
8841
8852
  userMetadata: boolean;
8853
+ /** The user table's name and columns, as `users` names them, for the store's migrations. */
8854
+ userTable: {
8855
+ modelName: string;
8856
+ column: (name: UserColumn) => string;
8857
+ fieldNames: Record<string, string>;
8858
+ metadata: string | undefined;
8859
+ };
8842
8860
  socialProviders: string[];
8843
8861
  /** The app's name it signs in and mails as: `PROTOBASE_APP_NAME`, else `appName`, else `Protobase`. */
8844
8862
  appName: string;
@@ -8860,4 +8878,6 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
8860
8878
  } | undefined;
8861
8879
  };
8862
8880
  export type AdminAuth = ReturnType<typeof createAuth>;
8881
+ /** `createAuth` with the optional plugins its options turn on loaded first (see `loadAuthPlugins`). */
8882
+ export declare const buildAuth: (options: CreateAuthOptions) => Promise<AdminAuth>;
8863
8883
  //#endregion
@@ -20,27 +20,27 @@ import { signUpPaths, signUpPlugin } from "./sign-up/sign-up-plugin.js";
20
20
  import { leakedPasswordsPlugin } from "./leaked-passwords.js";
21
21
  import { userDeletion } from "./user-deletion.js";
22
22
  import { revokeMcpGrants } from "./mcp/revoke-grants.js";
23
- import { coreNames, pluginNames } from "./snake-case-names.js";
23
+ import { mcpUnusedPaths, resolveMcp } from "./mcp/mcp-plugins.js";
24
24
  import { lastOrganizationField, sessionOrganizationHooks } from "./organizations/session-organization.js";
25
- import { tokenClaims } from "./token-claims.js";
26
- import { mcpAuthPlugins, mcpUnusedPaths, resolveMcp } from "./mcp/mcp-plugins.js";
27
25
  import { organizationPlugin } from "./organizations/organization-plugin.js";
28
26
  import { protobaseOrganizationPlugin } from "./organizations/protobase-plugin.js";
29
27
  import { resolveOrganizations } from "./organizations/options.js";
30
28
  import { passkeyHosts, readPasskeyDomain, resolvePasskeyDomain } from "./passkey-domain.js";
29
+ import { coreNames, pluginNames } from "./snake-case-names.js";
31
30
  import { passkeyPlugin } from "./passkey-plugin.js";
32
31
  import { passwordResetOptions } from "./password-reset.js";
33
32
  import { rolesPlugin } from "./roles/roles-plugin.js";
34
33
  import { platformSignInFor, platformSignInProvider, readPlatformSignIn, resolvePlatformSignIn } from "./platform-sign-in.js";
35
34
  import { appSignInPolicy } from "./app-sign-in-policy.js";
36
35
  import { assertNoEndpointKeyClashes } from "./endpoint-key-clashes.js";
37
- import { emailInDomains, resolveSamlProviders, samlDisabledPaths, samlGuardPlugin, samlPlugin } from "./saml-sign-in.js";
36
+ import { emailInDomains, resolveSamlProviders, samlDisabledPaths, samlGuardPlugin } from "./saml-sign-in.js";
38
37
  import { noAccountMailPlugin } from "./no-account-mail.js";
39
38
  import { emailCodeOptions, twoFactorCodeOptions, unusedEmailCodePaths } from "./sign-in-mail.js";
40
39
  import { confirmedOnCreate, confirmedOnUpdate, emailConfirmedField } from "./email-confirmed.js";
41
40
  import { rehashPasswordsPlugin, verifyAcceptedHash } from "./password-hashes.js";
42
41
  import { staffSignInPlugin } from "./staff-plugin.js";
43
42
  import { strongSignInsPlugin } from "./strong-sign-ins.js";
43
+ import { tokenClaims } from "./token-claims.js";
44
44
  import { twoFactorAfterPasswordOrCode } from "./two-factor-challenge.js";
45
45
  import { metadataField, userFieldsNamed, userModel, userTable, withUserColumns } from "./user-table.js";
46
46
  import { usersPlugin } from "./users/users-plugin.js";
@@ -70,6 +70,15 @@ const tokenLifetime = "15m";
70
70
  /** The configured roles with `admin` first; `admin` is added when missing. */
71
71
  const normalizeRoles = (roles) => roleDefinitions(roles).names;
72
72
  const adminImpersonationPaths = ["/admin/impersonate-user", "/admin/stop-impersonating"];
73
+ /** The optional plugins `options` turns on, imported: an app without SAML or MCP loads neither. */
74
+ const loadAuthPlugins = async (options) => ({
75
+ ...(options.sso?.saml.length ?? 0) > 0 && { samlPlugin: (await import("./saml-plugin.js")).samlPlugin },
76
+ ...options.mcp && { mcpAuthPlugins: (await import("./mcp/mcp-auth-plugins.js")).mcpAuthPlugins }
77
+ });
78
+ const loaded = (plugin, option) => {
79
+ if (!plugin) throw new Error(`${option} needs its plugin loaded: build auth with buildAuth, which loads it`);
80
+ return plugin;
81
+ };
73
82
  const newUserId = (generate) => generate === "uuid" ? crypto.randomUUID() : generate();
74
83
  const noContext = () => Promise.reject(/* @__PURE__ */ new Error("The auth context is read only once createAuth has made the instance"));
75
84
  const organizationPaths = ["/organization/set-active", "/organization/accept-invitation"];
@@ -77,7 +86,7 @@ const organizationPaths = ["/organization/set-active", "/organization/accept-inv
77
86
  * The options `createAuth` gives Better Auth, with the roles, default role, mailer, operator provider and platform
78
87
  * sign-in provider already resolved.
79
88
  */
80
- const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, definitions, defaultRole, appName = defaultAppName, mailer, signUpRole, operator, platformSignIn, saml = [], organizations, mcp, context = noContext, signInPolicy = defaultSignInPolicy, mobile, deletion }) => {
89
+ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, definitions, defaultRole, appName = defaultAppName, mailer, signUpRole, operator, platformSignIn, saml = [], organizations, mcp, context = noContext, signInPolicy = defaultSignInPolicy, mobile, deletion, ...plugins }) => {
81
90
  const secure = options.baseURL.startsWith("https://");
82
91
  const signIn = platformSignInFor(platformSignIn, Object.keys(options.socialProviders ?? {}));
83
92
  const hosts = passkeyHosts([options.baseURL, ...origins]);
@@ -185,7 +194,7 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
185
194
  defaultPolicy: signInPolicy
186
195
  })] : [],
187
196
  ...signIn ? [genericOAuth({ config: [platformSignInProvider(signIn)] })] : [],
188
- ...saml.length > 0 ? [samlPlugin(saml, options.baseURL), samlGuardPlugin(samlIds)] : [],
197
+ ...saml.length > 0 ? [loaded(plugins.samlPlugin, "sso.saml")(saml, options.baseURL), samlGuardPlugin(samlIds)] : [],
189
198
  signInPolicyPlugin(policy),
190
199
  setPasswordPlugin(),
191
200
  ...options.leakedPasswords ? [leakedPasswordsPlugin()] : [],
@@ -220,7 +229,7 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
220
229
  ...organizations && { organizations }
221
230
  }),
222
231
  ...passwordHashes.length > 0 ? [rehashPasswordsPlugin(passwordHashes)] : [],
223
- ...mcp ? mcpAuthPlugins({
232
+ ...mcp ? loaded(plugins.mcpAuthPlugins, "mcp")({
224
233
  mcp,
225
234
  organizations: Boolean(organizations),
226
235
  mail: Boolean(mailer),
@@ -306,7 +315,10 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
306
315
  secure
307
316
  },
308
317
  backgroundTasks: { handler: () => {} },
309
- ...options.generateUserId === "uuid" && { database: { generateId: "uuid" } }
318
+ database: {
319
+ validateSchema: false,
320
+ ...options.generateUserId === "uuid" && { generateId: "uuid" }
321
+ }
310
322
  }
311
323
  };
312
324
  };
@@ -315,7 +327,7 @@ const checkSignUpRole = (role, roles) => {
315
327
  if (!roles.includes(role)) throw new Error(`signUp.role "${role}" is not one of the roles: ${roles.join(", ")}`);
316
328
  return role;
317
329
  };
318
- const createAuth = (options) => {
330
+ const createAuth = (options, plugins = {}) => {
319
331
  if (options.signUp && options.organizations) throw new Error("signUp is not available with organizations: their people join by invitation");
320
332
  const definitions = roleDefinitions(options.roles, { organizations: options.organizations !== void 0 });
321
333
  const roles = definitions.names;
@@ -341,6 +353,7 @@ const createAuth = (options) => {
341
353
  const mobile = mobileRequests();
342
354
  const deletion = userDeletion();
343
355
  const authOptions = betterAuthOptions(options, {
356
+ ...plugins,
344
357
  mobile,
345
358
  deletion,
346
359
  origins,
@@ -402,6 +415,8 @@ const createAuth = (options) => {
402
415
  signUpRole: mailer ? signUpRole : void 0,
403
416
  /** The app keeps each user's metadata, in the column `users.metadata` names. */
404
417
  userMetadata: Boolean(options.users?.metadata),
418
+ /** The user table's name and columns, as `users` names them, for the store's migrations. */
419
+ userTable: userTable(options.users),
405
420
  socialProviders,
406
421
  /** The app's name it signs in and mails as: `PROTOBASE_APP_NAME`, else `appName`, else `Protobase`. */
407
422
  appName: appName ?? "Protobase",
@@ -423,5 +438,7 @@ const createAuth = (options) => {
423
438
  }
424
439
  });
425
440
  };
441
+ /** `createAuth` with the optional plugins its options turn on loaded first (see `loadAuthPlugins`). */
442
+ const buildAuth = async (options) => createAuth(options, await loadAuthPlugins(options));
426
443
  //#endregion
427
- export { authBasePath, betterAuthOptions, createAuth, normalizeRoles };
444
+ export { authBasePath, betterAuthOptions, buildAuth, createAuth, loadAuthPlugins, normalizeRoles };