@protobase/server 0.48.0 → 0.49.1

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 (74) 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 +8773 -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 +51 -11
  9. package/dist/better-auth/create-auth.js +33 -11
  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/secret-versions.d.ts +7 -0
  21. package/dist/better-auth/secret-versions.js +21 -0
  22. package/dist/better-auth/signing-keys.js +86 -0
  23. package/dist/better-auth/tokens.js +1 -0
  24. package/dist/better-auth/user-table.js +1 -1
  25. package/dist/better-auth/users.d.ts +1 -1
  26. package/dist/create-admin.d.ts +5 -3
  27. package/dist/create-admin.js +3 -1
  28. package/dist/encryption/keyring.js +1 -1
  29. package/dist/files/options.d.ts +5 -8
  30. package/dist/files/provider-settings.d.ts +16 -0
  31. package/dist/files/provider-settings.js +17 -0
  32. package/dist/files/runtime.js +4 -4
  33. package/dist/forms/runtime.js +3 -3
  34. package/dist/gotrue/sessions-plugin.js +3 -9
  35. package/dist/index.d.ts +16 -15
  36. package/dist/index.js +8 -10
  37. package/dist/internal.d.ts +13 -0
  38. package/dist/internal.js +13 -0
  39. package/dist/jobs/declared-job.d.ts +24 -0
  40. package/dist/jobs/declared-job.js +26 -0
  41. package/dist/jobs/job-types.d.ts +1 -1
  42. package/dist/mcp/mcp-authenticator.js +3 -3
  43. package/dist/notifications/device-store-of.d.ts +1 -1
  44. package/dist/notifications/device-store-of.js +1 -1
  45. package/dist/notifications/device-store.d.ts +1 -1
  46. package/dist/notifications/device-store.js +1 -1
  47. package/dist/notifications/history-store-of.d.ts +1 -1
  48. package/dist/notifications/history-store-of.js +1 -1
  49. package/dist/notifications/history-store.d.ts +1 -1
  50. package/dist/notifications/history-store.js +1 -1
  51. package/dist/notifications/options.d.ts +3 -1
  52. package/dist/notifications/options.js +1 -1
  53. package/dist/notifications/schema.d.ts +2 -2
  54. package/dist/notifications/schema.js +7 -7
  55. package/dist/notifications/send-notification.js +1 -1
  56. package/dist/notifications/sender.d.ts +1 -1
  57. package/dist/notifications/sender.js +2 -2
  58. package/dist/notifications/senders-of.d.ts +1 -1
  59. package/dist/notifications/senders-of.js +1 -1
  60. package/dist/package.js +1 -1
  61. package/dist/webhooks/subscription.d.ts +1 -0
  62. package/dist/webhooks/table/options.d.ts +1 -1
  63. package/dist/webhooks/table/schema.d.ts +2 -2
  64. package/dist/webhooks/table/schema.js +2 -2
  65. package/dist/webhooks/table/webhook-table.js +2 -2
  66. package/dist/webhooks/table/webhooks-module.d.ts +108 -0
  67. package/dist/webhooks/table/webhooks-module.js +11 -0
  68. package/package.json +6 -5
  69. package/dist/notifications/plugin.d.ts +0 -13
  70. package/dist/notifications/plugin.js +0 -16
  71. package/dist/project-config.d.ts +0 -54
  72. package/dist/project-config.js +0 -182
  73. package/dist/webhooks/table/plugin.d.ts +0 -10
  74. package/dist/webhooks/table/plugin.js +0 -18
@@ -0,0 +1,36 @@
1
+ import { samlEntityId } from "./saml-sign-in.js";
2
+ import { sso } from "@better-auth/sso";
3
+ //#region src/better-auth/saml-plugin.ts
4
+ /** The provider as one of the SSO plugin's configured providers (`defaultSSO`). */
5
+ const defaultSsoEntry = (provider, baseURL) => {
6
+ const { idp, attributes = {} } = provider;
7
+ const mapping = Object.fromEntries(Object.entries(attributes).filter(([, name]) => name !== void 0));
8
+ return {
9
+ providerId: provider.id,
10
+ domain: provider.domains.join(","),
11
+ samlConfig: {
12
+ issuer: samlEntityId(baseURL, provider.id),
13
+ entryPoint: "ssoUrl" in idp ? idp.ssoUrl : "",
14
+ idpMetadata: "metadata" in idp ? { metadata: idp.metadata } : {
15
+ entityID: idp.entityId,
16
+ cert: idp.certificate
17
+ },
18
+ ...Object.keys(mapping).length > 0 && { mapping }
19
+ }
20
+ };
21
+ };
22
+ /**
23
+ * Better Auth's SSO plugin with the configured providers. Their domains are trusted, so an address there links to the
24
+ * account that has it; organizations are not assigned by provider, and nobody registers providers.
25
+ */
26
+ const samlPlugin = (providers, baseURL) => {
27
+ const { schema: _schema, ...plugin } = sso({
28
+ defaultSSO: providers.map((provider) => defaultSsoEntry(provider, baseURL)),
29
+ domainVerification: { enabled: true },
30
+ organizationProvisioning: { disabled: true },
31
+ providersLimit: 0
32
+ });
33
+ return plugin;
34
+ };
35
+ //#endregion
36
+ export { defaultSsoEntry, samlPlugin };
@@ -1,4 +1,3 @@
1
- import "@better-auth/sso";
2
1
  //#region src/better-auth/saml-sign-in.d.ts
