@protobase/server 0.67.3 → 0.67.5

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.
@@ -590,7 +590,17 @@ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlug
590
590
  userId: string;
591
591
  expiresAt: Date;
592
592
  token: string;
593
- ipAddress?: string | null | undefined;
593
+ ipAddress?
594
+ /**
595
+ * What the sign-in page leads with: `password`, the email address and a password, with emailing a code below it; or
596
+ * `emailCode`, the address and "Email me a sign-in code", with the password behind "Use a password", for apps whose
597
+ * people mostly never set one. Only while the policy leaves both on; default `password`.
598
+ */
599
+ /**
600
+ * What the sign-in page leads with: `password`, the email address and a password, with emailing a code below it; or
601
+ * `emailCode`, the address and "Email me a sign-in code", with the password behind "Use a password", for apps whose
602
+ * people mostly never set one. Only while the policy leaves both on; default `password`.
603
+ */ : string | null | undefined;
594
604
  userAgent?: string | null | undefined;
595
605
  };
596
606
  };
@@ -1666,7 +1676,7 @@ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlug
1666
1676
  email: string;
1667
1677
  emailVerified: boolean;
1668
1678
  name: string;
1669
- image? /** Public origin of the API, for example `https://admin.example.com`. Issuer and audience of the tokens; new passkeys are made for its host unless `passkeyDomain` names another. */ : string | null | undefined;
1679
+ image?: string | null | undefined;
1670
1680
  };
1671
1681
  };
1672
1682
  }>>[];
@@ -2411,9 +2421,7 @@ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlug
2411
2421
  email: string;
2412
2422
  emailVerified: boolean;
2413
2423
  name: string;
2414
- image?
2415
- /** The RP ID of new passkeys, from `resolvePasskeyDomain`; default the host of `baseURL`. */
2416
- /** The RP ID of new passkeys, from `resolvePasskeyDomain`; default the host of `baseURL`. */ : string | null | undefined;
2424
+ image?: string | null | undefined;
2417
2425
  };
2418
2426
  };
2419
2427
  }>>[];
@@ -17,7 +17,7 @@ import { jsonOnlyOnMobile, mobileRequests } from "./mobile-requests.js";
17
17
  import { passwordLength } from "./new-account-password.js";
18
18
  import { platformMailer } from "../mail/platform-mailer.js";
19
19
  import { readOperatorSettings, resolveOperator } from "./operator-provider.js";
20
- import { defaultInvitationUrl } from "./invitations/invitation-link-hook.js";
20
+ import "./invitations/invitation-link-hook.js";
21
21
  import { lastAdminGuardPlugin } from "./last-admin-guard.js";
22
22
  import { setPasswordPath, setPasswordPlugin } from "./set-password.js";
23
23
  import { emailCodeOptions, twoFactorCodeOptions, unusedEmailCodePaths } from "./sign-in-mail.js";
@@ -271,7 +271,7 @@ const betterAuthOptions = (options, { origins = [], passkeyDomain, roles, defini
271
271
  definitions,
272
272
  defaultPolicy: signInPolicy,
273
273
  ...mail && { mail },
274
- invitationUrl: organizations?.invitationUrl ?? defaultInvitationUrl(options.baseURL),
274
+ ...organizations?.invitationUrl !== void 0 && { invitationUrl: organizations.invitationUrl },
275
275
  invitationSeconds: organizations?.invitationExpiresIn ?? 604800,
276
276
  ...organizations && { organizations }
277
277
  }),
@@ -410,7 +410,7 @@ const createAuth = (options, plugins = {}) => {
410
410
  const personalMail = resolvePersonalMail(options.personalMail ?? [], socialProviders, options.encryptOAuthTokens === true);
411
411
  const origins = resolveOrigins(options.baseURL, options.origins ?? platformOrigins());
412
412
  const passkeyDomain = resolvePasskeyDomain(options.passkeyDomain ?? platformPasskeyDomain(), [options.baseURL, ...origins]);
413
- const organizations = options.organizations && resolveOrganizations(options.organizations, definitions, options.baseURL);
413
+ const organizations = options.organizations && resolveOrganizations(options.organizations, definitions);
414
414
  const mcp = options.mcp && resolveMcp(options.baseURL, options.mcp);
415
415
  let instance;
416
416
  const context = () => instance?.$context ?? Promise.reject(/* @__PURE__ */ new Error("The auth instance is not made yet"));
@@ -1,3 +1,4 @@
1
+ import { requestAppUrl } from "../../request-app-url.js";
1
2
  import { invitationLink, invitationToken } from "./invitation-token.js";
2
3
  import { createAuthMiddleware } from "better-auth/api";
3
4
  //#region src/better-auth/invitations/invitation-link-hook.ts
@@ -9,7 +10,7 @@ import { createAuthMiddleware } from "better-auth/api";
9
10
  const invitationLinkHook = (paths, invitationUrl) => ({
10
11
  matcher: (context) => paths.includes(context.path ?? ""),
11
12
  handler: createAuthMiddleware(async (ctx) => {
12
- const answer = await withInvitationLink(ctx.context.returned, ctx.context.secret, invitationUrl);
13
+ const answer = await withInvitationLink(ctx.context.returned, ctx.context.secret, invitationPage(invitationUrl, ctx.context.baseURL));
13
14
  if (answer) ctx.context.returned = answer;
14
15
  })
15
16
  });
@@ -26,9 +27,13 @@ const withInvitationLink = async (returned, secret, invitationUrl) => {
26
27
  link: invitationLink(invitationUrl, token)
27
28
  };
28
29
  };
