@protobase/server 0.22.11 → 0.22.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ //#region src/background-work.d.ts
2
+ /**
3
+ * Runs `work` as background work: function calls and jobs, as opposed to page and API requests. A pool that knows,
4
+ * such as the runtime's, keeps a connection free for requests however many connections background work holds.
5
+ */
6
+ export declare const runInBackground: <T>(work: () => T) => T;
7
+ /** Whether the caller runs inside `runInBackground`. */
8
+ export declare const isBackgroundWork: () => boolean;
9
+ //#endregion
@@ -0,0 +1,12 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ //#region src/background-work.ts
3
+ const background = new AsyncLocalStorage();
4
+ /**
5
+ * Runs `work` as background work: function calls and jobs, as opposed to page and API requests. A pool that knows,
6
+ * such as the runtime's, keeps a connection free for requests however many connections background work holds.
7
+ */
8
+ const runInBackground = (work) => background.run(true, work);
9
+ /** Whether the caller runs inside `runInBackground`. */
10
+ const isBackgroundWork = () => background.getStore() === true;
11
+ //#endregion
12
+ export { isBackgroundWork, runInBackground };
@@ -24,6 +24,7 @@ const queryProblem = (error) => {
24
24
  };
25
25
  const isDatabaseError = (error) => error instanceof Error && /^[0-9A-Z]{5}$/.test(String(error.code));
26
26
  const databaseProblem = (error) => {
27
+ if (error.code === "25006") return new HttpProblem(503, "read-only", "Service Unavailable", "The app is read-only while it is being updated", {}, { "Retry-After": "5" });
27
28
  if (error.code === "57014") return new HttpProblem(504, "statement-timeout", "Gateway Timeout", "The query exceeded the statement timeout");
28
29
  if (error.code === "23505") return new HttpProblem(409, "conflict", "Conflict", "A record with the same unique value already exists");
29
30
  if (error.code === "23503") return new HttpProblem(409, "conflict", "Conflict", "The record points at, or is pointed at by, another record");
@@ -1,5 +1,6 @@
1
1
  import { forbidden, notFound } from "../problem.js";
2
2
  import { invokeFunction } from "./define-function.js";
3
+ import { runInBackground } from "../background-work.js";
3
4
  import { Hono } from "hono";
4
5
  import { cors } from "hono/cors";
5
6
  //#region src/functions/routes.ts
@@ -14,7 +15,8 @@ const requireRoles = (name, session, roles) => {
14
15
  };
15
16
  /**
16
17
  * Every function at `<basePath>/<name>` and below, any method. A protected function authenticates the request first, so
17
- * a call without a valid token is the authenticator's 401 problem; a public one gets the caller only when it asks.
18
+ * a call without a valid token is the authenticator's 401 problem; a public one gets the caller only when it asks. Each
19
+ * call runs as background work, so calls that hold the database for long leave a connection to page requests.
18
20
  */
19
21
  const functionRoutes = ({ basePath, functions, authenticate, db, records, onError }) => {
20
22
  const app = new Hono().basePath(basePath);
@@ -30,7 +32,7 @@ const functionRoutes = ({ basePath, functions, authenticate, db, records, onErro
30
32
  const prefix = `${basePath}/${name}`;
31
33
  const { options } = fn;
32
34
  if (options.cors) app.use(`/${name}/*`, cors(options.cors));
33
- app.all(`/${name}/*`, async (c) => {
35
+ app.all(`/${name}/*`, (c) => runInBackground(async () => {
34
36
  const request = relativeRequest(c.req.raw, prefix);
35
37
  if (options.public) {
36
38
  let caller;
@@ -49,7 +51,7 @@ const functionRoutes = ({ basePath, functions, authenticate, db, records, onErro
49
51
  caller: async () => caller
50
52
  };
51
53
  return invokeFunction(name, fn, request, context);
52
- });
54
+ }));
53
55
  }
54
56
  app.all("/*", (c) => {
55
57
  throw notFound(`There is no function at ${c.req.path}`);
package/dist/index.d.ts CHANGED
@@ -41,6 +41,7 @@ import { RuntimeOptions, runtimeUrl, runtimeVariable, seesRuntime } from "./runt
41
41
  import { AdminOptions } from "./admin-options.js";
42
42
  import { CreateAdminInput, createAdmin } from "./create-admin.js";
43
43
  import { handleDroppedConnections } from "./dropped-connections.js";
44
+ import { isBackgroundWork, runInBackground } from "./background-work.js";
44
45
  import { checkViewQueries } from "./check-view-queries.js";
45
46
  import { ProjectConfig, defineConfig, mergeConfig } from "./project-config.js";
46
47
  import { consoleAuditQueue } from "./audit/console-queue.js";
@@ -91,4 +92,4 @@ import { FatalJobError } from "./jobs/run-job.js";
91
92
  import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/runtime.js";
92
93
  import { jobsDrainApp } from "./jobs/drain-route.js";
93
94
  import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
94
- export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, 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 FunctionSource, type HistoryOptions, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type MemberInput, MissingCredentials, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, 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 Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
95
+ export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, 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 FunctionSource, type HistoryOptions, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type MemberInput, MissingCredentials, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, 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 Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
package/dist/index.js CHANGED
@@ -38,6 +38,7 @@ import { storageCleanupSchedule } from "./files/cleanup-schedule.js";
38
38
  import { limitedFileStore } from "./files/limits.js";
39
39
  import { localFileStore, localFiles } from "./files/local-files.js";
40
40
  import { s3FileStore, s3Files } from "./files/s3-files.js";
41
+ import { isBackgroundWork, runInBackground } from "./background-work.js";
41
42
  import { mapSettings, mapStyleUrl, mapStyleVariable } from "./maps/map-settings.js";
42
43
  import { beforeSignInPluginsVariable, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable } from "./plugins/plugin-settings.js";
43
44
  import { runtimeUrl, runtimeVariable, seesRuntime } from "./runtime/runtime-settings.js";
@@ -68,4 +69,4 @@ import { aspectRatio, fileSize, fileType, imageSize, processor } from "./files/p
68
69
  import { defineEmail } from "./mail/define-email.js";
69
70
  import { startJobs } from "./jobs/runtime.js";
70
71
  import { jobsDrainApp } from "./jobs/drain-route.js";
71
- export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
72
+ export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
@@ -3,6 +3,7 @@ import { jobsSchema } from "./schema.js";
3
3
  import "./schedule.js";
4
4
  import { runJob, validatePayload } from "./run-job.js";
5
5
  import { platformMailer } from "../mail/platform-mailer.js";
6
+ import { runInBackground } from "../background-work.js";
6
7
  import { jobsDatabase } from "./database.js";
7
8
  import { queueOptions, queueSettingsDiffer, sendOptions } from "./options.js";
8
9
  import { createSchedules } from "./schedules.js";
@@ -55,11 +56,11 @@ const startJobs = async ({ db, jobs, work = true, pollSeconds = 2, shutdownSecon
55
56
  pollingIntervalSeconds: pollSeconds,
56
57
  includeMetadata: true,
57
58
  perJobResults: true
58
- }, async ([job]) => {
59
+ }, async ([job]) => runInBackground(async () => {
59
60
  const current = definitions.get(definition.name) ?? definition;
60
61
  if (current.options.schedule !== void 0 && job.singletonKey === "protobase.schedule") await schedules.following(current, job.startAfter);
61
62
  return [await runJob(current, job, db, mail)];
62
- });
63
+ }));
63
64
  workers.set(definition.name, {
64
65
  id,
65
66
  concurrency
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.22.11",
3
+ "version": "0.22.13",
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": {
@@ -31,9 +31,9 @@
31
31
  "dependencies": {
32
32
  "@better-auth/passkey": "^1.7.7",
33
33
  "@better-auth/sso": "^1.7.7",
34
- "@protobase/layout": "0.22.11",
35
- "@protobase/query": "0.22.11",
36
- "@protobase/schema": "0.22.11",
34
+ "@protobase/layout": "0.22.13",
35
+ "@protobase/query": "0.22.13",
36
+ "@protobase/schema": "0.22.13",
37
37
  "@react-email/render": "^2.1.0",
38
38
  "@scalar/hono-api-reference": "^0.12.10",
39
39
  "@sentry/core": "^11.7.0",