@protobase/server 0.59.3 → 0.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/calls/admission.d.ts +4 -0
  2. package/dist/calls/admission.js +12 -0
  3. package/dist/calls/call-hub.js +170 -0
  4. package/dist/calls/call-member.d.ts +19 -6
  5. package/dist/calls/call-reads.d.ts +29 -0
  6. package/dist/calls/call-reads.js +79 -0
  7. package/dist/calls/call-signals-sql.d.ts +12 -0
  8. package/dist/calls/call-signals-sql.js +19 -0
  9. package/dist/calls/call-store.d.ts +30 -0
  10. package/dist/calls/call-store.js +112 -0
  11. package/dist/calls/call-sweep.js +26 -0
  12. package/dist/calls/call-watch.js +39 -0
  13. package/dist/calls/calls-access.d.ts +20 -5
  14. package/dist/calls/calls-access.js +38 -17
  15. package/dist/calls/calls-options.d.ts +9 -1
  16. package/dist/calls/calls-options.js +10 -2
  17. package/dist/calls/calls-runtime.d.ts +33 -0
  18. package/dist/calls/calls-runtime.js +94 -0
  19. package/dist/calls/calls-service-type.d.ts +11 -0
  20. package/dist/calls/calls-service.js +27 -0
  21. package/dist/calls/calls-sql.d.ts +7 -0
  22. package/dist/calls/calls-sql.js +66 -0
  23. package/dist/calls/calls-store.d.ts +23 -0
  24. package/dist/calls/calls-store.js +20 -0
  25. package/dist/calls/client-message.js +1 -0
  26. package/dist/calls/close-codes.js +17 -0
  27. package/dist/calls/livekit/livekit-session.js +1 -0
  28. package/dist/calls/member-relay.js +69 -17
  29. package/dist/calls/peer/peer-backend.js +68 -120
  30. package/dist/calls/record-calls.js +78 -0
  31. package/dist/create-admin.js +4 -2
  32. package/dist/deps.d.ts +3 -0
  33. package/dist/functions/function-socket.d.ts +1 -0
  34. package/dist/functions/function-socket.js +14 -2
  35. package/dist/functions/routes.js +3 -4
  36. package/dist/index.d.ts +2 -1
  37. package/dist/index.js +2 -1
  38. package/dist/package.js +1 -1
  39. package/dist/routes/record.js +6 -0
  40. package/dist/webhooks/attempt.js +6 -1
  41. package/package.json +4 -4
@@ -1,131 +1,79 @@
1
1
  //#region src/calls/peer/peer-backend.ts
2
- /** How long a member whose socket was lost stays in the call for the others, waiting for their browser to resume. */
3
- const awayMs = 3e4;
4
2
  /**
5
- * The peer plugin: no media server. Protobase passes each member's descriptions and candidates to the member they name,
6
- * and tells every member who else is in the call and which of their tracks they hear; the browsers send their media to
7
- * each other directly. Members meet only within this process, which keeps who is in each call.
3
+ * The peer plugin: no media server. Protobase passes each member's descriptions and candidates to the member they name
4
+ * in the same call, and tells every member who else is in it and which of their tracks they hear; the browsers send
5
+ * their media to each other directly. Who is in the call, and the tracks each sends, are the call's record.
8
6
  */
9
- const peerBackend = (settings) => {
10
- const calls = /* @__PURE__ */ new Map();
11
- const membersOf = (call) => [...calls.get(call)?.values() ?? []];
12
- const announce = (call) => {
13
- const present = membersOf(call);
14
- for (const viewer of present) {
15
- if (viewer.away) continue;
16
- const others = present.filter((other) => other !== viewer);
17
- const hears = viewer.member.hears ?? (() => true);
18
- viewer.link.send({
7
+ const peerBackend = (settings) => ({ open: (member, link, room) => {
8
+ const own = /* @__PURE__ */ new Map();
9
+ const keep = (sid, kind, source) => own.set(sid, {
10
+ sid,
11
+ member: member.member,
12
+ kind,
13
+ source,
14
+ muted: false
15
+ });
16
+ const share = () => room.tracks([...own.values()]);
17
+ const receive = async (message) => {
18
+ switch (message.type) {
19
+ case "join":
20
+ link.send({
21
+ type: "joined",
22
+ call: room.call,
23
+ mode: "peer",
24
+ participant: member.member,
25
+ iceServers: settings.iceServers ?? []
26
+ });
27
+ return;
28
+ case "resume":
29
+ for (const track of message.tracks) keep(track.sid, track.kind, track.source);
30
+ link.send({ type: "resumed" });
31
+ return;
32
+ case "publish":
33
+ for (const track of message.tracks) keep(track.cid, track.kind, track.source);
34
+ link.send({
35
+ type: "published",
36
+ tracks: message.tracks.map((track) => ({
37
+ cid: track.cid,
38
+ sid: track.cid
39
+ }))
40
+ });
41
+ return share();
42
+ case "unpublish":
43
+ own.delete(message.sid);
44
+ return share();
45
+ case "mute": {
46
+ const track = own.get(message.sid);
47
+ if (!track) return;
48
+ track.muted = message.muted;
49
+ return share();
50
+ }
51
+ case "signal": return room.signal(message.to, {
52
+ ...message.description && { description: message.description },
53
+ ...message.candidate && { candidate: message.candidate }
54
+ });
55
+ case "leave": return link.close(1e3, "left");
56
+ case "offer":
57
+ case "candidate":
58
+ case "view": return;
59
+ }
60
+ };
61
+ return {
62
+ receive,
63
+ end: () => {},
64
+ roster: (members) => {
65
+ const others = members.filter((other) => other.member !== member.member);
66
+ const hears = member.hears ?? (() => true);
67
+ link.send({
19
68
  type: "peers",
20
- members: others.map((other) => other.member.member)
69
+ members: others.map((other) => other.member)
21
70
  });
22
- viewer.link.send({
71
+ link.send({
23
72
  type: "tracks",
24
- tracks: others.flatMap((other) => [...other.tracks.values()]).filter(hears)
73
+ tracks: others.flatMap((other) => other.tracks).filter(hears)
25
74
  });
26
75
  }
27
76
  };
28
- const remove = (self) => {
29
- const call = calls.get(self.member.call);
30
- if (call?.get(self.member.member) !== self) return;
31
- clearTimeout(self.away);
32
- call.delete(self.member.member);
33
- if (call.size === 0) calls.delete(self.member.call);
34
- announce(self.member.call);
35
- };
36
- const open = (member, link) => {
37
- const self = {
38
- member,
39
- link,
40
- tracks: /* @__PURE__ */ new Map()
41
- };
42
- const enter = () => {
43
- const call = calls.get(member.call) ?? /* @__PURE__ */ new Map();
44
- calls.set(member.call, call);
45
- const before = call.get(member.member);
46
- call.set(member.member, self);
47
- if (before) {
48
- clearTimeout(before.away);
49
- if (!before.away) {
50
- before.link.send({
51
- type: "left",
52
- reason: "removed"
53
- });
54
- before.link.close(1e3, "left");
55
- }
56
- }
57
- };
58
- const receive = (message) => {
59
- switch (message.type) {
60
- case "join":
61
- case "resume":
62
- if (message.type === "resume") for (const track of message.tracks) self.tracks.set(track.sid, {
63
- sid: track.sid,
64
- member: member.member,
65
- kind: track.kind,
66
- source: track.source,
67
- muted: false
68
- });
69
- enter();
70
- link.send(message.type === "join" ? {
71
- type: "joined",
72
- mode: "peer",
73
- participant: member.member,
74
- iceServers: settings.iceServers ?? []
75
- } : { type: "resumed" });
76
- return announce(member.call);
77
- case "publish":
78
- for (const track of message.tracks) self.tracks.set(track.cid, {
79
- sid: track.cid,
80
- member: member.member,
81
- kind: track.kind,
82
- source: track.source,
83
- muted: false
84
- });
85
- link.send({
86
- type: "published",
87
- tracks: message.tracks.map((track) => ({
88
- cid: track.cid,
89
- sid: track.cid
90
- }))
91
- });
92
- return announce(member.call);
93
- case "unpublish":
94
- self.tracks.delete(message.sid);
95
- return announce(member.call);
96
- case "mute": {
97
- const track = self.tracks.get(message.sid);
98
- if (!track) return;
99
- track.muted = message.muted;
100
- return announce(member.call);
101
- }
102
- case "signal": {
103
- const to = calls.get(member.call)?.get(message.to);
104
- if (!to || to.away || to === self) return;
105
- to.link.send({
106
- type: "signal",
107
- from: member.member,
108
- ...message.description && { description: message.description },
109
- ...message.candidate && { candidate: message.candidate }
110
- });
111
- return;
112
- }
113
- case "leave": return link.close(1e3, "left");
114
- case "offer":
115
- case "candidate":
116
- case "view": return;
117
- }
118
- };
119
- return {
120
- receive,
121
- end: (how) => {
122
- if (how === "left") return remove(self);
123
- if (calls.get(member.call)?.get(member.member) !== self) return;
124
- self.away = setTimeout(() => remove(self), awayMs);
125
- }
126
- };
127
- };
128
- return { open };
129
- };
77
+ } });
130
78
  //#endregion
131
79
  export { peerBackend };
@@ -0,0 +1,78 @@
1
+ import { HttpProblem, forbidden, notFound } from "../problem.js";
2
+ import { requestAccess, requireOperation } from "../request-access.js";
3
+ import { readTransaction } from "../transactions.js";
4
+ import { readableRecord } from "../comments/comment-access.js";
5
+ import { encodeKey } from "@protobase/schema/internal";
6
+ import { streamSSE } from "hono/streaming";
7
+ //#region src/calls/record-calls.ts
8
+ /** How often a page that follows a record's calls is checked again: whether its user still reads the record. */
9
+ const recheckMs = 6e4;
10
+ const heartbeatMs = 25e3;
11
+ /**
12
+ * Whether the caller may see the record's calls: signed in, and able to read the record (operation, tenant, row filter
13
+ * and record-level rule, as a get). A record they cannot read is the same 404 as one that does not exist.
14
+ */
15
+ const requireReader = async (deps, entry, session, key) => {
16
+ if (session.anonymous || session.user.id === "") throw forbidden("calls-need-user", "Sign in to see the calls");
17
+ const access = await requestAccess(deps, entry, session);
18
+ requireOperation(access, "read");
19
+ if (!await readTransaction(deps.db, deps.statementTimeoutMs, (trx) => readableRecord(trx, access, key, "hide"))) throw notFound(`No ${entry.name} with this key`);
20
+ };
21
+ const callsOf = (deps) => {
22
+ if (!deps.calls) throw notFound("This app has no calls");
23
+ return deps.calls;
24
+ };
25
+ /** `GET /{resource}/{key}:calls`: the record's latest calls, newest first, the one going on first. */
26
+ const readRecordCalls = async (deps, entry, session, key) => {
27
+ const calls = callsOf(deps);
28
+ await requireReader(deps, entry, session, key);
29
+ return { items: await (await calls.runtime()).of({
30
+ resource: entry.name,
31
+ key: encodeKey(key)
32
+ }) };
33
+ };
34
+ /**
35
+ * `GET /{resource}/{key}:calls?watch=true`: the same as a `text/event-stream`, each event's data `{ items }`, at once
36
+ * and whenever the calls change. The stream ends once its user can no longer read the record, at the next minute's
37
+ * check, or when the check fails.
38
+ */
39
+ const watchRecordCalls = async (c, deps, entry, key) => {
40
+ const calls = callsOf(deps);
41
+ const session = c.get("session");
42
+ await requireReader(deps, entry, session, key);
43
+ const runtime = await calls.runtime();
44
+ return streamSSE(c, async (stream) => {
45
+ const queue = [];
46
+ let wake = () => {};
47
+ let allowed = true;
48
+ stream.onAbort(() => wake());
49
+ const stop = await runtime.watch({
50
+ resource: entry.name,
51
+ key: encodeKey(key)
52
+ }, (items) => {
53
+ queue.push(items);
54
+ wake();
55
+ });
56
+ const recheck = setInterval(() => {
57
+ requireReader(deps, entry, session, key).catch((error) => {
58
+ if (!(error instanceof HttpProblem)) deps.report(error);
59
+ allowed = false;
60
+ wake();
61
+ });
62
+ }, recheckMs);
63
+ const heartbeat = setInterval(() => void stream.write(": ping\n\n"), heartbeatMs);
64
+ try {
65
+ while (!stream.aborted && allowed) {
66
+ const items = queue.shift();
67
+ if (items) await stream.writeSSE({ data: JSON.stringify({ items }) });
68
+ else await new Promise((resolve) => wake = resolve);
69
+ }
70
+ } finally {
71
+ clearInterval(recheck);
72
+ clearInterval(heartbeat);
73
+ stop();
74
+ }
75
+ });
76
+ };
77
+ //#endregion
78
+ export { readRecordCalls, watchRecordCalls };
@@ -59,6 +59,7 @@ import { toApiFunction } from "./functions/define-function.js";
59
59
  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
+ import { callsService } from "./calls/calls-service.js";
62
63
  import { deviceStore, removeDevicesWithUsers } from "./notifications/device-store-of.js";
63
64
  import { historyStore, removeHistoryWithUsers } from "./notifications/history-store-of.js";
64
65
  import { devicesPath, historyPath } from "./notifications/paths.js";
@@ -263,7 +264,8 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
263
264
  ...withAi && { ai: {
264
265
  ...model && { model },
265
266
  ...options.onUnhandledError && { report: options.onUnhandledError }
266
- } }
267
+ } },
268
+ ...calls && { calls: callsService(() => deps, calls) }
267
269
  };
268
270
  const appName = shownAppName(auth, globalThis.process?.env ?? {});
269
271
  const meta = createMeta(deps, appName, icons?.favicon ? faviconPath : void 0);
@@ -409,7 +411,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
409
411
  wake: () => wakeDispatch(deps),
410
412
  upgradeWebSocket,
411
413
  upgradeAuthenticate,
412
- ...calls && { calls },
414
+ ...deps.calls && { calls: deps.calls },
413
415
  report
414
416
  }));
415
417
  if (upgradeWebSocket) {
package/dist/deps.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { AuditQueue, PipelineHook, WriteCheck } from "./types.js";
2
2
  import { CommentUsers } from "./comments/comment-users.js";
3
+ import { CallsService } from "./calls/calls-service-type.js";
3
4
  import { Registry } from "./registry.js";
4
5
  import { ErrorReportingSettings } from "./error-reporting/error-reporting-settings.js";
5
6
  import { mentionJob } from "./comments/mention-job.js";
@@ -91,5 +92,7 @@ export type Deps = {
91
92
  model?: ModelSettings;
92
93
  report?: (error: unknown) => void;
93
94
  };
95
+ /** With `calls`: the app's calls, which functions admit members to and the records' readers follow. */
96
+ calls?: CallsService;
94
97
  };
95
98
  //#endregion
@@ -13,6 +13,7 @@ export type SocketEvents = {
13
13
  onOpen?: (socket: FunctionSocket) => void | Promise<void>;
14
14
  /** Text arrives as a string, binary as an ArrayBuffer. The next message waits until a returned promise settles. */
15
15
  onMessage?: (data: string | ArrayBuffer, socket: FunctionSocket) => void | Promise<void>;
16
+ /** With the code the server closed the socket with, such as 1008 after a refused check, else the browser's. */
16
17
  onClose?: (code: number, reason: string) => void | Promise<void>;
17
18
  /**
18
19
  * Checked every minute after the framework's own check, while the socket is open; what it returns is ignored. Throw
@@ -18,9 +18,14 @@ const socketEvents = (events, { report, recheck }) => {
18
18
  let waiting = 0;
19
19
  let paused = false;
20
20
  let ended = false;
21
+ let closedWith;
21
22
  let stopRecheck = () => {};
22
23
  const end = (code, reason) => {
23
24
  ended = true;
25
+ closedWith ??= {
26
+ code,
27
+ reason
28
+ };
24
29
  stopRecheck();
25
30
  raw.close(code, reason);
26
31
  };
@@ -56,7 +61,13 @@ const socketEvents = (events, { report, recheck }) => {
56
61
  if (raw.readyState !== openState) return resolve();
57
62
  raw.send(data, () => resolve());
58
63
  }),
59
- close: (code, reason) => raw.close(code, reason),
64
+ close: (code, reason) => {
65
+ closedWith ??= {
66
+ code: code ?? 1e3,
67
+ reason: reason ?? ""
68
+ };
69
+ raw.close(code, reason);
70
+ },
60
71
  get bufferedAmount() {
61
72
  return raw.bufferedAmount;
62
73
  }
@@ -77,7 +88,8 @@ const socketEvents = (events, { report, recheck }) => {
77
88
  },
78
89
  onClose: (event) => {
79
90
  stopRecheck();
80
- enqueue(() => events.onClose?.(event.code, event.reason), true);
91
+ const { code, reason } = closedWith ?? event;
92
+ enqueue(() => events.onClose?.(code, reason), true);
81
93
  }
82
94
  };
83
95
  };
@@ -24,8 +24,7 @@ const isUpgrade = (request) => request.headers.get("upgrade")?.toLowerCase() ===
24
24
  * A function may answer an upgrade with a socket, only once it returned. While it is open, its caller is checked again
25
25
  * every minute: a protected function's always, a public one's once `caller()` resolved.
26
26
  */
27
- const functionRoutes = ({ basePath, functions, authenticate, access, db, records, channels, decryptField, onError, wake, upgradeWebSocket, upgradeAuthenticate = authenticate, calls: callsOptions, report }) => {
28
- const calls = callsAccess(callsOptions);
27
+ const functionRoutes = ({ basePath, functions, authenticate, access, db, records, channels, decryptField, onError, wake, upgradeWebSocket, upgradeAuthenticate = authenticate, calls, report }) => {
29
28
  const app = new Hono().basePath(basePath);
30
29
  app.onError(onError);
31
30
  const sessionOf = (request) => isUpgrade(request) ? upgradeAuthenticate(request) : authenticate(request);
@@ -71,7 +70,7 @@ const functionRoutes = ({ basePath, functions, authenticate, access, db, records
71
70
  channels,
72
71
  caller: resolveCaller,
73
72
  acceptWebSocket: acceptor.accept,
74
- calls
73
+ calls: callsAccess(calls, resolveCaller)
75
74
  };
76
75
  return acceptor.answer(name, await invokeFunction(name, fn, request, context));
77
76
  }
@@ -101,7 +100,7 @@ const functionRoutes = ({ basePath, functions, authenticate, access, db, records
101
100
  caller: async () => caller,
102
101
  decryptField: decryptField(reader),
103
102
  acceptWebSocket: acceptor.accept,
104
- calls
103
+ calls: callsAccess(calls, async () => caller)
105
104
  };
106
105
  return acceptor.answer(name, await invokeFunction(name, fn, request, context));
107
106
  }));
package/dist/index.d.ts CHANGED
@@ -104,6 +104,7 @@ import { checkWebhooksSchema, webhooksMigration } from "./webhooks/table/schema.
104
104
  import { checkRealtimeRelay, realtimeRelayMigration } from "./realtime/relay/relay-schema.js";
105
105
  import { channelSendsMigration, checkChannelSends } from "./channels/sends-schema.js";
106
106
  import { checkComments, commentsMigration } from "./comments/comments-sql.js";
107
+ import { callsMigration, checkCalls } from "./calls/calls-sql.js";
107
108
  import { CheckAiInput, checkAi } from "./ai/check-ai.js";
108
109
  import { CommentItem } from "./comments/comment-item.js";
109
110
  import { checkNotificationsSchema, notificationsMigration } from "./notifications/schema.js";
@@ -179,4 +180,4 @@ import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/ru
179
180
  import { jobsDrainApp } from "./jobs/drain-route.js";
180
181
  import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
181
182
  import { AdminAuth, CreateAuthOptions, UserCreatedHook, normalizeRoles } from "./better-auth/create-auth.js";
182
- 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 MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type McpApprovals, type McpGateInput, type McpHandlerInput, type McpRoutesInput, type McpServerInput, type McpToolsInput, type McpWrites, type MemberInput, type Membership, MissingCredentials, type MobileConfig, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type 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 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, capSocketMessages, changesMigration, channelSendsMigration, checkAi, checkAuthSchema, checkChanges, checkChannelSends, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkStatusSchema, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, 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, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, 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, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
183
+ 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 MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type McpApprovals, type McpGateInput, type McpHandlerInput, type McpRoutesInput, type McpServerInput, type McpToolsInput, type McpWrites, type MemberInput, type Membership, MissingCredentials, type MobileConfig, ModelError, type ModelSettings, type NewDevice, type NewNotification, type NewOrganization, type NewUser, type NotificationRecipients, NotificationSendError, type NotificationsOptions, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type 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 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, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, 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, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, 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, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
package/dist/index.js CHANGED
@@ -112,6 +112,7 @@ import { checkComputed, computedMigration } from "./computed/computed-schema.js"
112
112
  import { checkWebhooksSchema, webhooksMigration } from "./webhooks/table/schema.js";
113
113
  import { checkRealtimeRelay, realtimeRelayMigration } from "./realtime/relay/relay-schema.js";
114
114
  import { channelSendsMigration, checkChannelSends } from "./channels/sends-schema.js";
115
+ import { callsMigration, checkCalls } from "./calls/calls-sql.js";
115
116
  import { checkAi } from "./ai/check-ai.js";
116
117
  import { checkNotificationsSchema, notificationsMigration } from "./notifications/schema.js";
117
118
  import { sendNotification } from "./notifications/send-notification.js";
@@ -131,4 +132,4 @@ import { enqueueJob } from "./jobs/declared-job.js";
131
132
  import { defineEmail } from "./mail/define-email.js";
132
133
  import { startJobs } from "./jobs/runtime.js";
133
134
  import { jobsDrainApp } from "./jobs/drain-route.js";
134
- export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, MissingCredentials, ModelError, NotificationSendError, PushMessageError, addAppRoleToOwners, addCommentTool, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, appNameOver, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaDrift, authSchemaMigration, authStoreTables, backgroundSettled, badRequest, batchWriteTool, beforeSignInPluginsVariable, betterAuthTokens, capSocketMessages, changesMigration, channelSendsMigration, checkAi, checkAuthSchema, checkChanges, checkChannelSends, checkComments, checkComputed, checkJobsSchema, checkNotificationsSchema, checkQueryRunner, checkRealtimeRelay, checkResourcesOutsideAuthStore, checkSourceNames, checkStatusSchema, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, 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, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, 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, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
135
+ export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, MissingCredentials, ModelError, NotificationSendError, 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, checkViewQueries, checkWebhooksSchema, coalesce, commentTools, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, countRecordsTool, createAdmin, createConversations, createEncryptionTools, createFileCleanup, createOrganization, createRecordTool, createUser, defaultAppName, defaultHistoryPage, defaultSignInPolicy, defineEmail, defineFunction, defineJob, 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, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readRecordTools, readVapidSettings, readWriteQueryTool, readableResources, realtimeLimits, realtimeRelayMigration, recordOf, refusalOf, refused, relayed, 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, vapidPrivateKeyVariable, vapidPublicKeyVariable, vapidSubjectVariable, variantPath, verifySignature, verifyStandardWebhook, waitUntil, wantsLongQueries, webManifestPath, webPushSender, webauthnPath, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps, writeRecordTools };
package/dist/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.59.3";
2
+ var version = "0.60.0";
3
3
  //#endregion
4
4
  export { version };
@@ -13,6 +13,7 @@ import { revealField } from "../reveal-service.js";
13
13
  import { readHistory } from "../history/read-history.js";
14
14
  import { mentionable } from "../comments/mentionable.js";
15
15
  import { generateField } from "../ai/generate-route.js";
16
+ import { readRecordCalls, watchRecordCalls } from "../calls/record-calls.js";
16
17
  import { Hono } from "hono";
17
18
  //#region src/routes/record.ts
18
19
  const recordRoutes = (deps) => {
@@ -21,6 +22,11 @@ const recordRoutes = (deps) => {
21
22
  const { entry } = resolveTarget(deps, c.req.param("resource"));
22
23
  if (c.req.param("key").endsWith(":history")) return c.json(await readHistory(deps, entry, c.get("session"), keyFromPath(c, entry, ":history"), c.req.query()));
23
24
  if (c.req.param("key").endsWith(":comments")) return c.json(await readComments(deps, entry, c.get("session"), keyFromPath(c, entry, ":comments"), c.req.query()));
25
+ if (c.req.param("key").endsWith(":calls")) {
26
+ const key = keyFromPath(c, entry, ":calls");
27
+ if (c.req.query("watch") === "true") return watchRecordCalls(c, deps, entry, key);
28
+ return c.json(await readRecordCalls(deps, entry, c.get("session"), key));
29
+ }
24
30
  if (c.req.param("key").endsWith(":mentionable")) return c.json(await mentionable(deps, entry, c.get("session"), keyFromPath(c, entry, ":mentionable"), c.req.query()));
25
31
  const found = await readRecord(deps, entry, c.get("session"), keyFromPath(c, entry), c.req.query("show_deleted") === "true");
26
32
  const columns = selectedFields({
@@ -47,6 +47,7 @@ const callFunction = async (name, subscription, event, options, context, signal)
47
47
  session,
48
48
  records: context.records(session)
49
49
  };
50
+ const noCalls = () => Promise.reject(/* @__PURE__ */ new Error(`The function "${name}" reached calls, which a webhook delivery has none of`));
50
51
  const acceptWebSocket = () => {
51
52
  throw new Error(`The function "${name}" accepted a WebSocket, but a webhook delivery is no upgrade`);
52
53
  };
@@ -56,7 +57,11 @@ const callFunction = async (name, subscription, event, options, context, signal)
56
57
  channels: context.channels,
57
58
  caller: async () => caller,
58
59
  acceptWebSocket,
59
- calls: { join: async () => acceptWebSocket() }
60
+ calls: {
61
+ join: async () => acceptWebSocket(),
62
+ remove: noCalls,
63
+ of: noCalls
64
+ }
60
65
  };
61
66
  return invokeFunction(name, fn, await request("http://protobase.internal/", event, options, signal), fn.options.public ? functionContext : {
62
67
  ...functionContext,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.59.3",
3
+ "version": "0.60.0",
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": {
@@ -42,9 +42,9 @@
42
42
  "@better-auth/sso": "^1.7.12",
43
43
  "@livekit/protocol": "1.53.1",
44
44
  "@modelcontextprotocol/server": "^2.3.1",
45
- "@protobase/layout": "0.59.3",
46
- "@protobase/query": "0.59.3",
47
- "@protobase/schema": "0.59.3",
45
+ "@protobase/layout": "0.60.0",
46
+ "@protobase/query": "0.60.0",
47
+ "@protobase/schema": "0.60.0",
48
48
  "@react-email/render": "^2.1.0",
49
49
  "@scalar/hono-api-reference": "^0.12.10",
50
50
  "@sentry/core": "^11.7.0",