3
2
  /**
4
3
  * A SAML 2.0 identity provider people of the app sign in with, for example the company's Okta, Entra ID or Google
@@ -34,4 +33,31 @@ export type SamlProvider = {
34
33
  export type SsoOptions = {
35
34
  saml: SamlProvider[];
36
35
  };
36
+ /**
37
+ * The providers with their defaults filled in: the name `SSO`, and the domains trimmed and lowercased. A malformed id,
38
+ * an id used twice or by another sign-in provider (`takenIds`), no domains or a domain that is not a host name, and IdP
39
+ * settings that are missing or not a URL are errors.
40
+ */
41
+ export declare const resolveSamlProviders: (saml: SamlProvider[], takenIds: string[]) => {
42
+ name: string;
43
+ domains: string[];
44
+ /** The id: the button's `?sign-in=` link, the provider's paths and the namespace of its accounts. Lowercase letters, digits or "-". */
45
+ id: string;
46
+ /** The provider's metadata XML, or its entity ID, sign-in URL and signing certificate(s) (PEM; several while one rotates). */
47
+ idp: {
48
+ metadata: string;
49
+ } | {
50
+ entityId: string;
51
+ ssoUrl: string;
52
+ certificate: string | string[];
53
+ };
54
+ /** The assertion's attribute names, when they are not `email`, `givenName`, `surname` and `displayName`. */
55
+ attributes?: {
56
+ email?: string;
57
+ name?: string;
58
+ firstName?: string;
59
+ lastName?: string;
60
+ };
61
+ }[];
62
+ export type ResolvedSamlProvider = ReturnType<typeof resolveSamlProviders>[number];
37
63
  //#endregion
@@ -1,7 +1,6 @@
1
1
  import { authBasePath } from "./auth-base-path.js";
2
2
  import { providerIdPattern } from "./platform-sign-in.js";
3
3
  import { APIError, createAuthMiddleware } from "better-auth/api";
4
- import { sso } from "@better-auth/sso";
5
4
  //#region src/better-auth/saml-sign-in.ts
6
5
  const domainPattern = /^[a-z0-9-]+(\.[a-z0-9-]+)*$/;