29
- /** The page an invitation link opens, with `?token=`, unless the app names another. */
30
- const defaultInvitationUrl = (baseURL) => `${baseURL.replace(/\/$/, "")}/-/invitation`;
30
+ /**
31
+ * The page an invitation link opens, with `?token=`: the app's own `invitationUrl`, or `/-/invitation` on the origin
32
+ * the request came to, from Better Auth's `ctx.context.baseURL` (`requestAppUrl`), so a link made on one of the app's
33
+ * origins opens there.
34
+ */
35
+ const invitationPage = (invitationUrl, requestURL) => invitationUrl ?? requestAppUrl(requestURL, "/-/invitation");
31
36
  /** How long an invitation works unless the app says otherwise: 7 days, in seconds. */
32
37
  const defaultInvitationSeconds = 604800;
33
38
  //#endregion
34
- export { defaultInvitationSeconds, defaultInvitationUrl, invitationLinkHook, withInvitationLink };
39
+ export { defaultInvitationSeconds, invitationLinkHook, invitationPage, withInvitationLink };
@@ -22,7 +22,7 @@ export type OrganizationsOptions = {
22
22
  * rows in any `.tenant` resource; `'cascade'` leaves it to the project's foreign keys.
23
23
  */
24
24
  deleteRecords?: 'refuse' | 'cascade';
25
- /** The page an invitation link opens, with `?token=`. Default `{baseURL}/-/invitation`. */
25
+ /** The page an invitation link opens, with `?token=`. Default `/-/invitation` on the origin the request came to. */
26
26
  invitationUrl?: string;
27
27
  /** Runs after an organization is created, with its owner's membership, for example to add the app's own row for it. */
28
28
  onCreated?: (input: {
@@ -42,7 +42,7 @@ export type ResolvedOrganizations = {
42
42
  membershipLimit: number;
43
43
  generateId: () => string | Promise<string>;
44
44
  deleteRecords: 'refuse' | 'cascade';
45
- invitationUrl: string;
45
+ invitationUrl?: string;
46
46
  options: OrganizationsOptions;
47
47
  };
48
48
  //#endregion
@@ -1,7 +1,6 @@
1
1
  import { membershipRoles } from "./role-definitions.js";
2
- import { defaultInvitationUrl } from "../invitations/invitation-link-hook.js";
3
2
  //#region src/better-auth/organizations/options.ts
4
- const resolveOrganizations = (options, definitions, baseURL) => {
3
+ const resolveOrganizations = (options, definitions) => {
5
4
  const holdable = membershipRoles(definitions);
6
5
  const creatorAppRoles = options.creatorAppRoles === void 0 || options.creatorAppRoles === "all" ? holdable : options.creatorAppRoles;
7
6
  const unknown = creatorAppRoles.find((name) => !holdable.includes(name));
@@ -16,7 +15,7 @@ const resolveOrganizations = (options, definitions, baseURL) => {
16
15
  membershipLimit: options.membershipLimit ?? 1e3,
17
16
  generateId: options.generateId ?? (() => crypto.randomUUID()),
18
17
  deleteRecords: options.deleteRecords ?? "refuse",
19
- invitationUrl: options.invitationUrl ?? defaultInvitationUrl(baseURL),
18
+ ...options.invitationUrl !== void 0 && { invitationUrl: options.invitationUrl },
20
19
  options
21
20
  };
22
21
  };
@@ -2,8 +2,10 @@ import "./role-definitions.js";
2
2
  import { checkAppRoleChange, effectiveRoles, globalRoles, parseAppRoles } from "./app-roles.js";
3
3
  import { findMember } from "./store.js";
4
4
  import { invitationLink, invitationToken } from "../invitations/invitation-token.js";
5
+ import { invitationPage } from "../invitations/invitation-link-hook.js";
5
6
  import { sendAuthEmail } from "../auth-mail/send-auth-email.js";
6
7
  import { APIError } from "better-auth/api";
8
+ import { getCurrentAuthEndpointContext } from "@better-auth/core/context";
7
9
  import { organization } from "better-auth/plugins/organization";
8
10
  //#region src/better-auth/organizations/organization-plugin.ts
9
11
  /** The snake_case names of the organization plugin's tables and columns, with the app roles of members and invitations. */
@@ -112,8 +114,8 @@ const organizationPlugin = ({ resolved, secret, mail, context }) => {
112
114
  cancelPendingInvitationsOnReInvite: true,
113
115
  schema: organizationNames,
114
116
  ...mail && { sendInvitationEmail: async ({ invitation, organization, inviter }) => {
115
- const token = await invitationToken(secret, invitation);
116
- const url = invitationLink(resolved.invitationUrl, token);
117
+ const page = invitationPage(resolved.invitationUrl, getCurrentAuthEndpointContext().context.baseURL);
118
+ const url = invitationLink(page, await invitationToken(secret, invitation));
117
119
  await sendAuthEmail(mail, "invitationEmail", invitation.email, {
118
120
  inviter: inviter.user.name || inviter.user.email,
119
121
  organization: organization.name,
@@ -17,9 +17,11 @@ import { Hono } from "hono";
17
17
  * with their labels, `membership` for those a member can hold, and the roles each one's holders may also give; and
18
18
  * `anonymous` when the project's anonymous role reads a resource, so the admin app opens for visitors before anyone signs in; `mcp` when MCP clients can connect, with the `url` of its endpoint, so the account page shows that address and lists the connected clients; `personalMail`, the mail providers people may link their mailbox with, each with the sign-in provider it links through, the scopes and the authorization parameters of the link, so the account page offers "Link Gmail"; and
19
19
  * `plugins`, those the app loads before sign-in (see `PluginOption`); and `locale`, the language `options.locale` puts
20
- * the screens in, so the sign-in screens and public forms, which come before `/meta`, are in it too.
20
+ * the screens in, so the sign-in screens and public forms, which come before `/meta`, are in it too; `appName` and
21
+ * `appIcon`, the app's name and the path of its own icon when it has one, which those screens show as `/meta` names them;
22
+ * and `runsOnNote` when the host has the sign-in page end on the "Runs on Protobase" note (see `readRunsOnNote`).
21
23
  */
22
- const statusRoute = (auth, { anonymous = false, plugins = [], locale, firstAdminUrl } = {}) => {
24
+ const statusRoute = (auth, { anonymous = false, plugins = [], locale, firstAdminUrl, appName, appIcon, runsOnNote = false } = {}) => {
23
25
  const app = new Hono();
24
26
  app.get("/status", async (c) => {
25
27
  const context = await auth.$context;
@@ -60,6 +62,9 @@ const statusRoute = (auth, { anonymous = false, plugins = [], locale, firstAdmin
60
62
  })) },
61
63
  ...plugins.length > 0 && { plugins },
62
64
  ...locale && { locale },
65
+ ...appName && { appName },
66
+ ...appIcon && { appIcon },
67
+ ...runsOnNote && { runsOnNote },
63
68
  ...auth.organizations && { organizations: {
64
69
  create: auth.organizations.create,
65
70
  roles: roleLabels(auth.roleDefinitions)
@@ -1,5 +1,6 @@
1
1
  import { adminOnly } from "../admin-only.js";
2
2
  import { invitationLink, invitationToken } from "../invitations/invitation-token.js";
3
+ import { invitationPage } from "../invitations/invitation-link-hook.js";
3
4
  import { sendAuthEmail } from "../auth-mail/send-auth-email.js";
4
5
  import { createAppInvitation, deleteAppInvitation, listAppInvitations } from "./app-invitation-store.js";
5
6
  import { roleLabels } from "../roles/role-labels.js";
@@ -46,7 +47,7 @@ const userEndpoints = ({ definitions, mail, invitationUrl, invitationSeconds })
46
47
  inviterId: inviter.id
47
48
  }, invitationSeconds);
48
49
  if (mail) {
49
- const url = invitationLink(invitationUrl, await invitationToken(ctx.context.secret, invitation));
50
+ const url = invitationLink(invitationPage(invitationUrl, ctx.context.baseURL), await invitationToken(ctx.context.secret, invitation));
50
51
  await sendAuthEmail(mail, "invitationEmail", invitation.email, {
51
52
  inviter: inviter.name || inviter.email,
52
53
  url,
@@ -1,6 +1,9 @@
1
1
  import { configExports } from "./resource-source.js";
2
+ import { ownedTableNames } from "./user-tables/owned-definitions.js";
2
3
  import { definitionsSchema, userTablesSchema } from "./user-tables/names.js";
4
+ import { CheckedDefinition } from "./user-tables/check-definition.js";
5
+ import { maxTextLength } from "./user-tables/definition-resource.js";
3
6
  import { userTableResources } from "./user-tables/user-table-resources.js";
4
7
  import { builtInResources } from "./built-in-resources.js";
5
8
  import { webhooksModule } from "./webhooks/table/webhooks-module.js";
6
- export { builtInResources, configExports, definitionsSchema, userTableResources, userTablesSchema, webhooksModule };
9
+ export { type CheckedDefinition, builtInResources, configExports, definitionsSchema, maxTextLength, ownedTableNames, userTableResources, userTablesSchema, webhooksModule };
@@ -1,6 +1,8 @@
1
1
  import { builtInResources } from "./built-in-resources.js";
2
2
  import { definitionsSchema, userTablesSchema } from "./user-tables/names.js";
3
+ import { maxTextLength } from "./user-tables/definition-resource.js";
3
4
  import { configExports } from "./resource-source.js";
5
+ import { ownedTableNames } from "./user-tables/owned-definitions.js";
4
6
  import { userTableResources } from "./user-tables/user-table-resources.js";
5
7
  import { webhooksModule } from "./webhooks/table/webhooks-module.js";
6
- export { builtInResources, configExports, definitionsSchema, userTableResources, userTablesSchema, webhooksModule };
8
+ export { builtInResources, configExports, definitionsSchema, maxTextLength, ownedTableNames, userTableResources, userTablesSchema, webhooksModule };
@@ -108,6 +108,7 @@ import { metaRoutes } from "./routes/meta.js";
108
108
  import { faviconPath } from "./web-app/web-manifest.js";
109
109
  import { webManifestRoute } from "./web-app/web-manifest-route.js";
110
110
  import { mcpIcons } from "./web-app/mcp-icons.js";
111
+ import { readRunsOnNote } from "./runs-on-note.js";
111
112
  import { recordRoutes } from "./routes/record.js";
112
113
  import { firstAdminUrl } from "./better-auth/first-admin-url.js";
113
114
  import { createScanGuard } from "./scan-guard.js";
@@ -187,6 +188,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
187
188
  const assistant = assistantSettings(options.assistant, globalThis.process?.env ?? {});
188
189
  const runtime = runtimeUrl(options.runtime, globalThis.process?.env ?? {});
189
190
  const firstAdmin = firstAdminUrl(globalThis.process?.env ?? {});
191
+ const runsOnNote = readRunsOnNote(globalThis.process?.env ?? {});
190
192
  const errorReporting = errorReportingSettings(options.errorReporting, globalThis.process?.env ?? {});
191
193
  const maps = mapSettings(options.maps, globalThis.process?.env ?? {});
192
194
  const senders = notifications ? notificationSenders(notifications) : [];
@@ -287,7 +289,8 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
287
289
  }) }
288
290
  };
289
291
  const appName = shownAppName(auth, globalThis.process?.env ?? {});
290
- const meta = createMeta(deps, appName, icons?.favicon ? faviconPath : void 0);
292
+ const appIcon = icons?.favicon ? faviconPath : void 0;
293
+ const meta = createMeta(deps, appName, appIcon);
291
294
  const onError = createErrorHandler(options.onUnhandledError, deps.statementTimeoutMs);
292
295
  const guarded = (routes, caller = authenticate) => {
293
296
  const app = new Hono();
@@ -308,7 +311,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
308
311
  app.route("/", recordRoutes(deps));
309
312
  }, withAnonymous(authenticate, options.roles));
310
313
  const system = guarded((app) => {
311
- app.route("/", docsRoutes(deps));
314
+ app.route("/", docsRoutes(deps, appName));
312
315
  });
313
316
  const metaApp = guarded((app) => {
314
317
  app.route("/", metaRoutes(meta));
@@ -337,7 +340,10 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
337
340
  anonymous: visitorsBrowse(options.roles),
338
341
  plugins: pluginsBeforeSignIn(plugins),
339
342
  ...locale && { locale },
340
- ...firstAdmin && { firstAdminUrl: firstAdmin }
343
+ ...firstAdmin && { firstAdminUrl: firstAdmin },
344
+ appName,
345
+ ...appIcon && { appIcon },
346
+ runsOnNote
341
347
  }));
342
348
  if (auth.organizations) app.route(authBasePath, organizationRoutes({
343
349
  auth,
package/dist/index.d.ts CHANGED
@@ -102,6 +102,7 @@ import { parseColumns, readOutbox } from "./changes/outbox.js";
102
102
  import { newWebhookSecret } from "./webhooks/standard-webhooks.js";
103
103
  import { checkWebhooksSchema, webhooksMigration } from "./webhooks/table/schema.js";
104
104
  import { checkUserTablesSchema, userTablesMigration } from "./user-tables/schema.js";
105
+ import { ownedDefinitionsMigration } from "./user-tables/owned-definitions.js";
105
106
  import { UserTables, userTableResources } from "./user-tables/user-table-resources.js";
106
107
  import { readDefinitionsVersion } from "./user-tables/definitions-version.js";
107
108
  import { reloadingAdmin } from "./user-tables/reloading-admin.js";
@@ -188,4 +189,4 @@ import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/ru
188
189
  import { jobsDrainApp } from "./jobs/drain-route.js";
189
190
  import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
190
191
  import { AdminAuth, CreateAuthOptions, UserCreatedHook, normalizeRoles } from "./better-auth/create-auth.js";
191
- export { type Admin, type AdminAuth, type AdminOptions, type AggregateParams, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApnsEnvironment, type AppIcons, type AppIdentity, type AppPoolConfig, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type ArgumentsPayload, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type AuthHooks, type AuthSettings, type AuthenticateSettings, type Authenticator, type BaseToolContext, type BatchOperation, type BatchResult, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type CallBackend, type CallMember, type Caller, type CallerOptions, type CallsAccess, type CallsOptions, type CapturedRow, type CascadingKey, type ChannelBroadcast, type ChannelSender, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentToolsInput, type CommentUsers, type Completion, type CompletionOptions, ConnectionsBusy, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DecryptField, type Device, type DeviceColumn, type DeviceKind, type DeviceStore, DeviceStoreError, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueJob, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldDecrypter, type FieldReader, 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 JobName, type JobOptions, type JobPayload, type JobRun, type JobsRuntime, type JsonObject, type JsonValue, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LiveKitBackend, type LocalFilesOptions, type MailAttachment, type MailMessage, MailServerTimeoutError, 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, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PdfComponent, type PdfOptions, type PdfTemplate, PersonalMailError, type PersonalMailErrorCode, type PersonalMailProviderId, 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 RealtimeOptions, type RealtimePrune, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordGroups, type RecordKey, type RecordKeyInput, type RecordPage, 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 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 StatusOptions, 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 ToolComment, type ToolCommentPage, type ToolComments, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type UserTables, type VapidSettings, type ViewSource, type WebPushFields, type WebPushOptions, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, type WriteRecordToolsInput, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, callsMigration, capSocketMessages, changesMigration, channelSendsMigration, checkAi, checkAuthSchema, checkCalls, checkChanges, checkChannelSends, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkStatusSchema, checkUserTablesSchema, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, definePdf, defineTool, deleteRecordTool, deleteUser, describeResourceTool, 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, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpInstructions, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, onDoNotDisturb, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readDefinitionsVersion, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, reloadingAdmin, 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, sqlSends, startErrorReporting, startJobs, statusMigration, statusNames, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, userTableResources, userTablesMigration, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
192
+ export { type Admin, type AdminAuth, type AdminOptions, type AggregateParams, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApnsEnvironment, type AppIcons, type AppIdentity, type AppPoolConfig, type ApplyOptions, type ApplyResult, type ApprovalAnswer, type ApprovalRequest, type ArgumentsPayload, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type AuthHooks, type AuthSettings, type AuthenticateSettings, type Authenticator, type BaseToolContext, type BatchOperation, type BatchResult, type BetterAuthAuthenticator, type BetterAuthAuthenticatorOptions, type CallBackend, type CallMember, type Caller, type CallerOptions, type CallsAccess, type CallsOptions, type CapturedRow, type CascadingKey, type ChannelBroadcast, type ChannelSender, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentToolsInput, type CommentUsers, type Completion, type CompletionOptions, ConnectionsBusy, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DecryptField, type Device, type DeviceColumn, type DeviceKind, type DeviceStore, DeviceStoreError, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EncryptionStatus, type EncryptionTools, type EncryptionToolsInput, type EnqueueJob, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FieldApplied, type FieldDecrypter, type FieldReader, 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 JobName, type JobOptions, type JobPayload, type JobRun, type JobsRuntime, type JsonObject, type JsonValue, type JwtOptions, type JwtVerifyOptions, type KeyFunctionContext, type LinkedAccount, type ListParams, type LiveKitBackend, type LocalFilesOptions, type MailAttachment, type MailMessage, MailServerTimeoutError, 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, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PdfComponent, type PdfOptions, type PdfTemplate, PersonalMailError, type PersonalMailErrorCode, type PersonalMailProviderId, 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 RealtimeOptions, type RealtimePrune, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordGroups, type RecordKey, type RecordKeyInput, type RecordPage, 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 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 StatusOptions, 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 ToolComment, type ToolCommentPage, type ToolComments, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type UserTables, type VapidSettings, type ViewSource, type WebPushFields, type WebPushOptions, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, type WriteRecordToolsInput, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, callsMigration, capSocketMessages, changesMigration, channelSendsMigration, checkAi, checkAuthSchema, checkCalls, checkChanges, checkChannelSends, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkStatusSchema, checkUserTablesSchema, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, definePdf, defineTool, deleteRecordTool, deleteUser, describeResourceTool, 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, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpInstructions, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, onDoNotDisturb, ownedDefinitionsMigration, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readDefinitionsVersion, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, reloadingAdmin, 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, sqlSends, startErrorReporting, startJobs, statusMigration, statusNames, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, userTableResources, userTablesMigration, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
package/dist/index.js CHANGED
@@ -114,6 +114,7 @@ import { checkResourcesOutsideAuthStore } from "./better-auth/store/resources-ou
114
114
  import { checkComputed, computedMigration } from "./computed/computed-schema.js";
115
115
  import { checkWebhooksSchema, webhooksMigration } from "./webhooks/table/schema.js";
116
116
  import { checkUserTablesSchema, userTablesMigration } from "./user-tables/schema.js";
117
+ import { ownedDefinitionsMigration } from "./user-tables/owned-definitions.js";
117
118
  import { userTableResources } from "./user-tables/user-table-resources.js";
118
119
  import { readDefinitionsVersion } from "./user-tables/definitions-version.js";
119
120
  import { reloadingAdmin } from "./user-tables/reloading-admin.js";
@@ -139,4 +140,4 @@ import { defineEmail } from "./mail/define-email.js";
139
140
  import { definePdf } from "./pdf/define-pdf.js";
140
141
  import { startJobs } from "./jobs/runtime.js";
141
142
  import { jobsDrainApp } from "./jobs/drain-route.js";
142
- export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, MailServerTimeoutError, MissingCredentials, ModelError, NotificationSendError, PersonalMailError, PushMessageError, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, callsMigration, capSocketMessages, changesMigration, channelSendsMigration, checkAi, checkAuthSchema, checkCalls, checkChanges, checkChannelSends, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkStatusSchema, checkUserTablesSchema, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, definePdf, defineTool, deleteRecordTool, deleteUser, describeResourceTool, 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, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpInstructions, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, onDoNotDisturb, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readDefinitionsVersion, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, reloadingAdmin, 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, sqlSends, startErrorReporting, startJobs, statusMigration, statusNames, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, userTableResources, userTablesMigration, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
143
+ export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, MailServerTimeoutError, MissingCredentials, ModelError, NotificationSendError, PersonalMailError, PushMessageError, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, callsMigration, capSocketMessages, changesMigration, channelSendsMigration, checkAi, checkAuthSchema, checkCalls, checkChanges, checkChannelSends, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkStatusSchema, checkUserTablesSchema, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, definePdf, defineTool, deleteRecordTool, deleteUser, describeResourceTool, 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, listCommentsTool, listOrganizations, listRecordsTool, listResourcesTool, listUsers, localFileStore, longQueryTimeoutMs, mapSettings, mapStyleUrl, mapStyleVariable, maxDevicesPerUser, maxHistoryPage, maxMessageBytes, maxRecipients, maxTokenTtlSeconds, maxTtlSeconds, maxUnreadCount, maxWidgetPropsBytes, mcpApprovals, mcpGate, mcpHandler, mcpIcons, mcpInstructions, mcpRoutes, mcpServer, mcpToolContext, mcpTools, migrationCommand, newWebhookSecret, normalizeRoles, notFound, notificationSenders, notificationsMigration, oauthWellKnownPaths, objectKey, onDoNotDisturb, ownedDefinitionsMigration, parseColumns, parseRoles, passwordLength, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, pngIcons, poolWaitMs, postgresDeviceStore, postgresHistoryStore, processor, pushMessage, queryRunnerMigration, readDbConnections, readDefinitionsVersion, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, reloadingAdmin, 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, sqlSends, startErrorReporting, startJobs, statusMigration, statusNames, storageCleanupSchedule, storageProvider, storeFile, storeUsage, streamChatCompletion, subscription, supabasePath, thumbHash, unauthorized, updateRecordTool, urgencies, userTableResources, userTablesMigration, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
@@ -1,3 +1,4 @@
1
+ import { requestAppUrl } from "../request-app-url.js";
1
2
  //#region src/mail/mailing-app.ts
2
3
  /**
3
4
  * The app as an auth email names it: `appName`, and the home page on the origin of `requestURL`, a URL on the origin
@@ -5,7 +6,7 @@
5
6
  */
6
7
  const mailingApp = ({ appName, baseURL }, requestURL) => ({
7
8
  name: appName,
8
- url: new URL("/", requestURL ?? baseURL).href
9
+ url: requestAppUrl(requestURL ?? baseURL, "/")
9
10
  });
10
11
  //#endregion
11
12
  export { mailingApp };
@@ -4,11 +4,13 @@ import { resourceSchemas } from "./schemas.js";
4
4
  //#region src/openapi/document.ts
5
5
  const resourcesServer = (basePath) => basePath.slice(basePath.lastIndexOf("/") + 1);
6
6
  const systemServer = ".";
7
+ /** The title of the app's API reference and OpenAPI document, such as "Shop & Co API". */
8
+ const apiTitle = (appName) => `${appName} API`;
7
9
  /** The OpenAPI 3.1 document for one caller, generated from the resource models they may see and their zod record schemas. */
8
- const openApiDocument = (accesses, basePath) => ({
10
+ const openApiDocument = (accesses, basePath, appName) => ({
9
11
  openapi: "3.1.0",
10
12
  info: {
11
- title: "Protobase API",
13
+ title: apiTitle(appName),
12
14
  version: "1.0.0",
13
15
  description: "Admin API for an existing Postgres database. Follows Google's API design conventions ([AIP](https://google.aip.dev)) and reports errors as RFC 9457 `application/problem+json`."
14
16
  },
@@ -73,4 +75,4 @@ const openApiDocument = (accesses, basePath) => ({
73
75
  }
74
76
  });
75
77
  //#endregion
76
- export { openApiDocument };
78
+ export { apiTitle, openApiDocument };
package/dist/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.67.3";
2
+ var version = "0.67.5";
3
3
  //#endregion
4
4
  export { version };
@@ -0,0 +1,9 @@
1
+ //#region src/request-app-url.ts
2
+ /**
3
+ * The app's page at `path`, which starts with `/`, on the origin of `requestURL`: a URL Better Auth resolved for the
4
+ * request (`ctx.context.baseURL`), on the request's host when that is one of the app's origins and on `baseURL`'s
5
+ * otherwise. Only its origin counts, so Better Auth's base path, such as `/api/auth`, never reaches the page.
6
+ */
7
+ const requestAppUrl = (requestURL, path) => new URL(path, requestURL).href;
8
+ //#endregion
9
+ export { requestAppUrl };
@@ -1,18 +1,21 @@
1
1
  import { requestAccess } from "../request-access.js";
2
- import { openApiDocument } from "../openapi/document.js";
2
+ import { apiTitle, openApiDocument } from "../openapi/document.js";
3
3
  import { Hono } from "hono";
4
4
  import { Scalar } from "@scalar/hono-api-reference";
5
5
  //#region src/routes/docs.ts
6
- /** The OpenAPI document and the Scalar reference. Both need a token: the document lists what the caller may see and do. */
7
- const docsRoutes = (deps) => {
6
+ /**
7
+ * The OpenAPI document and the Scalar reference, both titled with the app's name. Both need a token: the document lists
8
+ * what the caller may see and do.
9
+ */
10
+ const docsRoutes = (deps, appName) => {
8
11
  const app = new Hono();
9
12
  app.get("/openapi.json", async (c) => {
10
13
  const visible = (await Promise.all(deps.registry.entries.map((entry) => requestAccess(deps, entry, c.get("session"))))).filter((access) => Object.values(access.resolved.operations).some(Boolean));
11
- return c.json(openApiDocument(visible, deps.basePath));
14
+ return c.json(openApiDocument(visible, deps.basePath, appName));
12
15
  });
13
16
  app.get("/docs", Scalar({
14
17
  url: "openapi.json",
15
- pageTitle: "Protobase API"
18
+ pageTitle: apiTitle(appName)
16
19
  }));
17
20
  return app;
18
21
  };
@@ -0,0 +1,15 @@
1
+ //#region src/runs-on-note.ts
2
+ const runsOnNoteVariable = "PROTOBASE_RUNS_ON_NOTE";
3
+ /**
4
+ * Whether the sign-in page ends on the "Runs on Protobase" note: the host turns it on with `PROTOBASE_RUNS_ON_NOTE=true`,
5
+ * so an app's repository cannot turn it off. Unset or empty, there is no note; any value but `true` or `false` stops the
6
+ * server at startup.
7
+ */
8
+ const readRunsOnNote = (env) => {
9
+ const value = env[runsOnNoteVariable];
10
+ if (!value) return false;
11
+ if (value !== "true" && value !== "false") throw new Error(`${runsOnNoteVariable} must be true or false, not "${value}"`);
12
+ return value === "true";
13
+ };
14
+ //#endregion
15
+ export { readRunsOnNote, runsOnNoteVariable };
@@ -1,6 +1,8 @@
1
1
  import { CheckedDefinition } from "./check-definition.js";
2
2
  import { TableIndexes } from "@protobase/query";
3
3
  //#region src/user-tables/definition-resource.d.ts
4
+ /** The most characters a text field takes: four bytes each at most, it always fits the entry of its btree index. */
5
+ export declare const maxTextLength = 500;
4
6
  /**
5
7
  * The resource and view of a checked definition over `user_tables.<name>`, with the indexes its table has (none before
6
8
  * they are read): built with the schema builders, so it is checked, accessed and guarded as a resource of the config.
@@ -3,6 +3,8 @@ import { f, resource, view } from "@protobase/schema";
3
3
  import { indexServes } from "@protobase/query";
4
4
  //#region src/user-tables/definition-resource.ts
5
5
  const admins = ({ user }) => user?.roles?.includes("admin") ?? false;
6
+ /** The most characters a text field takes: four bytes each at most, it always fits the entry of its btree index. */
7
+ const maxTextLength = 500;
6
8
  const builders = {
7
9
  text: () => f.text().max(500),
8
10
  long_text: () => f.text(),
@@ -59,4 +61,4 @@ const definitionResource = (definition, indexes = {
59
61
  };
60
62
  };
61
63
  //#endregion
62
- export { definitionResource };
64
+ export { definitionResource, maxTextLength };
@@ -0,0 +1,12 @@
1
+ import { ResourceModel } from "@protobase/schema";
2
+ import { Db } from "@protobase/query";
3
+ //#region src/user-tables/owned-definitions.d.ts
4
+ /** The user tables a resource in code owns, as `protobase eject` writes one: over `user_tables.<name>`, with that name. */
5
+ export declare const ownedTableNames: (models: readonly ResourceModel[]) => string[];
6
+ /**
7
+ * The delete of the definitions of the user tables a resource in code owns, with their fields; their tables and rows
8
+ * stay. `undefined` when no such definition is left. `protobase migration` writes it once the code that owns them has
9
+ * deployed, so a definition goes in a later deploy than the one that stopped reading it.
10
+ */
11
+ export declare const ownedDefinitionsMigration: (db: Db, models: readonly ResourceModel[]) => Promise<string | undefined>;
12
+ //#endregion
@@ -0,0 +1,22 @@
1
+ import { definitionsSchema } from "./names.js";
2
+ import { sql } from "kysely";
3
+ //#region src/user-tables/owned-definitions.ts
4
+ /** The user tables a resource in code owns, as `protobase eject` writes one: over `user_tables.<name>`, with that name. */
5
+ const ownedTableNames = (models) => models.filter((model) => model.table.schema === "user_tables" && model.table.name === model.name).map((model) => model.name);
6
+ const literal = (text) => `'${text.replaceAll("'", "''")}'`;
7
+ /**
8
+ * The delete of the definitions of the user tables a resource in code owns, with their fields; their tables and rows
9
+ * stay. `undefined` when no such definition is left. `protobase migration` writes it once the code that owns them has
10
+ * deployed, so a definition goes in a later deploy than the one that stopped reading it.
11
+ */
12
+ const ownedDefinitionsMigration = async (db, models) => {
13
+ const owned = ownedTableNames(models);
14
+ if (owned.length === 0) return;
15
+ const { rows: found } = await sql`select to_regclass(${`${definitionsSchema}.tables`}) is not null as found`.execute(db);
16
+ if (!found[0].found) return;
17
+ const { rows } = await sql`select name from ${sql.table(`${definitionsSchema}.tables`)} where name = any(${owned}) order by name`.execute(db);
18
+ if (rows.length === 0) return;
19
+ return `delete from ${definitionsSchema}.tables where name in (${rows.map((row) => literal(row.name)).join(", ")});`;
20
+ };
21
+ //#endregion
22
+ export { ownedDefinitionsMigration, ownedTableNames };
@@ -1,10 +1,15 @@
1
+ import { CheckedDefinition } from "./check-definition.js";
1
2
  import { definitionResource } from "./definition-resource.js";
2
3
  import { Db } from "@protobase/query";
3
4
  //#region src/user-tables/user-table-resources.d.ts
4
- /** What the stored definitions serve: a resource and view for each that fits the database, and why each other one is left out. */
5
+ /**
6
+ * What the stored definitions serve: a resource and view for each that fits the database, the definitions they are
7
+ * built from, as `protobase eject` writes them into code, and why each other one is left out.
8
+ */
5
9
  export type UserTables = {
6
10
  resources: Array<ReturnType<typeof definitionResource>['resource']>;
7
11
  views: Array<ReturnType<typeof definitionResource>['view']>;
12
+ definitions: CheckedDefinition[];
8
13
  problems: string[];
9
14
  };
10
15
  /**
@@ -13,6 +13,7 @@ const userTableResources = async (db) => {
13
13
  const tables = {
14
14
  resources: [],
15
15
  views: [],
16
+ definitions: [],
16
17
  problems: []
17
18
  };
18
19
  for (const stored of definitions) {
@@ -25,6 +26,7 @@ const userTableResources = async (db) => {
25
26
  const { resource, view } = definitionResource(checked.definition, indexes);
26
27
  tables.resources.push(resource);
27
28
  tables.views.push(view);
29
+ tables.definitions.push(checked.definition);
28
30
  }
29
31
  return tables;
30
32
  };
@@ -1,7 +1,7 @@
1
1
  import { pngIcons } from "@protobase/schema/png-icons";
2
2
  //#region src/web-app/app-icons.d.ts
3
3
  export type PngIcon = keyof typeof pngIcons;
4
- /** The icons a project has of its own: `favicon` when the favicon is its own rather than Protobase's, and its PNGs. */
4
+ /** The icons a project has of its own: `favicon` when the favicon is its own rather than the neutral mark, and its PNGs. */
5
5
  export type AppIcons = {
6
6
  favicon: boolean;
7
7
  png: PngIcon[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.67.3",
3
+ "version": "0.67.5",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -37,15 +37,16 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@better-auth/cimd": "^1.7.12",
40
+ "@better-auth/core": "^1.7.12",
40
41
  "@better-auth/mcp": "^1.7.12",
41
42
  "@better-auth/oauth-provider": "^1.7.12",
42
43
  "@better-auth/passkey": "^1.7.12",
43
44
  "@better-auth/sso": "^1.7.12",
44
45
  "@livekit/protocol": "1.53.1",
45
46
  "@modelcontextprotocol/server": "^2.3.1",
46
- "@protobase/layout": "0.67.3",
47
- "@protobase/query": "0.67.3",
48
- "@protobase/schema": "0.67.3",
47
+ "@protobase/layout": "0.67.5",
48
+ "@protobase/query": "0.67.5",
49
+ "@protobase/schema": "0.67.5",
49
50
  "@react-email/render": "^2.1.0",
50
51
  "@react-pdf/primitives": "^4.4.0",
51
52
  "@react-pdf/renderer": "^4.9.0",