@protobase/server 0.67.12 → 0.68.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.
- package/dist/batch/run-batch.d.ts +1 -0
- package/dist/batch/run-batch.js +6 -4
- package/dist/check-views.js +6 -0
- package/dist/create-admin.js +7 -4
- package/dist/idempotency.d.ts +1 -0
- package/dist/idempotency.js +12 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/mcp/mcp-tools.d.ts +4 -2
- package/dist/mcp/mcp-tools.js +9 -3
- package/dist/package.js +1 -1
- package/dist/user-tables/admin-user-tables.js +9 -4
- package/dist/user-tables/definitions-views.js +93 -0
- package/dist/view-access.js +1 -0
- package/dist/webhooks/attempt.js +2 -2
- package/dist/webhooks/table/address-check.js +1 -1
- package/dist/webhooks/table/webhook-table.js +1 -1
- package/dist/webhooks/webhooks.js +2 -1
- package/dist/workflows/effects-store.js +18 -0
- package/dist/workflows/mcp/workflow-instructions.js +1 -1
- package/dist/workflows/mcp/workflow-read-tools.d.ts +11 -1
- package/dist/workflows/mcp/workflow-read-tools.js +14 -19
- package/dist/workflows/options.d.ts +6 -0
- package/dist/workflows/plugin-fetch.js +40 -0
- package/dist/workflows/plugin-records.d.ts +10 -0
- package/dist/workflows/plugin-records.js +120 -0
- package/dist/workflows/plugin-services.d.ts +13 -0
- package/dist/workflows/plugin-services.js +32 -0
- package/dist/workflows/ready/ready-check.js +62 -0
- package/dist/workflows/ready/ready-start.js +104 -0
- package/dist/workflows/ready/ready-when.js +101 -0
- package/dist/workflows/run-files.js +3 -7
- package/dist/workflows/save-hook.js +15 -13
- package/dist/workflows/schema-sql.js +65 -3
- package/dist/workflows/schema.d.ts +2 -2
- package/dist/workflows/schema.js +6 -2
- package/dist/workflows/start-workflow.d.ts +3 -1
- package/dist/workflows/start-workflow.js +3 -3
- package/dist/workflows/triggers/trigger-jobs.js +114 -0
- package/dist/workflows/triggers/trigger-row.js +36 -0
- package/dist/workflows/triggers/trigger-sync.js +48 -0
- package/dist/workflows/workflow-engine.js +17 -5
- package/dist/workflows/workflow-types-route.js +22 -0
- package/dist/workflows/workflow-types.d.ts +22 -0
- package/dist/workflows/workflow-types.js +63 -0
- package/dist/workflows/workflows-module.d.ts +25 -1
- package/package.json +6 -5
- package/dist/workflows/http-step.js +0 -103
- package/dist/workflows/mail-step.js +0 -58
- package/dist/workflows/mcp/type-catalog.js +0 -144
- package/dist/workflows/piece-step.js +0 -11
- package/dist/workflows/records-step.js +0 -114
- package/dist/workflows/step-types.js +0 -27
package/dist/batch/run-batch.js
CHANGED
|
@@ -3,6 +3,7 @@ import { requestAccess } from "../request-access.js";
|
|
|
3
3
|
import { writeTransaction } from "../transactions.js";
|
|
4
4
|
import { actorSettings, wakeDispatch } from "../changes/actor.js";
|
|
5
5
|
import { problemOf } from "../error-handler.js";
|
|
6
|
+
import { once } from "../idempotency.js";
|
|
6
7
|
import { scheduleRemovedFiles } from "../files/attach.js";
|
|
7
8
|
import { keyOf } from "../write-shared.js";
|
|
8
9
|
import { checkBeforeWrite, writeIn } from "../write-pipeline.js";
|
|
@@ -27,9 +28,10 @@ const atOperation = (error, index, operation) => {
|
|
|
27
28
|
/**
|
|
28
29
|
* Runs the operations in order inside ONE transaction, each through the normal write pipeline (validation, access with row
|
|
29
30
|
* filters and record-level rules, tenant, ETags, hooks), after the checks that come before it. Any failure rolls the
|
|
30
|
-
* whole batch back and names the failing operation.
|
|
31
|
+
* whole batch back and names the failing operation. With `idempotency`, a batch repeated with its key writes nothing and
|
|
32
|
+
* returns the results of the one that committed.
|
|
31
33
|
*/
|
|
32
|
-
const runBatch = async (deps, session, operations) => {
|
|
34
|
+
const runBatch = async (deps, session, operations, idempotency) => {
|
|
33
35
|
const refs = operations.flatMap((operation) => operation.op === "create" && operation.ref ? [operation.ref] : []);
|
|
34
36
|
if (new Set(refs).size !== refs.length) throw badRequest("invalid-parameter", "Each create may use a ref name once");
|
|
35
37
|
const accesses = /* @__PURE__ */ new Map();
|
|
@@ -51,7 +53,7 @@ const runBatch = async (deps, session, operations) => {
|
|
|
51
53
|
});
|
|
52
54
|
}
|
|
53
55
|
const removed = [];
|
|
54
|
-
const written = await writeTransaction(deps.db, deps.statementTimeoutMs, async (
|
|
56
|
+
const written = await writeTransaction(deps.db, deps.statementTimeoutMs, (trx) => once(trx, idempotency, async () => {
|
|
55
57
|
const created = /* @__PURE__ */ new Map();
|
|
56
58
|
const results = [];
|
|
57
59
|
for (const [index, operation] of operations.entries()) try {
|
|
@@ -114,7 +116,7 @@ const runBatch = async (deps, session, operations) => {
|
|
|
114
116
|
throw atOperation(error, index, operation);
|
|
115
117
|
}
|
|
116
118
|
return results;
|
|
117
|
-
}, actorSettings(deps, session));
|
|
119
|
+
}), actorSettings(deps, session));
|
|
118
120
|
await scheduleRemovedFiles(deps, removed);
|
|
119
121
|
wakeDispatch(deps);
|
|
120
122
|
return written;
|
package/dist/check-views.js
CHANGED
|
@@ -69,6 +69,11 @@ const textHintErrors = (view, model) => Object.entries(view.fields).flatMap(([na
|
|
|
69
69
|
const format = hints.format !== void 0 && textFormats.has(hints.format) ? [`format('${hints.format}') of "${name}" needs a text field, not ${field.type}`] : [];
|
|
70
70
|
return [...textHints.filter((hint) => hints[hint]).map((hint) => `${hint} "${name}" needs a text field, not ${field.type}`), ...format];
|
|
71
71
|
});
|
|
72
|
+
const notOnCreateErrors = (view, model) => Object.entries(view.fields).flatMap(([name, hints]) => {
|
|
73
|
+
const field = model.fields[name];
|
|
74
|
+
if (!hints.notOnCreate || !field || field.nullable || field.default || field.readOnly) return [];
|
|
75
|
+
return [`notOnCreate "${name}" is a field a create needs: make it optional or give it a default`];
|
|
76
|
+
});
|
|
72
77
|
const linkErrors = (view, model, models, pages, createPages) => view.actions.flatMap(({ name, label, run }) => {
|
|
73
78
|
if (run?.kind !== "link") return [];
|
|
74
79
|
const error = linkActionError(label, run);
|
|
@@ -192,6 +197,7 @@ const checkViews = (registry, views, pages = [], fieldTypes = {}) => {
|
|
|
192
197
|
...valueLabelErrors(view, model),
|
|
193
198
|
...valueColorErrors(view, model),
|
|
194
199
|
...textHintErrors(view, model),
|
|
200
|
+
...notOnCreateErrors(view, model),
|
|
195
201
|
...numberHintErrors(view, model),
|
|
196
202
|
...listEditErrors(view, model),
|
|
197
203
|
...widgetErrors(view, model, fieldTypes),
|
package/dist/create-admin.js
CHANGED
|
@@ -60,6 +60,7 @@ import { createWebhooks } from "./webhooks/webhooks.js";
|
|
|
60
60
|
import { webhookTable } from "./webhooks/table/webhook-table.js";
|
|
61
61
|
import { subscriptionUrlCheck, subscriptionWriteCheck } from "./webhooks/table/validate-hook.js";
|
|
62
62
|
import { workflowEngine } from "./workflows/workflow-engine.js";
|
|
63
|
+
import { workflowTypesRoute } from "./workflows/workflow-types-route.js";
|
|
63
64
|
import { callsService } from "./calls/calls-service.js";
|
|
64
65
|
import { ringRoutes } from "./calls/ring-routes.js";
|
|
65
66
|
import { upgradeAuthenticator } from "./functions/upgrade-caller.js";
|
|
@@ -119,7 +120,7 @@ import { builtInResources } from "./built-in-resources.js";
|
|
|
119
120
|
import { adminUserTables } from "./user-tables/admin-user-tables.js";
|
|
120
121
|
import { Hono } from "hono";
|
|
121
122
|
import { accountPage, accountPageName, checkPages, settingsResources, withSettingsFields } from "@protobase/layout";
|
|
122
|
-
import { guestCallsPath, ringsPath, statusPath } from "@protobase/schema/internal";
|
|
123
|
+
import { guestCallsPath, ringsPath, statusPath, workflowTypesPath } from "@protobase/schema/internal";
|
|
123
124
|
import { getIP } from "better-auth/api";
|
|
124
125
|
//#region src/create-admin.ts
|
|
125
126
|
const declaredRoles = (auth, roles) => {
|
|
@@ -386,7 +387,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
|
|
|
386
387
|
sql: options.mcp !== false && options.mcp?.sql === true,
|
|
387
388
|
writes,
|
|
388
389
|
commented,
|
|
389
|
-
workflows:
|
|
390
|
+
...engine && { workflows: engine.types },
|
|
390
391
|
own: options.mcp !== false && options.mcp?.tools || []
|
|
391
392
|
});
|
|
392
393
|
const instructions = engine ? `${mcpInstructions}\n${workflowInstructions}` : mcpInstructions;
|
|
@@ -495,6 +496,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
|
|
|
495
496
|
if (auth) removeHistoryWithUsers(auth, history);
|
|
496
497
|
app.route(historyPath(systemPath), guarded((routes) => void routes.route("/", historyRoutes(history, auth?.origins ?? []))));
|
|
497
498
|
}
|
|
499
|
+
if (engine) app.route(workflowTypesPath(systemPath), guarded((routes) => void routes.route("/", workflowTypesRoute(deps, engine.types.types))));
|
|
498
500
|
if (statusTables) app.route(statusPath(systemPath), guarded((routes) => void routes.route("/", statusRoutes(db, statusTables))));
|
|
499
501
|
if (deps.calls) app.route(ringsPath(systemPath), guarded((routes) => void routes.route("/", ringRoutes(deps.calls))));
|
|
500
502
|
if (deps.calls && auth) {
|
|
@@ -565,7 +567,8 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
|
|
|
565
567
|
channels,
|
|
566
568
|
schema: changes,
|
|
567
569
|
log: (line) => console.log(line),
|
|
568
|
-
...table && { table }
|
|
570
|
+
...table && { table },
|
|
571
|
+
...engine && { onChanges: engine.onChanges }
|
|
569
572
|
});
|
|
570
573
|
const prune = () => startRealtimePrune({
|
|
571
574
|
db,
|
|
@@ -580,7 +583,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], userTables
|
|
|
580
583
|
metaPath: `${deps.systemPath}/meta`,
|
|
581
584
|
jobs: [
|
|
582
585
|
...webhooks.jobs,
|
|
583
|
-
...engine ?
|
|
586
|
+
...engine ? engine.jobs : [],
|
|
584
587
|
...withHistory && days !== void 0 ? [pruneHistoryJob(changes, days)] : [],
|
|
585
588
|
...mentions ? [mentions] : [],
|
|
586
589
|
...fill ? [fill] : [],
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import { Db } from "@protobase/query";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/idempotency.ts
|
|
2
|
+
/** Runs `write` in `trx` once per key: a repeat returns the result the first write kept, as JSON keeps it. */
|
|
3
|
+
const once = async (trx, idempotency, write) => {
|
|
4
|
+
if (!idempotency) return write();
|
|
5
|
+
const first = await idempotency.store.claim(trx, idempotency.key);
|
|
6
|
+
if (first) return first.result;
|
|
7
|
+
const result = await write();
|
|
8
|
+
await idempotency.store.keep(trx, idempotency.key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { once };
|
package/dist/index.d.ts
CHANGED
|
@@ -151,8 +151,9 @@ import { McpApprovals, mcpApprovals } from "./mcp/mcp-approval-store.js";
|
|
|
151
151
|
import { McpServerInput, mcpServer } from "./mcp/mcp-server.js";
|
|
152
152
|
import { mcpIcons } from "./web-app/mcp-icons.js";
|
|
153
153
|
import { mcpInstructions } from "./mcp/mcp-instructions.js";
|
|
154
|
+
import { WorkflowCatalog, workflowReadTools } from "./workflows/mcp/workflow-read-tools.js";
|
|
154
155
|
import { McpToolsInput, mcpTools } from "./mcp/mcp-tools.js";
|
|
155
|
-
import {
|
|
156
|
+
import { WorkflowTypes, workflowTypes } from "./workflows/workflow-types.js";
|
|
156
157
|
import { workflowWriteTools } from "./workflows/mcp/workflow-write-tools.js";
|
|
157
158
|
import { workflowInstructions } from "./workflows/mcp/workflow-instructions.js";
|
|
158
159
|
import { McpGateInput, mcpGate, sessionOf } from "./mcp/mcp-gate.js";
|
|
@@ -195,4 +196,4 @@ import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/ru
|
|
|
195
196
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
196
197
|
import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
|
|
197
198
|
import { AdminAuth, CreateAuthOptions, UserCreatedHook, normalizeRoles } from "./better-auth/create-auth.js";
|
|
198
|
-
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 StartWorkflowOptions, 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 WorkflowsOptions, 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, checkWorkflowsSchema, 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, startWorkflow, 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, workflowInstructions, workflowReadTools, workflowWriteTools, workflowsMigration, writeRecordTools };
|
|
199
|
+
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 StartWorkflowOptions, 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 WorkflowCatalog, type WorkflowTypes, type WorkflowsOptions, 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, checkWorkflowsSchema, 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, startWorkflow, 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, workflowInstructions, workflowReadTools, workflowTypes, workflowWriteTools, workflowsMigration, writeRecordTools };
|
package/dist/index.js
CHANGED
|
@@ -68,6 +68,8 @@ import { recordOf, resourceChange } from "./changes/resource-change.js";
|
|
|
68
68
|
import { defineFunction } from "./functions/define-function.js";
|
|
69
69
|
import { newWebhookSecret } from "./webhooks/standard-webhooks.js";
|
|
70
70
|
import { subscription } from "./webhooks/subscription.js";
|
|
71
|
+
import { startWorkflow } from "./workflows/start-workflow.js";
|
|
72
|
+
import { workflowTypes } from "./workflows/workflow-types.js";
|
|
71
73
|
import { historyIdPattern, historyLimits } from "./notifications/history.js";
|
|
72
74
|
import { PushMessageError, maxTtlSeconds, pushMessage, urgencies } from "./notifications/message.js";
|
|
73
75
|
import { NotificationSendError, maxMessageBytes, maxRecipients } from "./notifications/send-input.js";
|
|
@@ -117,7 +119,6 @@ import { checkResourcesOutsideAuthStore } from "./better-auth/store/resources-ou
|
|
|
117
119
|
import { checkComputed, computedMigration } from "./computed/computed-schema.js";
|
|
118
120
|
import { checkWebhooksSchema, webhooksMigration } from "./webhooks/table/schema.js";
|
|
119
121
|
import { checkWorkflowsSchema, workflowsMigration } from "./workflows/schema.js";
|
|
120
|
-
import { startWorkflow } from "./workflows/start-workflow.js";
|
|
121
122
|
import { checkUserTablesSchema, userTablesMigration } from "./user-tables/schema.js";
|
|
122
123
|
import { ownedDefinitionsMigration } from "./user-tables/owned-definitions.js";
|
|
123
124
|
import { userTableResources } from "./user-tables/user-table-resources.js";
|
|
@@ -145,4 +146,4 @@ import { defineEmail } from "./mail/define-email.js";
|
|
|
145
146
|
import { definePdf } from "./pdf/define-pdf.js";
|
|
146
147
|
import { startJobs } from "./jobs/runtime.js";
|
|
147
148
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
148
|
-
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, checkWorkflowsSchema, 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, startWorkflow, 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, workflowInstructions, workflowReadTools, workflowWriteTools, workflowsMigration, writeRecordTools };
|
|
149
|
+
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, checkWorkflowsSchema, 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, startWorkflow, 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, workflowInstructions, workflowReadTools, workflowTypes, workflowWriteTools, workflowsMigration, writeRecordTools };
|
package/dist/mcp/mcp-tools.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Session } from "../types.js";
|
|
2
2
|
import { AssistantTool } from "../assistant/tools.js";
|
|
3
3
|
import { McpWrites } from "./mcp-writes.js";
|
|
4
|
+
import { WorkflowCatalog } from "../workflows/mcp/workflow-read-tools.js";
|
|
4
5
|
import { Db } from "@protobase/query";
|
|
5
6
|
//#region src/mcp/mcp-tools.d.ts
|
|
6
7
|
export type McpToolsInput = {
|
|
@@ -20,9 +21,10 @@ export type McpToolsInput = {
|
|
|
20
21
|
commented?: string[];
|
|
21
22
|
/**
|
|
22
23
|
* Offers the workflow tools, for an app with `workflows`: reading workflows, their types and runs, and checking
|
|
23
|
-
* definitions; with writes on, `create_workflow`, `update_workflow` and `run_workflow` too.
|
|
24
|
+
* definitions against the app's types; with writes on, `create_workflow`, `update_workflow` and `run_workflow` too.
|
|
25
|
+
* Off by default.
|
|
24
26
|
*/
|
|
25
|
-
workflows?:
|
|
27
|
+
workflows?: WorkflowCatalog;
|
|
26
28
|
/** The app's own tools, offered to every caller after the built-in ones. */
|
|
27
29
|
own?: AssistantTool[];
|
|
28
30
|
};
|
package/dist/mcp/mcp-tools.js
CHANGED
|
@@ -14,7 +14,13 @@ const builtInNames = (db) => new Set([
|
|
|
14
14
|
...writeTools({}),
|
|
15
15
|
...commentTools({ commented: ["comments"] }, {}),
|
|
16
16
|
readOnlyQueryTool(db),
|
|
17
|
-
...workflowReadTools(
|
|
17
|
+
...workflowReadTools({
|
|
18
|
+
types: [],
|
|
19
|
+
checkWith: () => ({
|
|
20
|
+
resources: [],
|
|
21
|
+
triggers: {}
|
|
22
|
+
})
|
|
23
|
+
}),
|
|
18
24
|
...workflowWriteTools()
|
|
19
25
|
].map((tool) => tool.name));
|
|
20
26
|
/** The app's own tools; one whose name is taken twice, or by a built-in tool, stops the server at startup. */
|
|
@@ -31,13 +37,13 @@ const checkedOwnTools = (db, own) => {
|
|
|
31
37
|
* tools are built once and only chosen per session: the MCP server compiles each tool's schema, and a schema object made
|
|
32
38
|
* per request would be compiled again.
|
|
33
39
|
*/
|
|
34
|
-
const mcpTools = ({ db, sql, writes, commented = [], workflows
|
|
40
|
+
const mcpTools = ({ db, sql, writes, commented = [], workflows, own = [] }) => {
|
|
35
41
|
const ownTools = checkedOwnTools(db, own);
|
|
36
42
|
const read = readRecordTools();
|
|
37
43
|
const limits = writes === false ? false : writes === true || !writes.resources ? {} : { resources: writes.resources };
|
|
38
44
|
const write = limits === false ? [] : writeTools(limits);
|
|
39
45
|
const comments = commentTools({ commented }, limits);
|
|
40
|
-
const flows = workflows ? [...workflowReadTools(), ...limits === false ? [] : workflowWriteTools(limits)] : [];
|
|
46
|
+
const flows = workflows ? [...workflowReadTools(workflows), ...limits === false ? [] : workflowWriteTools(limits)] : [];
|
|
41
47
|
const query = sql ? [readOnlyQueryTool(db)] : [];
|
|
42
48
|
return (session) => [
|
|
43
49
|
...read,
|
package/dist/package.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { definitionsResources, fieldsResourceName, tablesResourceName } from "./definitions-resources.js";
|
|
2
2
|
import { definitionsHook } from "./definitions-hook.js";
|
|
3
|
+
import { fieldsView, tablesView } from "./definitions-views.js";
|
|
3
4
|
import { servedUserTables } from "./served-user-tables.js";
|
|
4
5
|
//#region src/user-tables/admin-user-tables.ts
|
|
5
6
|
/**
|
|
6
7
|
* What the tables users add bring to the admin, with `userTables` on: the resources over their definitions, through
|
|
7
|
-
* which they are created, each user table a name in code (`codeNames`, the
|
|
8
|
-
* hook that creates their tables and columns. Without `tables`, nothing.
|
|
9
|
-
* to the organization it was made in (`definitionsResources`).
|
|
8
|
+
* which they are created, with the views the admin app makes them in, each user table a name in code (`codeNames`, the
|
|
9
|
+
* app's and Protobase's) does not take, and the hook that creates their tables and columns. Without `tables`, nothing.
|
|
10
|
+
* With `organizations`, each definition belongs to the organization it was made in (`definitionsResources`).
|
|
10
11
|
*/
|
|
11
12
|
const adminUserTables = (tables, codeNames, roles, organizations = false) => {
|
|
12
13
|
if (!tables) return {
|
|
@@ -31,7 +32,11 @@ const adminUserTables = (tables, codeNames, roles, organizations = false) => {
|
|
|
31
32
|
definitions.fields,
|
|
32
33
|
...served.resources
|
|
33
34
|
],
|
|
34
|
-
views:
|
|
35
|
+
views: [
|
|
36
|
+
tablesView,
|
|
37
|
+
fieldsView,
|
|
38
|
+
...served.views
|
|
39
|
+
],
|
|
35
40
|
hooks: [definitionsHook(codeNames)],
|
|
36
41
|
warnings: served.warnings
|
|
37
42
|
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { fieldsResourceName, tablesResourceName } from "./definitions-resources.js";
|
|
2
|
+
import { l, view } from "@protobase/schema";
|
|
3
|
+
//#region src/user-tables/definitions-views.ts
|
|
4
|
+
/** What each field type is called in the admin app; the UI's locale files translate them. */
|
|
5
|
+
const fieldTypeLabels = {
|
|
6
|
+
text: "Text",
|
|
7
|
+
long_text: "Long text",
|
|
8
|
+
integer: "Whole number",
|
|
9
|
+
decimal: "Decimal number",
|
|
10
|
+
boolean: "Yes or no",
|
|
11
|
+
date: "Date",
|
|
12
|
+
timestamp: "Date and time",
|
|
13
|
+
json: "JSON"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The tables list of the admin app, for whoever may make tables: a table's page has its fields, a link to add one and a
|
|
17
|
+
* link to the table's own list, which shows once the app serves it. The title field is set once its field exists.
|
|
18
|
+
*/
|
|
19
|
+
const tablesView = view(tablesResourceName).names({
|
|
20
|
+
singular: "Table",
|
|
21
|
+
plural: "Tables"
|
|
22
|
+
}).title((r) => r.plural_label).help("The tables people add to the app. Open one to give it fields or to go to its records.").nav({
|
|
23
|
+
creatorsOnly: true,
|
|
24
|
+
order: 0
|
|
25
|
+
}).fields((r) => ({
|
|
26
|
+
name: r.name.label("Name").format("code").help("Its address and the name of its database table: lowercase letters, digits and _, starting with a letter. It cannot change later."),
|
|
27
|
+
plural_label: r.plural_label.label("Plural label").help("Its name in the sidebar and above its list, such as Notes."),
|
|
28
|
+
singular_label: r.singular_label.label("Singular label").help("What one record is called, such as Note."),
|
|
29
|
+
title_field: r.title_field.label("Title field").notOnCreate().help("The name of the text field that titles each record and that search looks in.")
|
|
30
|
+
})).list((r) => ({
|
|
31
|
+
columns: [r.plural_label, r.name],
|
|
32
|
+
sort: [[r.name, "asc"]]
|
|
33
|
+
})).layout((r) => [l.section("Table", [
|
|
34
|
+
r.plural_label,
|
|
35
|
+
r.singular_label,
|
|
36
|
+
r.name,
|
|
37
|
+
r.title_field
|
|
38
|
+
]), l.related("Fields", {
|
|
39
|
+
resource: fieldsResourceName,
|
|
40
|
+
field: "table_id",
|
|
41
|
+
columns: [
|
|
42
|
+
"label",
|
|
43
|
+
"name",
|
|
44
|
+
"type"
|
|
45
|
+
],
|
|
46
|
+
sort: "position",
|
|
47
|
+
empty: "No fields yet."
|
|
48
|
+
})]).actions((a) => [a.link("open_table", {
|
|
49
|
+
label: "Open table",
|
|
50
|
+
icon: "table",
|
|
51
|
+
to: {
|
|
52
|
+
kind: "list",
|
|
53
|
+
resource: "{table_name}"
|
|
54
|
+
}
|
|
55
|
+
}), a.link("add_field", {
|
|
56
|
+
label: "Add field",
|
|
57
|
+
icon: "plus",
|
|
58
|
+
to: {
|
|
59
|
+
kind: "create",
|
|
60
|
+
resource: fieldsResourceName,
|
|
61
|
+
values: { table_id: "{id}" }
|
|
62
|
+
}
|
|
63
|
+
})]);
|
|
64
|
+
/** A table's fields, reached from its page; a field users add is always optional, so its form leaves that out. */
|
|
65
|
+
const fieldsView = view(fieldsResourceName).names({
|
|
66
|
+
singular: "Field",
|
|
67
|
+
plural: "Fields"
|
|
68
|
+
}).title((r) => r.label).nav({ hidden: true }).fields((r) => ({
|
|
69
|
+
table_id: r.table_id.label("Table"),
|
|
70
|
+
label: r.label.label("Label").help("What the field is called on screen."),
|
|
71
|
+
name: r.name.label("Name").format("code").help("Its name in the API and its database column: lowercase letters, digits and _, starting with a letter. It cannot change later."),
|
|
72
|
+
type: r.type.label("Type").valueLabels(fieldTypeLabels).help("What it holds. It cannot change later."),
|
|
73
|
+
position: r.position.label("Position").help("Where it sits among the fields of its table, 1 the first."),
|
|
74
|
+
precision: r.precision.label("Digits").help("For a decimal number only: how many digits it holds in all, from 1 to 1000."),
|
|
75
|
+
scale: r.scale.label("Decimals").help("For a decimal number only: how many of those digits come after the decimal point."),
|
|
76
|
+
required: r.required.notOnCreate()
|
|
77
|
+
})).list((r) => ({
|
|
78
|
+
columns: [
|
|
79
|
+
r.label,
|
|
80
|
+
r.name,
|
|
81
|
+
r.type,
|
|
82
|
+
r.position
|
|
83
|
+
],
|
|
84
|
+
sort: [[r.position, "asc"]]
|
|
85
|
+
})).layout((r) => [l.section("Field", [
|
|
86
|
+
r.table_id,
|
|
87
|
+
r.label,
|
|
88
|
+
r.name,
|
|
89
|
+
r.type,
|
|
90
|
+
r.position
|
|
91
|
+
]), l.section("Decimal number", [r.precision, r.scale])]);
|
|
92
|
+
//#endregion
|
|
93
|
+
export { fieldTypeLabels, fieldsView, tablesView };
|
package/dist/view-access.js
CHANGED
|
@@ -306,6 +306,7 @@ const actionShape = (model, models, createPages) => shapes.object({
|
|
|
306
306
|
const viewShape = (resource, model, models, prompted, createPages, writeOnly) => {
|
|
307
307
|
const nav = shapes.object({
|
|
308
308
|
hidden: shapes.data,
|
|
309
|
+
creatorsOnly: shapes.data,
|
|
309
310
|
group: shapes.data,
|
|
310
311
|
order: shapes.data,
|
|
311
312
|
tenant: shapes.data,
|
package/dist/webhooks/attempt.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AddressRefusedError, pinnedRequest } from "./table/pinned-request.js";
|
|
2
|
-
import { readLimited } from "./table/read-limited.js";
|
|
3
1
|
import { invokeFunction } from "../functions/define-function.js";
|
|
4
2
|
import { retryAfterMs } from "./retry-schedule.js";
|
|
5
3
|
import { standardWebhookHeaders } from "./standard-webhooks.js";
|
|
6
4
|
import { subscriberSession } from "./subscriber-view.js";
|
|
5
|
+
import { AddressRefusedError, pinnedRequest } from "./table/pinned-request.js";
|
|
6
|
+
import { readLimited } from "./table/read-limited.js";
|
|
7
7
|
//#region src/webhooks/attempt.ts
|
|
8
8
|
/** How long a receiver has to answer. */
|
|
9
9
|
const attemptTimeoutMs = 15e3;
|
|
@@ -4,7 +4,7 @@ import { isIP } from "node:net";
|
|
|
4
4
|
const v4 = (address) => address.split(".").map(Number);
|
|
5
5
|
const privateV4 = (address) => {
|
|
6
6
|
const [a, b] = v4(address);
|
|
7
|
-
return a === 0 || a === 10 || a === 127 || a >= 224 || a === 100 && b >= 64 && b < 128 || a === 169 && b === 254 || a === 172 && b >= 16 && b < 32 || a === 192 && b === 168;
|
|
7
|
+
return a === 0 || a === 10 || a === 127 || a >= 224 || a === 100 && b >= 64 && b < 128 || a === 169 && b === 254 || a === 172 && b >= 16 && b < 32 || a === 192 && b === 168 || a === 198 && (b === 18 || b === 19);
|
|
8
8
|
};
|
|
9
9
|
const v6Groups = (address) => {
|
|
10
10
|
const halves = address.toLowerCase().replace(/%.*$/, "").replace(/(\d+)\.(\d+)\.(\d+)\.(\d+)$/, (_, a, b, c, d) => `${(+a << 8 | +b).toString(16)}:${(+c << 8 | +d).toString(16)}`).split("::");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { checkWebhookUrl } from "./address-check.js";
|
|
2
1
|
import { betterAuthOwnerRoles } from "./owner-roles.js";
|
|
2
|
+
import { checkWebhookUrl } from "./address-check.js";
|
|
3
3
|
import { webhooksSchema } from "./options.js";
|
|
4
4
|
import { tableSubscriptions } from "./table-subscriptions.js";
|
|
5
5
|
//#region src/webhooks/table/webhook-table.ts
|
|
@@ -60,7 +60,7 @@ const deliveryGroup = ({ subscription, change }) => `${subscription.name}:${chan
|
|
|
60
60
|
*
|
|
61
61
|
* No jobs without a resource with events or history; the subscriptions must name declared events.
|
|
62
62
|
*/
|
|
63
|
-
const createWebhooks = ({ deps, subscriptions, functions, channels, schema, log, table }) => {
|
|
63
|
+
const createWebhooks = ({ deps, subscriptions, functions, channels, schema, log, table, onChanges }) => {
|
|
64
64
|
const entries = deps.registry.entries;
|
|
65
65
|
const models = entries.map((entry) => entry.model);
|
|
66
66
|
const problems = subscriptionProblems(subscriptions, models, Object.keys(functions));
|
|
@@ -292,6 +292,7 @@ const createWebhooks = ({ deps, subscriptions, functions, channels, schema, log,
|
|
|
292
292
|
});
|
|
293
293
|
await writeHistory(trx, schema, changes.filter((change) => deps.registry.find(change.resource)?.model.history));
|
|
294
294
|
await writeNotices(trx, schema, changes.filter((change) => deps.registry.find(change.resource)?.model.live));
|
|
295
|
+
await onChanges?.(trx, changes);
|
|
295
296
|
await deleteOutbox(trx, schema, rows.map((row) => row.id));
|
|
296
297
|
});
|
|
297
298
|
for (const [index, { subscription, event }] of now.entries()) report(subscription.name, event, 1, results[index]);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { sql } from "kysely";
|
|
2
|
+
//#region src/workflows/effects-store.ts
|
|
3
|
+
/** The idempotency keys of one run's steps, in the `effects` table of the `workflows` schema. */
|
|
4
|
+
const effectsStore = (schema, runId) => {
|
|
5
|
+
const effects = sql.id(schema, "effects");
|
|
6
|
+
return {
|
|
7
|
+
claim: async (trx, key) => {
|
|
8
|
+
if ((await sql`insert into ${effects} (run_id, key) values (${runId}, ${key}) on conflict do nothing returning key`.execute(trx)).rows.length > 0) return;
|
|
9
|
+
const { rows } = await sql`select result from ${effects} where run_id = ${runId} and key = ${key}`.execute(trx);
|
|
10
|
+
return { result: rows[0].result };
|
|
11
|
+
},
|
|
12
|
+
keep: async (trx, key, result) => {
|
|
13
|
+
await sql`update ${effects} set result = ${JSON.stringify(result)}::jsonb where run_id = ${runId} and key = ${key}`.execute(trx);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { effectsStore };
|
|
@@ -5,7 +5,7 @@ import { limits } from "@protobase/workflows";
|
|
|
5
5
|
*/
|
|
6
6
|
const workflowInstructions = [
|
|
7
7
|
"Workflows: list_workflow_types names the step types and triggers with their arguments and inputs; list_workflows and get_workflow read workflows; validate_workflow checks a definition without saving it; create_workflow and update_workflow save one; run_workflow starts a run with an input, and get_workflow_run reads it with each step's input, output, logs and error. A run goes on in the background: read it again until its status is succeeded or failed, then fix the step that failed with update_workflow and run it again.",
|
|
8
|
-
"A definition is one JSON document: { \"trigger\": <
|
|
8
|
+
"A definition is one JSON document: { \"trigger\": <trigger>, \"stateMachine\": { \"QueryLanguage\": \"JSONata\", \"StartAt\": \"<state>\", \"States\": { \"<state>\": <state>, ... } } }, the States Language with JSONata expressions, in a profile where every value is read by name. It holds no layout. <trigger> is an object with one key: { \"<trigger id>\": <its input> } for a trigger list_workflow_types names, or { \"manual\": {} } for a workflow that runs only when someone starts it.",
|
|
9
9
|
"States: Task { Resource: <step type>, Arguments, TimeoutSeconds, Retry, Catch }; Pass { Output, Assign }; Choice { Choices: [{ Condition, Next, Output?, Assign? }], Default }; Map { Items, ItemProcessor: { StartAt, States }, MaxConcurrency }; Wait { Seconds | Timestamp }; Succeed { Output }; Fail { Error, Cause }. Every state may have Comment, Output and Assign. Task, Pass, Map and Wait have exactly one of Next (a state name) and End: true. State names are unique across the document, Maps included, and every state must be reachable from StartAt. InputPath, Parameters, ResultPath and the other JSONPath fields, and Parallel, are not part of the profile.",
|
|
10
10
|
"Expressions: a string that is whole \"{% ... %}\" is a JSONata expression whose value, of any type, the field takes; any other string is literal text. Build text inside one expression with &: \"{% 'Order ' & $order.id %}\". Expressions sit at any depth in Arguments, Output and Assign, and in Items, Condition, Seconds, Timestamp, Error and Cause.",
|
|
11
11
|
"Reading values by name, the only reads allowed: $states.context.Execution.Input (the run's input, in every state), $states.context.Execution.StartTime, $states.context.Secrets.<NAME> (a secret the app lists), $<variable> (assigned by a state that runs before), $states.result (a Task's or Map's result, in its Output and Assign), $states.errorOutput ({ Error, Cause }, in a Catch rule's Output and Assign), $states.input (the item, only in the first state of a Map's ItemProcessor). Never a bare field name, $ or $$ on its own, or $eval. Keep a result for later states with \"Assign\": { \"order\": \"{% $states.result %}\" }, read as $order from the next state on; a state inside a Map may not assign a name an outer state assigns.",
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { AssistantTool, ToolContext } from "../../assistant/tools.js";
|
|
2
2
|
import "../../index.js";
|
|
3
|
+
import { ResourceModel } from "@protobase/schema";
|
|
4
|
+
import { CheckOptions, TypeEntry } from "@protobase/workflows";
|
|
3
5
|
//#region src/workflows/mcp/workflow-read-tools.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* The app's types, which the tools list and check definitions against: `checkWith` checks against the resources it is
|
|
8
|
+
* given, so a check names only what its caller may read.
|
|
9
|
+
*/
|
|
10
|
+
export type WorkflowCatalog = {
|
|
11
|
+
types: readonly TypeEntry[];
|
|
12
|
+
checkWith: (models: (name: string) => ResourceModel | undefined) => CheckOptions;
|
|
13
|
+
};
|
|
4
14
|
/** The tools that read workflows, their types and runs, and check definitions. */
|
|
5
|
-
export declare const workflowReadTools: () => AssistantTool<ToolContext>[];
|
|
15
|
+
export declare const workflowReadTools: (catalog: WorkflowCatalog) => AssistantTool<ToolContext>[];
|
|
6
16
|
//#endregion
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { defineTool } from "../../assistant/tools.js";
|
|
2
2
|
import { refused } from "../../assistant/record-tool-args.js";
|
|
3
|
-
import { stepTypeNames } from "../step-types.js";
|
|
4
3
|
import { mergePatch } from "./merge-patch.js";
|
|
5
|
-
import { stepTypeCatalog, triggerCatalog, triggerNote } from "./type-catalog.js";
|
|
6
4
|
import { definitionParameter, editParameter, idOf, idParameter, objectOf, pageSizeOf, textOf } from "./workflow-tool-args.js";
|
|
7
|
-
import { checkDefinition } from "@protobase/workflows";
|
|
5
|
+
import { checkDefinition, typeCatalog } from "@protobase/workflows";
|
|
8
6
|
//#region src/workflows/mcp/workflow-read-tools.ts
|
|
9
7
|
const reads = {
|
|
10
8
|
readOnlyHint: true,
|
|
@@ -18,19 +16,15 @@ const listed = [
|
|
|
18
16
|
"updated_at"
|
|
19
17
|
];
|
|
20
18
|
/** The step types and triggers a definition may name, with their arguments, results, errors and run inputs. */
|
|
21
|
-
const listWorkflowTypesTool = defineTool({
|
|
19
|
+
const listWorkflowTypesTool = (catalog) => defineTool({
|
|
22
20
|
name: "list_workflow_types",
|
|
23
|
-
description: "Lists what a workflow definition may name, as JSON ({ step_types, triggers }): each step type a Task names as its Resource, with its
|
|
21
|
+
description: "Lists what a workflow definition may name, as JSON ({ step_types, triggers }): each step type a Task names as its Resource and each trigger, by id, with its label, description, input (the Task's Arguments, or the trigger's input) and output as JSON Schema, the errors a step fails with, the connection it signs in with, and whether this app can run it.",
|
|
24
22
|
parameters: {
|
|
25
23
|
type: "object",
|
|
26
24
|
properties: {}
|
|
27
25
|
},
|
|
28
26
|
annotations: reads,
|
|
29
|
-
run: async () => JSON.stringify(
|
|
30
|
-
step_types: stepTypeCatalog,
|
|
31
|
-
triggers: triggerCatalog,
|
|
32
|
-
note: triggerNote
|
|
33
|
-
})
|
|
27
|
+
run: async () => JSON.stringify(typeCatalog(catalog.types))
|
|
34
28
|
});
|
|
35
29
|
/** The workflows the caller may read, a page at a time, without their definitions. */
|
|
36
30
|
const listWorkflowsTool = defineTool({
|
|
@@ -89,15 +83,16 @@ const getWorkflowTool = defineTool({
|
|
|
89
83
|
}), refused);
|
|
90
84
|
}
|
|
91
85
|
});
|
|
92
|
-
const checked = (definition) => {
|
|
93
|
-
const
|
|
86
|
+
const checked = async (definition, catalog, context) => {
|
|
87
|
+
const { models } = await context.resources();
|
|
88
|
+
const problems = checkDefinition(definition, catalog.checkWith((name) => models.find((model) => model.name === name)));
|
|
94
89
|
return JSON.stringify(problems.length > 0 ? {
|
|
95
90
|
valid: false,
|
|
96
91
|
problems
|
|
97
92
|
} : { valid: true });
|
|
98
93
|
};
|
|
99
94
|
/** Checks a definition, or a saved one with an edit, without saving anything. */
|
|
100
|
-
const validateWorkflowTool = defineTool({
|
|
95
|
+
const validateWorkflowTool = (catalog) => defineTool({
|
|
101
96
|
name: "validate_workflow",
|
|
102
97
|
description: "Checks a definition as a save checks it, and saves nothing: pass a whole definition, or a workflow's id with an edit to check that edit of its saved definition. Returns JSON { valid: true }, or { valid: false, problems }, each problem { state, field, message } naming the state, the field and what was expected.",
|
|
103
98
|
parameters: {
|
|
@@ -112,8 +107,8 @@ const validateWorkflowTool = defineTool({
|
|
|
112
107
|
run: async (args, context) => {
|
|
113
108
|
const id = idOf(args);
|
|
114
109
|
const edit = objectOf(args.edit);
|
|
115
|
-
if (args.definition !== void 0 && id === void 0 && edit === void 0) return checked(args.definition);
|
|
116
|
-
if (args.definition === void 0 && id && edit) return context.records.get("workflows", id).then(({ record }) => checked(mergePatch(record.definition, edit)), refused);
|
|
110
|
+
if (args.definition !== void 0 && id === void 0 && edit === void 0) return checked(args.definition, catalog, context);
|
|
111
|
+
if (args.definition === void 0 && id && edit) return context.records.get("workflows", id).then(({ record }) => checked(mergePatch(record.definition, edit), catalog, context), refused);
|
|
117
112
|
return "Pass either { \"definition\": { ... } } or { \"id\": \"<id>\", \"edit\": { ... } }.";
|
|
118
113
|
}
|
|
119
114
|
});
|
|
@@ -200,12 +195,12 @@ const getWorkflowRunTool = defineTool({
|
|
|
200
195
|
}
|
|
201
196
|
});
|
|
202
197
|
/** The tools that read workflows, their types and runs, and check definitions. */
|
|
203
|
-
const workflowReadTools = () => [
|
|
204
|
-
listWorkflowTypesTool,
|
|
198
|
+
const workflowReadTools = (catalog) => [
|
|
199
|
+
listWorkflowTypesTool(catalog),
|
|
205
200
|
listWorkflowsTool,
|
|
206
201
|
getWorkflowTool,
|
|
207
|
-
validateWorkflowTool,
|
|
202
|
+
validateWorkflowTool(catalog),
|
|
208
203
|
getWorkflowRunTool
|
|
209
204
|
];
|
|
210
205
|
//#endregion
|
|
211
|
-
export { getWorkflowRunTool, getWorkflowTool,
|
|
206
|
+
export { getWorkflowRunTool, getWorkflowTool, listWorkflowsTool, workflowReadTools };
|