7
6
  const checkIdp = (id, idp) => {
@@ -37,37 +36,6 @@ const resolveSamlProviders = (saml, takenIds) => {
37
36
  };
38
37
  /** The app's SP entity ID for a provider: its metadata URL on `baseURL`, the same on every origin. */
39
38
  const samlEntityId = (baseURL, id) => `${baseURL.replace(/\/$/, "")}${authBasePath}/sso/saml2/sp/metadata?providerId=${encodeURIComponent(id)}`;
40
- /** The provider as one of the SSO plugin's configured providers (`defaultSSO`). */
41
- const defaultSsoEntry = (provider, baseURL) => {
42
- const { idp, attributes = {} } = provider;
43
- const mapping = Object.fromEntries(Object.entries(attributes).filter(([, name]) => name !== void 0));
44
- return {
45
- providerId: provider.id,
46
- domain: provider.domains.join(","),
47
- samlConfig: {
48
- issuer: samlEntityId(baseURL, provider.id),
49
- entryPoint: "ssoUrl" in idp ? idp.ssoUrl : "",
50
- idpMetadata: "metadata" in idp ? { metadata: idp.metadata } : {
51
- entityID: idp.entityId,
52
- cert: idp.certificate
53
- },
54
- ...Object.keys(mapping).length > 0 && { mapping }
55
- }
56
- };
57
- };
58
- /**
59
- * Better Auth's SSO plugin with the configured providers. Their domains are trusted, so an address there links to the
60
- * account that has it; organizations are not assigned by provider, and nobody registers providers.
61
- */
62
- const samlPlugin = (providers, baseURL) => {
63
- const { schema: _schema, ...plugin } = sso({
64
- defaultSSO: providers.map((provider) => defaultSsoEntry(provider, baseURL)),
65
- domainVerification: { enabled: true },
66
- organizationProvisioning: { disabled: true },
67
- providersLimit: 0
68
- });
69
- return plugin;
70
- };
71
39
  /** The SSO plugin's endpoints for providers kept in its table, and its OIDC callback, which Protobase does not serve. */
72
40
  const samlDisabledPaths = [
73
41
  "/sso/register",
@@ -130,4 +98,4 @@ const emailInDomains = (email, domains) => {
130
98
  return domains.some((allowed) => domain === allowed || domain.endsWith(`.${allowed}`));
131
99
  };
132
100
  //#endregion
133
- export { defaultSsoEntry, emailInDomains, isSamlPath, resolveSamlProviders, samlDisabledPaths, samlEntityId, samlGuardPlugin, samlPlugin, samlRefusal };
101
+ export { emailInDomains, isSamlPath, resolveSamlProviders, samlDisabledPaths, samlEntityId, samlGuardPlugin, samlRefusal };
@@ -0,0 +1,7 @@
1
+ //#region src/better-auth/secret-versions.d.ts
2
+ /** Better Auth's versioned secrets: the current one first, each with the version its ciphertexts name. */
3
+ export type VersionedSecret = {
4
+ version: number;
5
+ value: string;
6
+ };
7
+ //#endregion
@@ -0,0 +1,21 @@
1
+ import { createHash } from "node:crypto";
2
+ //#region src/better-auth/secret-versions.ts
3
+ const versionOf = (secret) => Number.parseInt(createHash("sha256").update(`protobase-secret-version:${secret}`).digest("hex").slice(0, 7), 16);
4
+ /**
5
+ * Better Auth's options for the app's `secret` and its `previousSecrets`: `secrets`, which encrypt with the current
6
+ * one and decrypt with any of them, and `secret`, which Better Auth keeps for what was encrypted before secrets had
7
+ * versions. That is the oldest secret listed: the one in use when the app last ran without versions, unless it was
8
+ * changed since without being listed.
9
+ */
10
+ const versionedSecrets = (secret, previousSecrets = []) => {
11
+ const all = [.../* @__PURE__ */ new Set([secret, ...previousSecrets])];
12
+ return {
13
+ secrets: all.map((value) => ({
14
+ version: versionOf(value),
15
+ value
16
+ })),
17
+ legacySecret: all.at(-1)
18
+ };
19
+ };
20
+ //#endregion
21
+ export { versionedSecrets };
@@ -0,0 +1,86 @@
1
+ import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api";
2
+ import { createJwk } from "better-auth/plugins";
3
+ const daySeconds = 86400;
4
+ /** The JWT plugin's rotation for `options`: `rotationInterval` and `gracePeriod`, in seconds. */
5
+ const signingKeyRotation = ({ signingKeyDays = 30, signingKeyGraceDays = 7 } = {}) => {
6
+ if (!(signingKeyDays > 0)) throw new Error("signingKeyDays must be more than 0");
7
+ if (!(signingKeyGraceDays >= 1)) throw new Error("signingKeyGraceDays must be at least 1: tokens of `protobase token` last up to a day");
8
+ return {
9
+ rotationInterval: Math.round(signingKeyDays * daySeconds),
10
+ gracePeriod: Math.round(signingKeyGraceDays * daySeconds)
11
+ };
12
+ };
13
+ const isPrimary = (key) => key.alg === null || key.alg === void 0 || key.alg === "EdDSA";
14
+ const marginMs = 6e4;
15
+ const signingPaths = /* @__PURE__ */ new Set(["/token", "/oauth2/token"]);
16
+ /**
17
+ * Keeps a live EdDSA key for the app's tokens. The JWT plugin signs with the newest live key of the primary algorithm,
18
+ * else with the newest live key of any: once the EdDSA key expired while the ES256 one of the GoTrue-compatible
19
+ * tokens still lived, it would sign the app's tokens ES256 until that one expired too. So before every signing, a new
20
+ * EdDSA key is made when none lives; a key made before rotation was on (without an expiry) gets the one it would have
21
+ * had, its creation plus the rotation interval, so it rotates too. A key past its grace period, which no longer
22
+ * verifies, is deleted, so the store keeps a few keys (Better Auth reads at most 100). The key set is read once per
23
+ * key's lifetime: until the newest EdDSA key expires, signing reads nothing more.
24
+ */
25
+ const signingKeys = (jwt) => {
26
+ const intervalMs = jwt.jwks.rotationInterval * 1e3;
27
+ const graceMs = jwt.jwks.gracePeriod * 1e3;
28
+ let liveUntil = 0;
29
+ let pending;
30
+ const check = async (ctx) => {
31
+ const now = Date.now();
32
+ const { adapter } = ctx.context;
33
+ const dated = (await adapter.findMany({ model: "jwks" })).map((key) => ({
34
+ ...key,
35
+ undated: !key.expiresAt,
36
+ expiresAt: key.expiresAt ?? new Date(key.createdAt.getTime() + intervalMs)
37
+ }));
38
+ const retired = dated.filter((key) => key.expiresAt.getTime() + graceMs <= now);
39
+ if (retired.length > 0) await adapter.deleteMany({
40
+ model: "jwks",
41
+ where: [{
42
+ field: "id",
43
+ operator: "in",
44
+ value: retired.map((key) => key.id)
45
+ }]
46
+ });
47
+ const keys = dated.filter((key) => !retired.includes(key));
48
+ await Promise.all(keys.filter((key) => key.undated).map((key) => adapter.update({
49
+ model: "jwks",
50
+ where: [{
51
+ field: "id",
52
+ value: key.id
53
+ }],
54
+ update: { expiresAt: key.expiresAt }
55
+ })));
56
+ liveUntil = (keys.filter((key) => isPrimary(key) && key.expiresAt.getTime() - marginMs > now).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0] ?? await createJwk(ctx, jwt)).expiresAt.getTime() - marginMs;
57
+ };
58
+ /** Makes sure a live EdDSA key signs the next token; concurrent callers share one check. */
59
+ const ensure = async (ctx) => {
60
+ if (Date.now() < liveUntil) return;
61
+ pending ??= check(ctx).finally(() => {
62
+ pending = void 0;
63
+ });
64
+ await pending;
65
+ };
66
+ return {
67
+ plugin: {
68
+ id: "protobase-signing-keys",
69
+ endpoints: {
70
+ /** Makes sure a live EdDSA key signs the next token, for signing outside the plugin's paths (`issueToken`). */
71
+ ensureSigningKey: createAuthEndpoint.serverOnly({ method: "POST" }, async (ctx) => {
72
+ await ensure(ctx);
73
+ return ctx.json({ ok: true });
74
+ }) },
75
+ hooks: { before: [{
76
+ matcher: (ctx) => signingPaths.has(ctx.path ?? ""),
77
+ handler: createAuthMiddleware(async (ctx) => {
78
+ await ensure(ctx);
79
+ })
80
+ }] }
81
+ },
82
+ ensure
83
+ };
84
+ };
85
+ //#endregion
86
+ export { signingKeyRotation, signingKeys };
@@ -24,6 +24,7 @@ const issueToken = async (auth, options) => {
24
24
  if (user.banned) throw new Error(`${options.email} is banned`);
25
25
  const issuedAt = Math.floor(Date.now() / 1e3);
26
26
  const { role } = narrowClaims({ role: parseRoles(user.role).join(",") }, [user.lastRole], Boolean(auth.organizations));
27
+ await auth.api.ensureSigningKey();
27
28
  const { token } = await auth.api.signJWT({ body: { payload: {
28
29
  iat: issuedAt,
29
30
  exp: issuedAt + ttl,
@@ -16,7 +16,7 @@ const userFields = {
16
16
  last_role: "lastRole",
17
17
  last_organization_id: "lastOrganizationId"
18
18
  };
19
- /** The user table's names, from `createAuth`'s `users` option; unknown columns are an error. */
19
+ /** The user table's names, from `auth.users` option; unknown columns are an error. */
20
20
  const userTable = ({ table = "user", columns = {}, metadata } = {}) => {
21
21
  const unknown = Object.keys(columns).find((name) => !(name in userFields));
22
22
  if (unknown !== void 0) throw new Error(`users.columns names "${unknown}", which is not a column of the user table: ${Object.keys(userFields).join(", ")}`);
@@ -10,7 +10,7 @@ export type LinkedAccount = {
10
10
  };
11
11
  /**
12
12
  * Without `password` the user signs in by emailed code, passkey or a sign-in provider only. `metadata` lands in the
13
- * user metadata column, which `createAuth`'s `users.metadata` names; it needs one.
13
+ * user metadata column, which `auth.users.metadata` names; it needs one.
14
14
  */
15
15
  export type NewUser = {
16
16
  email: string;
@@ -35,6 +35,8 @@ export type CreateAdminInput = {
35
35
  auth?: AdminAuth;
36
36
  /** API functions of the app's own, each served at `<systemPath>/functions/<name>` (see `defineFunction`). */
37
37
  functions?: Record<string, FunctionSource>;
38
+ /** The app's secret (`secret`): it signs public forms' bot checks, and upload tickets unless `files.secret` names another. */
39
+ secret?: string;
38
40
  /** Where file fields keep their bytes (see `FilesOptions`). */
39
41
  files?: FilesOptions;
40
42
  /** Where the changes that resources' events are raised from are captured (see `EventsOptions`). */
@@ -45,9 +47,9 @@ export type CreateAdminInput = {
45
47
  jobs?: JobDefinition[];
46
48
  /** Where the resources' events are delivered (`subscription(...)` exports of the config module). */
47
49
  subscriptions?: SubscriptionDefinition[];
48
- /** Webhook subscriptions made in the admin app, from `extends: [webhooks()]` (see `WebhooksOptions`). */
50
+ /** Webhook subscriptions made in the admin app, from `webhooks: {}` (see `WebhooksOptions`). */
49
51
  webhooks?: WebhooksOptions;
50
- /** Each user's devices and the endpoints that register them, from `extends: [notifications()]` (see `NotificationsOptions`). */
52
+ /** Each user's devices and the endpoints that register them, from `notifications: {}` (see `NotificationsOptions`). */
51
53
  notifications?: NotificationsOptions;
52
54
  /**
53
55
  * The app's iOS and Android build (see `MobileConfig`): the API answers its Capacitor origins through CORS, and sign-in
@@ -88,5 +90,5 @@ export type CreateAdminInput = {
88
90
  upgradeWebSocket?: UpgradeWebSocket;
89
91
  };
90
92
  /** The admin REST API as a Hono app. It uses only Web APIs, so it runs on Node, Workers and anywhere else Hono does. */
91
- export declare const createAdmin: ({ resources: appResources, views: appViews, pages, userMenu, bottomBars, db, authenticate, auth, functions, files: filesOptions, events, history: historyOptions, jobs, subscriptions, webhooks: webhooksOptions, notifications, mobile, app: identity, icons, bundlePlugins, fieldTypes, options, formsDifficulty, commentUsers: givenCommentUsers, verifyToken, upgradeWebSocket }: CreateAdminInput) => Admin;
93
+ export declare const createAdmin: ({ resources: appResources, views: appViews, pages, userMenu, bottomBars, db, authenticate, auth, functions, secret, files: filesOptions, events, history: historyOptions, jobs, subscriptions, webhooks: webhooksOptions, notifications, mobile, app: identity, icons, bundlePlugins, fieldTypes, options, formsDifficulty, commentUsers: givenCommentUsers, verifyToken, upgradeWebSocket }: CreateAdminInput) => Admin;
92
94
  //#endregion
@@ -103,7 +103,7 @@ const declaredRoles = (auth, roles) => {
103
103
  return names.length > 0 ? [...new Set(names)] : void 0;
104
104
  };
105
105
  /** The admin REST API as a Hono app. It uses only Web APIs, so it runs on Node, Workers and anywhere else Hono does. */
106
- const createAdmin = ({ resources: appResources, views: appViews = [], pages = [], userMenu, bottomBars = [], db, authenticate, auth, functions = {}, files: filesOptions, events, history: historyOptions, jobs = [], subscriptions = [], webhooks: webhooksOptions, notifications, mobile, app: identity, icons, bundlePlugins = [], fieldTypes = {}, options = {}, formsDifficulty, commentUsers: givenCommentUsers, verifyToken, upgradeWebSocket }) => {
106
+ const createAdmin = ({ resources: appResources, views: appViews = [], pages = [], userMenu, bottomBars = [], db, authenticate, auth, functions = {}, secret, files: filesOptions, events, history: historyOptions, jobs = [], subscriptions = [], webhooks: webhooksOptions, notifications, mobile, app: identity, icons, bundlePlugins = [], fieldTypes = {}, options = {}, formsDifficulty, commentUsers: givenCommentUsers, verifyToken, upgradeWebSocket }) => {
107
107
  const basePath = options.basePath ?? "/api/v1";
108
108
  const appModels = appResources.map((resource) => resource.toModel());
109
109
  const withComments = appModels.some((model) => model.comments);
@@ -154,6 +154,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
154
154
  views: viewModels,
155
155
  limits: options.roles?.limits ?? [],
156
156
  env: globalThis.process?.env ?? {},
157
+ ...secret && { secret },
157
158
  ...formsDifficulty && { difficulty: formsDifficulty }
158
159
  });
159
160
  const systemPath = basePath.slice(0, basePath.lastIndexOf("/"));
@@ -178,6 +179,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
178
179
  });
179
180
  const files = createFilesRuntime({
180
181
  ...filesOptions && { options: filesOptions },
182
+ ...secret && { secret },
181
183
  env: globalThis.process?.env ?? {},
182
184
  models: registry.entries.map((entry) => entry.model),
183
185
  systemPath,
@@ -27,7 +27,7 @@ const entriesOf = (env) => {
27
27
  }))];
28
28
  };
29
29
  const checkApart = (entries, env) => {
30
- for (const name of ["BETTER_AUTH_SECRET", "PROTOBASE_SECRET_KEY"]) {
30
+ for (const name of ["PROTOBASE_SECRET", "PROTOBASE_SECRET_KEY"]) {
31
31
  const secret = env[name]?.trim();
32
32
  const same = secret && entries.find((entry) => entry.text === secret);
33
33
  if (same) throw new Error(`${same.where} is the same as ${name}: give encryption a key of its own`);
@@ -1,21 +1,18 @@
1
1
  import { Sharp } from "./images.js";
2
2
  import { FileProvider } from "./store.js";
3
3
  //#region src/files/options.d.ts
4
- /** `files` in `protobase.config.ts`. Environment variables override it (see `resolveProviders`). */
4
+ /** Where file fields keep their bytes, as the API runs with them: `files` of `protobase.config.ts` with its providers made. Environment variables override it (see `resolveProviders`). */
5
5
  export type FilesOptions = {
6
6
  /**
7
- * Providers by name, such as `private: localFiles({ dir: './data/files' })`. A name is part of every stored value, so
8
- * name the role (`archive`), not the vendor. Without config, `private` and `public` are folders under `data/files`.
7
+ * Providers by name. A name is part of every stored value, so name the role (`archive`), not the vendor. Without
8
+ * config, `private` and `public` are folders under `data/files`.
9
9
  */
10
10
  providers?: Record<string, FileProvider>;
11
11
  /** How long bytes outlive their last reference, for restores; default `1 day`. Public providers default to 0. */
12
12
  retention?: number | string;
13
- /** Signs upload tickets and download URLs; default `PROTOBASE_FILES_SECRET`, then `BETTER_AUTH_SECRET`. */
13
+ /** Signs upload tickets and download URLs; default `PROTOBASE_FILES_SECRET`, then the app's `secret` (`PROTOBASE_SECRET`). */
14
14
  secret?: string;
15
- /**
16
- * The image library that makes the variants and placeholders of image fields: `import sharp from 'sharp'` in the
17
- * config, so a built bundle carries it with its native add-on.
18
- */
15
+ /** The image library that makes the variants and placeholders of image fields: sharp's default export. */
19
16
  sharp?: Sharp;
20
17
  /**
21
18
  * Hosts whose images the admin app draws with the page's referrer, besides the app's own and those its providers link
@@ -0,0 +1,16 @@
1
+ import { FileProvider } from "./store.js";
2
+ import { LocalFilesOptions } from "./local-files.js";
3
+ import { S3FilesOptions } from "./s3-files.js";
4
+ //#region src/files/provider-settings.d.ts
5
+ /**
6
+ * A built-in file provider in `files.providers`, as data: `{ kind: 'local', dir }`, a folder on local disk, or
7
+ * `{ kind: 's3', bucket }`, an S3-compatible bucket. The provider is made when the app serves.
8
+ */
9
+ export type FileProviderSettings = ({
10
+ kind: 'local';
11
+ } & LocalFilesOptions) | ({
12
+ kind: 's3';
13
+ } & S3FilesOptions);
14
+ /** The provider the settings describe. */
15
+ export declare const fileProviderOf: (name: string, settings: FileProviderSettings) => FileProvider;
16
+ //#endregion
@@ -0,0 +1,17 @@
1
+ import { localFiles } from "./local-files.js";
2
+ import { s3Files } from "./s3-files.js";
3
+ //#region src/files/provider-settings.ts
4
+ /** The provider the settings describe. */
5
+ const fileProviderOf = (name, settings) => {
6
+ if (settings.kind === "local") {
7
+ const { kind: _, ...options } = settings;
8
+ return localFiles(options);
9
+ }
10
+ if (settings.kind === "s3") {
11
+ const { kind: _, ...options } = settings;
12
+ return s3Files(options);
13
+ }
14
+ throw new Error(`files.providers.${name}: kind is "local", "s3" or "custom", whose provider is the default export of files/${name}.ts`);
15
+ };
16
+ //#endregion
17
+ export { fileProviderOf };
@@ -13,7 +13,7 @@ const imageFields = (models) => models.flatMap((model) => Object.values(model.fi
13
13
  * The runtime, when a resource has a file field, the config names providers or the app serves `/api/sb/storage/v1`. It fails at startup when a field's
14
14
  * provider is not configured, nothing signs uploads, or a field makes image variants or placeholders without sharp.
15
15
  */
16
- const createFilesRuntime = ({ options = {}, env, models, systemPath, storage: servesStorage = false }) => {
16
+ const createFilesRuntime = ({ options = {}, env, secret: appSecret, models, systemPath, storage: servesStorage = false }) => {
17
17
  const storageName = servesStorage ? storageProviderName(options) : void 0;
18
18
  const storage = storageName && options.storage !== false ? {
19
19
  provider: storageName,
@@ -22,10 +22,10 @@ const createFilesRuntime = ({ options = {}, env, models, systemPath, storage: se
22
22
  const fieldProviders = models.flatMap((model) => Object.values(model.fields).flatMap((field) => field.file ? [field.file.provider] : []));
23
23
  const used = [.../* @__PURE__ */ new Set([...fieldProviders, ...storage ? [storage.provider] : []])];
24
24
  if (used.length === 0 && !options.providers) return void 0;
25
- const secret = options.secret ?? env.PROTOBASE_FILES_SECRET ?? env.BETTER_AUTH_SECRET;
26
- if (!secret) throw new Error("File fields and /api/sb/storage/v1 need a secret to sign uploads: set BETTER_AUTH_SECRET, PROTOBASE_FILES_SECRET or files.secret");
25
+ const secret = options.secret ?? env.PROTOBASE_FILES_SECRET ?? appSecret ?? env.PROTOBASE_SECRET;
26
+ if (!secret) throw new Error("File fields and /api/sb/storage/v1 need a secret to sign uploads: set secret in protobase.config.ts, files.secret or PROTOBASE_FILES_SECRET");
27
27
  const images = imageFields(models);
28
- if (images.length > 0 && !options.sharp) throw new Error(`${images.join(", ")} make image variants or placeholders, which need sharp: add it to the project (bun add sharp), then import sharp from 'sharp' in the config and pass files: { sharp }`);
28
+ if (images.length > 0 && !options.sharp) throw new Error(`${images.join(", ")} make image variants or placeholders, which need sharp: add it to the project (bun add sharp), then give the config files: { sharp: () => import('sharp') }`);
29
29
  const providers = resolveProviders(options, env, used);
30
30
  const retention = retentionOf(options, env);
31
31
  return {
@@ -12,15 +12,15 @@ const anonymousCreates = (limits) => (resource) => {
12
12
  * The public forms of the views, checked, with the challenges that guard them and their rate limit; `undefined` without
13
13
  * any. Fails at startup on a form that cannot be served and when nothing signs the challenges.
14
14
  */
15
- const createFormsRuntime = ({ registry, views, limits, env, difficulty }) => {
15
+ const createFormsRuntime = ({ registry, views, limits, env, secret: appSecret, difficulty }) => {
16
16
  const declared = [...views].sort((a, b) => Number(a.roles !== void 0) - Number(b.roles !== void 0)).flatMap((view) => (view.forms ?? []).map((form) => ({
17
17
  form,
18
18
  view
19
19
  })));
20
20
  if (declared.length === 0) return void 0;
21
21
  const forms = checkForms(registry, declared, anonymousCreates(limits));
22
- const secret = env.PROTOBASE_FORMS_SECRET ?? env.BETTER_AUTH_SECRET;
23
- if (!secret) throw new Error("Public forms need a secret to sign their bot checks: set PROTOBASE_FORMS_SECRET or BETTER_AUTH_SECRET");
22
+ const secret = env.PROTOBASE_FORMS_SECRET ?? appSecret ?? env.PROTOBASE_SECRET;
23
+ if (!secret) throw new Error("Public forms need a secret to sign their bot checks: set secret in protobase.config.ts, or PROTOBASE_FORMS_SECRET");
24
24
  return {
25
25
  forms,
26
26
  challenges: createFormChallenges(secret, { ...difficulty && { difficulty } }),
@@ -4,7 +4,7 @@ import { goTrueUser } from "./user-json.js";
4
4
  import { accessClaims, goTrueSession } from "./session-json.js";
5
5
  import * as z$1 from "zod";
6
6
  import { APIError, createAuthEndpoint } from "better-auth/api";
7
- import { createJwk, signJWT } from "better-auth/plugins";
7
+ import { signJWT } from "better-auth/plugins";
8
8
  import { generateRandomString } from "better-auth/crypto";
9
9
  //#region src/gotrue/sessions-plugin.ts
10
10
  const refreshTokenNotFound = () => new APIError("BAD_REQUEST", {
@@ -16,13 +16,7 @@ const refreshTokenNotFound = () => new APIError("BAD_REQUEST", {
16
16
  * so signing out anywhere, a ban or a revoked session ends it, and refreshing gives the session a new token, so each
17
17
  * refresh token works once. Server-side endpoints only, for `goTrueRoutes`.
18
18
  */
19
- const goTrueSessionsPlugin = ({ issuer, jwt, policy }) => {
20
- let primaryKeyMade = false;
21
- const makePrimaryKey = async (ctx) => {
22
- if (primaryKeyMade) return;
23
- if (!(await ctx.context.adapter.findMany({ model: "jwks" })).some((key) => key.alg === null || key.alg === void 0 || key.alg === "EdDSA")) await createJwk(ctx, jwt);
24
- primaryKeyMade = true;
25
- };
19
+ const goTrueSessionsPlugin = ({ issuer, jwt, signingKey, policy }) => {
26
20
  const sessionOf = async (ctx, sessionToken) => {
27
21
  const found = await ctx.context.internalAdapter.findSession(sessionToken);
28
22
  if (!found) throw refreshTokenNotFound();
@@ -31,7 +25,7 @@ const goTrueSessionsPlugin = ({ issuer, jwt, policy }) => {
31
25
  if (refusal) throw new APIError("FORBIDDEN", refusal);
32
26
  const accounts = await ctx.context.internalAdapter.findAccounts(user.id);
33
27
  const now = Math.floor(Date.now() / 1e3);
34
- await makePrimaryKey(ctx);
28
+ await signingKey(ctx);
35
29
  const accessToken = await signJWT(ctx, {
36
30
  options: jwt,
37
31
  payload: accessClaims({
package/dist/index.d.ts CHANGED
@@ -51,20 +51,25 @@ import { RuntimeOptions, runtimeUrl, runtimeVariable, seesRuntime } from "./runt
51
51
  import { AdminOptions } from "./admin-options.js";
52
52
  import { CreateAdminInput, createAdmin } from "./create-admin.js";
53
53
  import { handleDroppedConnections } from "./dropped-connections.js";
54
- import { AppPoolConfig, PgModule, appPool, longQueryPool, poolWaitMs, readDbConnections } from "./app-pool.js";
54
+ import { AppPoolConfig, PgModule, poolWaitMs, readDbConnections } from "./app-pool.js";
55
55
  import { ConnectionsBusy } from "./connections-busy.js";
56
56
  import { isBackgroundWork, runInBackground, wantsLongQueries } from "./background-work.js";
57
57
  import { longQueryTimeoutMs } from "./statement-timeout.js";
58
58
  import { checkViewQueries } from "./check-view-queries.js";
59
- import { ProjectConfig, defineConfig, mergeConfig } from "./project-config.js";
60
59
  import { consoleAuditQueue } from "./audit/console-queue.js";
61
60
  import { JwtOptions, JwtVerifyOptions, jwtAuthenticator, jwtVerifier } from "./auth/jwt.js";
61
+ import { SignInPolicy, SignInRule, StaffAccessRule, defaultSignInPolicy, signInPolicyMethods } from "./better-auth/sign-in-policy.js";
62
+ import { StaffSignIn } from "./better-auth/staff-log.js";
63
+ import { RoleDefinition, RolesInput } from "./better-auth/organizations/role-definitions.js";
64
+ import { OrganizationRole, StoredMember, StoredOrganization } from "./better-auth/organizations/store.js";
65
+ import { OrganizationsOptions } from "./better-auth/organizations/options.js";
66
+ import { AuthHooks, AuthSettings, HookContext } from "./better-auth/auth-settings.js";
62
67
  import { TrustedApp, withTrustedApps } from "./better-auth/app-tokens.js";
63
- import { BetterAuthAuthenticator, BetterAuthAuthenticatorOptions, betterAuthAuthenticator, betterAuthTokens } from "./better-auth/authenticator.js";
68
+ import { BetterAuthAuthenticator, BetterAuthAuthenticatorOptions, betterAuthTokens } from "./better-auth/authenticator.js";
69
+ import { AuthenticateSettings } from "./better-auth/authenticate-settings.js";
64
70
  import { parseRoles } from "./better-auth/parse-roles.js";
65
71
  import { LinkedAccount, NewUser, StoredUser, createUser, deleteUser, hasUsers, listUsers, roleChoices, setUserBanned, setUserRole } from "./better-auth/users.js";
66
72
  import { IssueTokenOptions, issueToken, maxTokenTtlSeconds } from "./better-auth/tokens.js";
67
- import { SignInPolicy, SignInRule, StaffAccessRule, defaultSignInPolicy, signInPolicyMethods } from "./better-auth/sign-in-policy.js";
68
73
  import { passwordLength } from "./better-auth/new-account-password.js";
69
74
  import { OperatorProvider, readOperatorSettings } from "./better-auth/operator-provider.js";
70
75
  import { isOAuthWellKnownPath, oauthWellKnownPaths, webauthnPath } from "./better-auth/origins.js";
@@ -72,7 +77,7 @@ import { goTruePath } from "./gotrue/keys.js";
72
77
  import { supabasePath } from "./supabase-paths.js";
73
78
  import { realtimeLimits } from "./realtime/realtime-limits.js";
74
79
  import { capSocketMessages, honorSocketMessageCaps, socketMessageCapOf } from "./functions/socket-message-cap.js";
75
- import { defaultAppName, shownAppName } from "./app-name.js";
80
+ import { appNameOver, defaultAppName, shownAppName } from "./app-name.js";
76
81
  import { webManifestPath } from "./web-app/web-manifest-route.js";
77
82
  import { PlatformSignIn, readPlatformSignIn } from "./better-auth/platform-sign-in.js";
78
83
  import { authSchemaMigration, checkAuthSchema } from "./better-auth/auth-schema.js";
@@ -86,12 +91,10 @@ import { ResourceChange, recordOf, resourceChange } from "./changes/resource-cha
86
91
  import { eventMatcher } from "./changes/match-events.js";
87
92
  import { parseColumns, readOutbox } from "./changes/outbox.js";
88
93
  import { newWebhookSecret } from "./webhooks/standard-webhooks.js";
89
- import { webhooks } from "./webhooks/table/plugin.js";
90
94
  import { checkWebhooksSchema, webhooksMigration } from "./webhooks/table/schema.js";
91
95
  import { checkComments, commentsMigration } from "./comments/comments-sql.js";
92
96
  import { CheckAiInput, checkAi } from "./ai/check-ai.js";
93
97
  import { CommentItem } from "./comments/comment-item.js";
94
- import { notifications } from "./notifications/plugin.js";
95
98
  import { checkNotificationsSchema, notificationsMigration } from "./notifications/schema.js";
96
99
  import { deviceStore, removeDevicesWithUsers } from "./notifications/device-store-of.js";
97
100
  import { DeviceStoreError, postgresDeviceStore } from "./notifications/postgres-store.js";
@@ -105,11 +108,7 @@ import { sendNotification } from "./notifications/send-notification.js";
105
108
  import { VapidSettings, readVapidSettings, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable } from "./notifications/web-push/vapid-settings.js";
106
109
  import { WebPushOptions, webPushSender } from "./notifications/web-push/web-push-sender.js";
107
110
  import { generateVapidKeys } from "./notifications/web-push/keys.js";
108
- import { RoleDefinition, RolesInput } from "./better-auth/organizations/role-definitions.js";
109
- import { OrganizationRole, StoredMember, StoredOrganization } from "./better-auth/organizations/store.js";
110
- import { OrganizationsOptions } from "./better-auth/organizations/options.js";
111
111
  import { MemberInput, NewOrganization, addAppRoleToOwners, addMember, createOrganization, listOrganizations, removeMember, setMemberRoles } from "./better-auth/organizations/host.js";
112
- import { StaffSignIn } from "./better-auth/staff-log.js";
113
112
  import { AssistantBackend, assistantProtocolRoutes } from "./assistant/protocol-routes.js";
114
113
  import { fileConversationStore } from "./assistant/file-conversation-store.js";
115
114
  import { withCacheBreakpoints } from "./assistant/cache-breakpoints.js";
@@ -139,9 +138,10 @@ import { SignatureOptions, StandardWebhookOptions, verifySignature, verifyStanda
139
138
  import { requireEnv } from "./functions/require-env.js";
140
139
  import { backgroundSettled, waitUntil } from "./functions/wait-until.js";
141
140
  import { FileLimits, limitedFileStore, storeUsage } from "./files/limits.js";
142
- import { LocalFilesOptions, localFileStore, localFiles } from "./files/local-files.js";
141
+ import { LocalFilesOptions, localFileStore } from "./files/local-files.js";
142
+ import { S3Bucket, S3FilesOptions, S3ListPage, S3Object, s3FileStore } from "./files/s3-files.js";
143
+ import { FileProviderSettings } from "./files/provider-settings.js";
143
144
  import { StoreFileInput, storeFile } from "./files/store-file.js";
144
- import { S3Bucket, S3FilesOptions, S3ListPage, S3Object, s3FileStore, s3Files } from "./files/s3-files.js";
145
145
  import { storageProvider } from "./files/storage-provider.js";
146
146
  import { objectKey } from "./storage/object-key.js";
147
147
  import { FileCleanupInput, createFileCleanup } from "./files/file-cleanup.js";
@@ -154,6 +154,7 @@ import { FileRef, formatUri, variantPath } from "./files/uri.js";
154
154
  import { aspectRatio, fileSize, fileType, imageSize, processor } from "./files/processors.js";
155
155
  import { defineJob, isJobDefinition, jobDefinitions } from "./jobs/define-job.js";
156
156
  import { FatalJobError } from "./jobs/run-job.js";
157
+ import { JobDeclaration, JobRun, enqueueJob } from "./jobs/declared-job.js";
157
158
  import { isSchedule } from "./jobs/schedule.js";
158
159
  import { EmailComponent, EmailOptions, EmailTemplate, RenderedEmail, defineEmail } from "./mail/define-email.js";
159
160
  import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/runtime.js";
@@ -162,5 +163,5 @@ import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.
162
163
  import { MobileRelease, ReleaseFile, ServedReleaseFile, composeRelease, releaseManifest } from "./mobile-release/release.js";
163
164
  import { MobileReleaseAppInput, OfferedRelease, mobileReleaseApp } from "./mobile-release/release-app.js";
164
165
  import { mobileSigningKeyVariable, readSigningKey } from "./mobile-release/signing-key.js";
165
- import { AdminAuth, CreateAuthOptions, UserCreatedHook, createAuth, normalizeRoles } from "./better-auth/create-auth.js";
166
- export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApnsEnvironment, type AppIcons, type AppIdentity, type AppPoolConfig, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BatchOperation, type BatchResult, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type CascadingKey, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, ConnectionsBusy, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type Device, type DeviceColumn, type DeviceKind, type DeviceStore, DeviceStoreError, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldStatus, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSocket, type FunctionSource, type HistoryColumn, type HistoryOptions, type HistoryPosition, type HistoryStore, HistoryStoreError, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JsonObject, type JsonValue, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type McpApprovals, type McpGateInput, type McpHandlerInput, type McpRoutesInput, type McpServerInput, type McpToolsInput, type McpWrites, type MemberInput, type Membership, MissingCredentials, type MobileConfig, type MobileRelease, type MobileReleaseAppInput, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OfferedRelease, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordKeyInput, type RecordPage, type ReleaseFile, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type SendNotification, type ServedReleaseFile, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SocketEvents, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredNotification, type StoredObject, type StoredOrganization, type StoredUser, type StrayValues, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolAnnotations, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type VapidSettings, type ViewSource, type WebPushFields, type WebPushOptions, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, type WriteRecordToolsInput, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appPool, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, capSocketMessages, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkResourcesOutsideAuthStore, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, composeRelease, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteRecordTool, deleteUser, deviceIdParam, deviceStore, devicesPath, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, generateVapidKeys, getRecordTool, goTruePath, handleDroppedConnections, hasUsers, historyIdParam, historyIdPattern, historyLimits, historyPath, historyStore, honorSocketMessageCaps, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, localFiles, longQueryPool, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpRoutes, mcpServer, mcpToolContext, mcpTools, mergeConfig, migrationCommand, mobileReleaseApp, mobileSigningKeyVariable, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notifications, notificationsMigration, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readSigningKey, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, recordOf, releaseManifest, removeDevicesWithUsers, removeHistoryWithUsers, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, sendNotification, sessionOf, setMemberRoles, setUserBanned, setUserRole, shownAppName, signInPolicyMethods, socketMessageCapOf, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
166
+ import { AdminAuth, CreateAuthOptions, UserCreatedHook, normalizeRoles } from "./better-auth/create-auth.js";
167
+ export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApnsEnvironment, type AppIcons, type AppIdentity, type AppPoolConfig, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type AuthHooks, type AuthSettings, type AuthenticateSettings, type Authenticator, type BatchOperation, type BatchResult, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type CascadingKey, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, ConnectionsBusy, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type Device, type DeviceColumn, type DeviceKind, type DeviceStore, DeviceStoreError, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldStatus, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileProviderSettings, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSocket, type FunctionSource, type HistoryColumn, type HistoryOptions, type HistoryPosition, type HistoryStore, HistoryStoreError, type HookContext, HttpProblem, type IssueTokenOptions, type JobContext, type JobDeclaration, type JobDefinition, type JobOptions, type JobRun, type JobsRuntime, type JsonObject, type JsonValue, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type McpApprovals, type McpGateInput, type McpHandlerInput, type McpRoutesInput, type McpServerInput, type McpToolsInput, type McpWrites, type MemberInput, type Membership, MissingCredentials, type MobileConfig, type MobileRelease, type MobileReleaseAppInput, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OfferedRelease, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordKeyInput, type RecordPage, type ReleaseFile, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type SendNotification, type ServedReleaseFile, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SocketEvents, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredNotification, type StoredObject, type StoredOrganization, type StoredUser, type StrayValues, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolAnnotations, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type VapidSettings, type ViewSource, type WebPushFields, type WebPushOptions, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, type WriteRecordToolsInput, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, capSocketMessages, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkResourcesOutsideAuthStore, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, composeRelease, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, defineTool, deleteRecordTool, deleteUser, deviceIdParam, deviceStore, devicesPath, enqueueJob, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, generateVapidKeys, getRecordTool, goTruePath, handleDroppedConnections, hasUsers, historyIdParam, historyIdPattern, historyLimits, historyPath, historyStore, honorSocketMessageCaps, imageSize, isBackgroundWork, isCaptured, isJobDefinition, isOAuthWellKnownPath, isSchedule, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, mobileReleaseApp, mobileSigningKeyVariable, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readSigningKey, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, recordOf, releaseManifest, removeDevicesWithUsers, removeHistoryWithUsers, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, seesAssistant, seesRuntime, sendNotification, sessionOf, setMemberRoles, setUserBanned, setUserRole, shownAppName, signInPolicyMethods, socketMessageCapOf, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };