@protobase/server 0.48.0 → 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 (69) 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/better-auth/auth-settings.d.ts +8754 -0
  5. package/dist/better-auth/auth-settings.js +43 -0
  6. package/dist/better-auth/authenticate-settings.d.ts +15 -0
  7. package/dist/better-auth/authenticate-settings.js +12 -0
  8. package/dist/better-auth/create-auth.d.ts +23 -11
  9. package/dist/better-auth/create-auth.js +21 -9
  10. package/dist/better-auth/mcp/mcp-auth-plugins.d.ts +2719 -0
  11. package/dist/better-auth/mcp/mcp-auth-plugins.js +68 -0
  12. package/dist/better-auth/mcp/mcp-plugins.d.ts +7 -2
  13. package/dist/better-auth/mcp/mcp-plugins.js +3 -68
  14. package/dist/better-auth/mcp/mcp-token-claims.js +1 -1
  15. package/dist/better-auth/organizations/store.d.ts +1 -0
  16. package/dist/better-auth/saml-plugin.d.ts +993 -0
  17. package/dist/better-auth/saml-plugin.js +36 -0
  18. package/dist/better-auth/saml-sign-in.d.ts +27 -1
  19. package/dist/better-auth/saml-sign-in.js +1 -33
  20. package/dist/better-auth/user-table.js +1 -1
  21. package/dist/better-auth/users.d.ts +1 -1
  22. package/dist/create-admin.d.ts +5 -3
  23. package/dist/create-admin.js +3 -1
  24. package/dist/encryption/keyring.js +1 -1
  25. package/dist/files/options.d.ts +5 -8
  26. package/dist/files/provider-settings.d.ts +16 -0
  27. package/dist/files/provider-settings.js +17 -0
  28. package/dist/files/runtime.js +4 -4
  29. package/dist/forms/runtime.js +3 -3
  30. package/dist/index.d.ts +16 -15
  31. package/dist/index.js +8 -10
  32. package/dist/internal.d.ts +13 -0
  33. package/dist/internal.js +13 -0
  34. package/dist/jobs/declared-job.d.ts +24 -0
  35. package/dist/jobs/declared-job.js +26 -0
  36. package/dist/jobs/job-types.d.ts +1 -1
  37. package/dist/mcp/mcp-authenticator.js +3 -3
  38. package/dist/notifications/device-store-of.d.ts +1 -1
  39. package/dist/notifications/device-store-of.js +1 -1
  40. package/dist/notifications/device-store.d.ts +1 -1
  41. package/dist/notifications/device-store.js +1 -1
  42. package/dist/notifications/history-store-of.d.ts +1 -1
  43. package/dist/notifications/history-store-of.js +1 -1
  44. package/dist/notifications/history-store.d.ts +1 -1
  45. package/dist/notifications/history-store.js +1 -1
  46. package/dist/notifications/options.d.ts +3 -1
  47. package/dist/notifications/options.js +1 -1
  48. package/dist/notifications/schema.d.ts +2 -2
  49. package/dist/notifications/schema.js +7 -7
  50. package/dist/notifications/send-notification.js +1 -1
  51. package/dist/notifications/sender.d.ts +1 -1
  52. package/dist/notifications/sender.js +2 -2
  53. package/dist/notifications/senders-of.d.ts +1 -1
  54. package/dist/notifications/senders-of.js +1 -1
  55. package/dist/package.js +1 -1
  56. package/dist/webhooks/subscription.d.ts +1 -0
  57. package/dist/webhooks/table/options.d.ts +1 -1
  58. package/dist/webhooks/table/schema.d.ts +2 -2
  59. package/dist/webhooks/table/schema.js +2 -2
  60. package/dist/webhooks/table/webhook-table.js +2 -2
  61. package/dist/webhooks/table/webhooks-module.d.ts +108 -0
  62. package/dist/webhooks/table/webhooks-module.js +11 -0
  63. package/package.json +6 -5
  64. package/dist/notifications/plugin.d.ts +0 -13
  65. package/dist/notifications/plugin.js +0 -16
  66. package/dist/project-config.d.ts +0 -54
  67. package/dist/project-config.js +0 -182
  68. package/dist/webhooks/table/plugin.d.ts +0 -10
  69. 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 };
@@ -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,19 +1,21 @@
1
1
  import { UserColumn, UserTableOptions } from "./user-table.js";
2
2
  import { Mailer } from "../mail/smtp-mailer.js";
3
3
  import { SignInPolicy } from "./sign-in-policy.js";
4
- import { OperatorProvider } from "./operator-provider.js";
5
- import { PlatformSignIn } from "./platform-sign-in.js";
6
- import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
7
- import { OrganizationRole } from "./organizations/store.js";
8
- import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
9
4
  import { StaffSignIn } from "./staff-log.js";
10
- import "../index.js";
5
+ import { RoleDefinitions, RolesInput } from "./organizations/role-definitions.js";
11
6
  import { ConnectedApp } from "./mcp/connected-apps.js";
12
7
  import { ReplacingContext } from "./end-replaced-session.js";
13
8
  import { UserDeletionListener } from "./user-deletion.js";
14
- import "./auth-base-path.js";
9
+ import { OrganizationRole } from "./organizations/store.js";
10
+ import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
15
11
  import { McpAuthOptions } from "./mcp/mcp-plugins.js";
12
+ import { OperatorProvider } from "./operator-provider.js";
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";
16
17
  import { SsoOptions } from "./saml-sign-in.js";
18
+ import { samlPlugin } from "./saml-plugin.js";
17
19
  import { signUpPaths } from "./sign-up/sign-up-plugin.js";
18
20
  import { PasswordHash } from "./password-hashes.js";
19
21
  import { BetterAuthOptions } from "better-auth";
@@ -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
  }>>[];
@@ -8868,4 +8878,6 @@ export declare const createAuth: (options: CreateAuthOptions) => import("better-
8868
8878
  } | undefined;
8869
8879
  };
8870
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>;
8871
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),
@@ -318,7 +327,7 @@ const checkSignUpRole = (role, roles) => {
318
327
  if (!roles.includes(role)) throw new Error(`signUp.role "${role}" is not one of the roles: ${roles.join(", ")}`);
319
328
  return role;
320
329
  };
321
- const createAuth = (options) => {
330
+ const createAuth = (options, plugins = {}) => {
322
331
  if (options.signUp && options.organizations) throw new Error("signUp is not available with organizations: their people join by invitation");
323
332
  const definitions = roleDefinitions(options.roles, { organizations: options.organizations !== void 0 });
324
333
  const roles = definitions.names;
@@ -344,6 +353,7 @@ const createAuth = (options) => {
344
353
  const mobile = mobileRequests();
345
354
  const deletion = userDeletion();
346
355
  const authOptions = betterAuthOptions(options, {
356
+ ...plugins,
347
357
  mobile,
348
358
  deletion,
349
359
  origins,
@@ -428,5 +438,7 @@ const createAuth = (options) => {
428
438
  }
429
439
  });
430
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));
431
443
  //#endregion
432
- export { authBasePath, betterAuthOptions, createAuth, normalizeRoles };
444
+ export { authBasePath, betterAuthOptions, buildAuth, createAuth, loadAuthPlugins, normalizeRoles };