@protobase/server 0.62.4 → 0.62.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/better-auth/auth-settings.d.ts +4 -1
- package/dist/better-auth/create-auth.d.ts +14 -2
- package/dist/better-auth/create-auth.js +8 -0
- package/dist/better-auth/status-route.js +8 -1
- package/dist/create-admin.js +1 -0
- package/dist/functions/define-function.d.ts +10 -0
- package/dist/functions/own-mailbox.js +9 -0
- package/dist/functions/routes.js +4 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/jobs/job-types.d.ts +1 -1
- package/dist/jobs/runtime.d.ts +1 -1
- package/dist/mail/composer-message.js +27 -0
- package/dist/mail/define-email.d.ts +7 -4
- package/dist/mail/define-email.js +3 -2
- package/dist/mail/{smtp-mailer.d.ts → mail-message.d.ts} +9 -1
- package/dist/mail/smtp-mailer.js +2 -8
- package/dist/package.js +1 -1
- package/dist/personal-mail/gmail.js +43 -0
- package/dist/personal-mail/linked-accounts.js +36 -0
- package/dist/personal-mail/personal-mail-error.d.ts +22 -0
- package/dist/personal-mail/personal-mail-error.js +25 -0
- package/dist/personal-mail/personal-mail-provider.d.ts +25 -0
- package/dist/personal-mail/personal-mail-providers.d.ts +8 -0
- package/dist/personal-mail/personal-mail-providers.js +16 -0
- package/dist/personal-mail/personal-mailer.js +26 -0
- package/dist/personal-mail/rfc822-message.js +15 -0
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UserColumn } from "./user-table.js";
|
|
2
|
-
import { Mailer } from "../mail/
|
|
2
|
+
import { Mailer } from "../mail/mail-message.js";
|
|
3
3
|
import { SignInPolicy } from "./sign-in-policy.js";
|
|
4
4
|
import { StaffSignIn } from "./staff-log.js";
|
|
5
5
|
import { Person } from "./organizations/people-endpoint.js";
|
|
@@ -10,6 +10,7 @@ import { VersionedSecret } from "./secret-versions.js";
|
|
|
10
10
|
import { UserDeletionListener } from "./user-deletion.js";
|
|
11
11
|
import { OrganizationRole, StoredMember, StoredOrganization } from "./organizations/store.js";
|
|
12
12
|
import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
|
|
13
|
+
import { PersonalMailProvider } from "../personal-mail/personal-mail-provider.js";
|
|
13
14
|
import { McpAuthOptions } from "./mcp/mcp-plugins.js";
|
|
14
15
|
import "../index.js";
|
|
15
16
|
import { CreateAuthOptions, UserCreatedHook } from "./create-auth.js";
|
|
@@ -8836,6 +8837,8 @@ export declare const buildAppAuth: (settings: AuthSettings, input: AppAuthInput)
|
|
|
8836
8837
|
id: string;
|
|
8837
8838
|
name: string;
|
|
8838
8839
|
}[];
|
|
8840
|
+
personalMail: PersonalMailProvider[];
|
|
8841
|
+
personalMailer: (userId: string) => Mailer;
|
|
8839
8842
|
mcp: {
|
|
8840
8843
|
resource: string;
|
|
8841
8844
|
path: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UserColumn, UserTableOptions } from "./user-table.js";
|
|
2
|
-
import { Mailer } from "../mail/
|
|
2
|
+
import { Mailer } from "../mail/mail-message.js";
|
|
3
3
|
import { SignInPolicy } from "./sign-in-policy.js";
|
|
4
4
|
import { StaffSignIn } from "./staff-log.js";
|
|
5
5
|
import { Person } from "./organizations/people-endpoint.js";
|
|
@@ -10,9 +10,11 @@ import { VersionedSecret } from "./secret-versions.js";
|
|
|
10
10
|
import { UserDeletionListener } from "./user-deletion.js";
|
|
11
11
|
import { OrganizationRole } from "./organizations/store.js";
|
|
12
12
|
import { OrganizationsOptions, ResolvedOrganizations } from "./organizations/options.js";
|
|
13
|
+
import { PersonalMailProvider } from "../personal-mail/personal-mail-provider.js";
|
|
13
14
|
import { McpAuthOptions } from "./mcp/mcp-plugins.js";
|
|
14
15
|
import { OperatorProvider } from "./operator-provider.js";
|
|
15
16
|
import { PlatformSignIn } from "./platform-sign-in.js";
|
|
17
|
+
import { PersonalMailProviderId } from "../personal-mail/personal-mail-providers.js";
|
|
16
18
|
import "../index.js";
|
|
17
19
|
import "./auth-base-path.js";
|
|
18
20
|
import { mcpAuthPlugins } from "./mcp/mcp-auth-plugins.js";
|
|
@@ -108,6 +110,12 @@ export type CreateAuthOptions = {
|
|
|
108
110
|
* One with the id of `signInProvider` takes its place. Default none.
|
|
109
111
|
*/
|
|
110
112
|
socialProviders?: BetterAuthOptions['socialProviders'];
|
|
113
|
+
/**
|
|
114
|
+
* The mail providers people may link their own mailbox with, from the account page, for the app's functions to send
|
|
115
|
+
* mail from it (`context.personalMail`), such as `['gmail']`. Each links through its sign-in provider, which
|
|
116
|
+
* `socialProviders` must have: Gmail through `google`. Default none.
|
|
117
|
+
*/
|
|
118
|
+
personalMail?: PersonalMailProviderId[];
|
|
111
119
|
/** Encrypt the OAuth access, refresh and ID tokens Better Auth stores for social sign-ins, with `secret`. Default off. */
|
|
112
120
|
encryptOAuthTokens?: boolean;
|
|
113
121
|
/** Runs after a user is created, by any route: `createUser`, an admin, or a social sign-up. Default none. */
|
|
@@ -1794,7 +1802,7 @@ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlug
|
|
|
1794
1802
|
email: string;
|
|
1795
1803
|
emailVerified: boolean;
|
|
1796
1804
|
name: string;
|
|
1797
|
-
image
|
|
1805
|
+
image?: string | null | undefined;
|
|
1798
1806
|
}) | import("better-auth/plugins").UserWithTwoFactor;
|
|
1799
1807
|
}>;
|
|
1800
1808
|
generateBackupCodes: import("better-call").StrictEndpoint<"/two-factor/generate-backup-codes", {
|
|
@@ -8977,6 +8985,10 @@ export declare const createAuth: (options: CreateAuthOptions, plugins?: AuthPlug
|
|
|
8977
8985
|
id: string;
|
|
8978
8986
|
name: string;
|
|
8979
8987
|
}[];
|
|
8988
|
+
/** The mail providers people link their own mailbox with (`personalMail`). */
|
|
8989
|
+
personalMail: PersonalMailProvider[];
|
|
8990
|
+
/** Mail from `userId`'s own mailbox, through the mail provider they linked (see `personalMailer`). */
|
|
8991
|
+
personalMailer: (userId: string) => Mailer;
|
|
8980
8992
|
/** The OAuth provider for MCP clients, when on: the endpoint's resource (its URL) and path, and the scope its tokens carry. */
|
|
8981
8993
|
mcp: {
|
|
8982
8994
|
resource: string;
|
|
@@ -5,6 +5,9 @@ import { defaultSignInPolicy } from "./sign-in-policy.js";
|
|
|
5
5
|
import { roleDefinitions } from "./organizations/role-definitions.js";
|
|
6
6
|
import { signInPolicyPlugin } from "./policy-plugin.js";
|
|
7
7
|
import { goTrueSessionsPlugin } from "../gotrue/sessions-plugin.js";
|
|
8
|
+
import { betterAuthLinkedAccounts } from "../personal-mail/linked-accounts.js";
|
|
9
|
+
import { resolvePersonalMail } from "../personal-mail/personal-mail-providers.js";
|
|
10
|
+
import { personalMailer } from "../personal-mail/personal-mailer.js";
|
|
8
11
|
import { endReplacedSession } from "./end-replaced-session.js";
|
|
9
12
|
import { authBasePath } from "./auth-base-path.js";
|
|
10
13
|
import { authLogger } from "./auth-logger.js";
|
|
@@ -368,6 +371,7 @@ const createAuth = (options, plugins = {}) => {
|
|
|
368
371
|
const socialProviders = Object.keys(options.socialProviders ?? {});
|
|
369
372
|
const platformSignIn = platformSignInFor(signInSettings && resolvePlatformSignIn(signInSettings), socialProviders);
|
|
370
373
|
const saml = resolveSamlProviders(options.sso?.saml ?? [], [...socialProviders, ...platformSignIn ? [platformSignIn.provider] : []]);
|
|
374
|
+
const personalMail = resolvePersonalMail(options.personalMail ?? [], socialProviders);
|
|
371
375
|
const origins = resolveOrigins(options.baseURL, options.origins ?? platformOrigins());
|
|
372
376
|
const passkeyDomain = resolvePasskeyDomain(options.passkeyDomain ?? platformPasskeyDomain(), [options.baseURL, ...origins]);
|
|
373
377
|
const organizations = options.organizations && resolveOrganizations(options.organizations, definitions, options.baseURL);
|
|
@@ -458,6 +462,10 @@ const createAuth = (options, plugins = {}) => {
|
|
|
458
462
|
id,
|
|
459
463
|
name
|
|
460
464
|
})),
|
|
465
|
+
/** The mail providers people link their own mailbox with (`personalMail`). */
|
|
466
|
+
personalMail,
|
|
467
|
+
/** Mail from `userId`'s own mailbox, through the mail provider they linked (see `personalMailer`). */
|
|
468
|
+
personalMailer: (userId) => personalMailer(betterAuthLinkedAccounts(auth), personalMail, userId),
|
|
461
469
|
/** The OAuth provider for MCP clients, when on: the endpoint's resource (its URL) and path, and the scope its tokens carry. */
|
|
462
470
|
mcp: mcp && {
|
|
463
471
|
resource: mcp.resource,
|
|
@@ -14,7 +14,7 @@ import { Hono } from "hono";
|
|
|
14
14
|
* operator provider's name, when staff can sign in as people; `passkeyDomains`, when people have passkeys for more than
|
|
15
15
|
* one of the app's hosts, the RP IDs a passkey sign-in can ask for, the passkey domain first; with organizations, who may create them and the roles
|
|
16
16
|
* with their labels, `membership` for those a member can hold, and the roles each one's holders may also give; and
|
|
17
|
-
* `anonymous` when the project's anonymous role reads a resource, so the admin app opens for visitors before anyone signs in; `mcp` when MCP clients can connect, with the `url` of its endpoint, so the account page shows that address and lists the connected clients; and
|
|
17
|
+
* `anonymous` when the project's anonymous role reads a resource, so the admin app opens for visitors before anyone signs in; `mcp` when MCP clients can connect, with the `url` of its endpoint, so the account page shows that address and lists the connected clients; `personalMail`, the mail providers people may link their mailbox with, each with the sign-in provider it links through, the scopes and the authorization parameters of the link, so the account page offers "Link Gmail"; and
|
|
18
18
|
* `plugins`, those the app loads before sign-in (see `PluginOption`); and `locale`, the language `options.locale` puts
|
|
19
19
|
* the screens in, so the sign-in screens and public forms, which come before `/meta`, are in it too.
|
|
20
20
|
*/
|
|
@@ -48,6 +48,13 @@ const statusRoute = (auth, { anonymous = false, plugins = [], locale } = {}) =>
|
|
|
48
48
|
...passkeyDomains.length > 1 && { passkeyDomains },
|
|
49
49
|
...anonymous && { anonymous },
|
|
50
50
|
...auth.mcp && { mcp: { url: auth.mcp.resource } },
|
|
51
|
+
...auth.personalMail.length > 0 && { personalMail: auth.personalMail.map(({ id, name, signInProvider, scopes, linkParams }) => ({
|
|
52
|
+
id,
|
|
53
|
+
name,
|
|
54
|
+
provider: signInProvider,
|
|
55
|
+
scopes,
|
|
56
|
+
params: linkParams
|
|
57
|
+
})) },
|
|
51
58
|
...plugins.length > 0 && { plugins },
|
|
52
59
|
...locale && { locale },
|
|
53
60
|
...auth.organizations && { organizations: {
|
package/dist/create-admin.js
CHANGED
|
@@ -414,6 +414,7 @@ const createAdmin = ({ resources: appResources, views: appViews = [], pages = []
|
|
|
414
414
|
records: (session) => callerRecords(deps, session),
|
|
415
415
|
channels,
|
|
416
416
|
decryptField,
|
|
417
|
+
...auth && auth.personalMail.length > 0 && { personalMailer: auth.personalMailer },
|
|
417
418
|
onError,
|
|
418
419
|
wake: () => wakeDispatch(deps),
|
|
419
420
|
upgradeWebSocket,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DecryptField } from "../encryption/decrypt-field-types.js";
|
|
2
|
+
import { Mailer } from "../mail/mail-message.js";
|
|
2
3
|
import { Session } from "../types.js";
|
|
3
4
|
import { Caller } from "../api-keys/resolve-caller.js";
|
|
4
5
|
import { SocketEvents } from "./function-socket.js";
|
|
@@ -43,6 +44,15 @@ export type FunctionContext = PublicFunctionContext & FunctionCaller & {
|
|
|
43
44
|
* the audit does. Not on a public function's context: a public function that needs a value enqueues a job.
|
|
44
45
|
*/
|
|
45
46
|
decryptField: DecryptField;
|
|
47
|
+
/**
|
|
48
|
+
* Mail from the caller's own mailbox, through the mail provider they linked (`auth.personalMail`), attachments and
|
|
49
|
+
* all: `personalMail.send({ to, subject, text, html, attachments })`, or an email template's `send(to, data,
|
|
50
|
+
* context.personalMail, { attachments })`. Rejects with a `PersonalMailError`, sending nothing, when they linked no
|
|
51
|
+
* mailbox (`not_linked`) or the link no longer works (`link_expired`); thrown on, it answers as a 409 problem with
|
|
52
|
+
* that `code`. Only someone signed in as themselves sends from their mailbox: staff signed in as them, or an outside
|
|
53
|
+
* app acting for them, is refused with a 403 problem. Not on a public function's context.
|
|
54
|
+
*/
|
|
55
|
+
personalMail: Mailer;
|
|
46
56
|
};
|
|
47
57
|
/** What a function gets at `/api/sb/functions/v1/<name>`, where supabase-js calls it: the caller its keys and token make. */
|
|
48
58
|
export type KeyFunctionContext = {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ownSignInUser } from "../notifications/caller.js";
|
|
2
|
+
//#region src/functions/own-mailbox.ts
|
|
3
|
+
/**
|
|
4
|
+
* The caller's own mailbox: mail goes out from it only for someone signed in as themselves. Staff signed in as them,
|
|
5
|
+
* an outside app acting for them and a visitor are refused with a 403 problem, sending nothing.
|
|
6
|
+
*/
|
|
7
|
+
const ownMailbox = (session, personalMailer) => ({ send: async (message) => personalMailer(ownSignInUser(session, "send mail from their own mailbox")).send(message) });
|
|
8
|
+
//#endregion
|
|
9
|
+
export { ownMailbox };
|
package/dist/functions/routes.js
CHANGED
|
@@ -5,6 +5,7 @@ import { invokeFunction } from "./define-function.js";
|
|
|
5
5
|
import { runInBackground } from "../background-work.js";
|
|
6
6
|
import { callsAccess } from "../calls/calls-access.js";
|
|
7
7
|
import { socketAcceptor } from "./accept-socket.js";
|
|
8
|
+
import { ownMailbox } from "./own-mailbox.js";
|
|
8
9
|
import { functionGate, requireGate } from "./function-gate.js";
|
|
9
10
|
import { sameCaller } from "./same-caller.js";
|
|
10
11
|
import { Hono } from "hono";
|
|
@@ -15,6 +16,7 @@ const relativeRequest = (request, prefix) => {
|
|
|
15
16
|
url.pathname = url.pathname.slice(prefix.length) || "/";
|
|
16
17
|
return new Request(url, request);
|
|
17
18
|
};
|
|
19
|
+
const noPersonalMail = () => ({ send: () => Promise.reject(/* @__PURE__ */ new Error("Personal mail is off: name the mail providers people may link in auth.personalMail, such as [\"gmail\"]")) });
|
|
18
20
|
const isUpgrade = (request) => request.headers.get("upgrade")?.toLowerCase() === "websocket";
|
|
19
21
|
/**
|
|
20
22
|
* Every function at `<basePath>/<name>` and below, any method. A protected function authenticates the request first, so
|
|
@@ -24,7 +26,7 @@ const isUpgrade = (request) => request.headers.get("upgrade")?.toLowerCase() ===
|
|
|
24
26
|
* A function may answer an upgrade with a socket, only once it returned. While it is open, its caller is checked again
|
|
25
27
|
* every minute: a protected function's always, a public one's once `caller()` resolved.
|
|
26
28
|
*/
|
|
27
|
-
const functionRoutes = ({ basePath, functions, authenticate, access, db, records, channels, decryptField, onError, wake, upgradeWebSocket, upgradeAuthenticate = authenticate, calls, report }) => {
|
|
29
|
+
const functionRoutes = ({ basePath, functions, authenticate, access, db, records, channels, decryptField, personalMailer = noPersonalMail, onError, wake, upgradeWebSocket, upgradeAuthenticate = authenticate, calls, report }) => {
|
|
28
30
|
const app = new Hono().basePath(basePath);
|
|
29
31
|
app.onError(onError);
|
|
30
32
|
const sessionOf = (request) => isUpgrade(request) ? upgradeAuthenticate(request) : authenticate(request);
|
|
@@ -99,6 +101,7 @@ const functionRoutes = ({ basePath, functions, authenticate, access, db, records
|
|
|
99
101
|
...caller,
|
|
100
102
|
caller: async () => caller,
|
|
101
103
|
decryptField: decryptField(reader),
|
|
104
|
+
personalMail: ownMailbox(caller.session, personalMailer),
|
|
102
105
|
acceptWebSocket: acceptor.accept,
|
|
103
106
|
calls: callsAccess(calls, async () => caller)
|
|
104
107
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { RealtimeOptions, relayed, sqlSends } from "./realtime/relay/realtime-op
|
|
|
5
5
|
import { EventsOptions } from "./changes/events-options.js";
|
|
6
6
|
import { DecryptField, FieldDecrypter, FieldReader, RecordKey } from "./encryption/decrypt-field-types.js";
|
|
7
7
|
import { StandardSchema, readJson } from "./functions/read-json.js";
|
|
8
|
-
import { MailMessage, Mailer } from "./mail/
|
|
8
|
+
import { MailAttachment, MailMessage, Mailer } from "./mail/mail-message.js";
|
|
9
9
|
import { JsonObject, JsonValue } from "./notifications/json-value.js";
|
|
10
10
|
import { HistoryPosition, NewNotification, StoredNotification, historyIdPattern, historyLimits } from "./notifications/history.js";
|
|
11
11
|
import { PushMessage, PushMessageError, Urgency, WebPushFields, maxTtlSeconds, pushMessage, urgencies } from "./notifications/message.js";
|
|
@@ -175,9 +175,11 @@ import { defineJob, isJobDefinition, jobDefinitions } from "./jobs/define-job.js
|
|
|
175
175
|
import { FatalJobError } from "./jobs/run-job.js";
|
|
176
176
|
import { ArgumentsPayload, EnqueueJob, JobDeclaration, JobName, JobPayload, JobRun, enqueueJob } from "./jobs/declared-job.js";
|
|
177
177
|
import { isSchedule } from "./jobs/schedule.js";
|
|
178
|
+
import { PersonalMailError, PersonalMailErrorCode } from "./personal-mail/personal-mail-error.js";
|
|
179
|
+
import { PersonalMailProviderId } from "./personal-mail/personal-mail-providers.js";
|
|
178
180
|
import { EmailComponent, EmailOptions, EmailTemplate, RenderedEmail, defineEmail } from "./mail/define-email.js";
|
|
179
181
|
import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/runtime.js";
|
|
180
182
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
181
183
|
import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
|
|
182
184
|
import { AdminAuth, CreateAuthOptions, UserCreatedHook, normalizeRoles } from "./better-auth/create-auth.js";
|
|
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 };
|
|
185
|
+
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, 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, PersonalMailError, type PersonalMailErrorCode, type PersonalMailProviderId, type PgModule, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type PngIcon, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type PushAnswer, type PushMessage, PushMessageError, type PushSender, type QueryOptions, type QueryResult, type ReadableResources, type RealtimeOptions, type RealtimePrune, type ReasoningDetail, type ReasoningEffort, type RebindOption, type RecordGroups, type RecordKey, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type SendNotification, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SocketEvents, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StatusOptions, type StoreFileInput, type StoredMember, type StoredNotification, type StoredObject, type StoredOrganization, type StoredUser, type StrayValues, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolAnnotations, type ToolCall, type ToolComment, type ToolCommentPage, type ToolComments, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type UnreadableEntry, type Urgency, type User, type UserCreatedHook, type 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
|
@@ -33,6 +33,7 @@ import { supabasePath } from "./supabase-paths.js";
|
|
|
33
33
|
import { goTruePath } from "./gotrue/keys.js";
|
|
34
34
|
import { defaultSignInPolicy, signInPolicyMethods } from "./better-auth/sign-in-policy.js";
|
|
35
35
|
import { parseRoles } from "./better-auth/parse-roles.js";
|
|
36
|
+
import { PersonalMailError } from "./personal-mail/personal-mail-error.js";
|
|
36
37
|
import { passwordLength } from "./better-auth/new-account-password.js";
|
|
37
38
|
import { readOperatorSettings } from "./better-auth/operator-provider.js";
|
|
38
39
|
import { readPlatformSignIn } from "./better-auth/platform-sign-in.js";
|
|
@@ -132,4 +133,4 @@ import { enqueueJob } from "./jobs/declared-job.js";
|
|
|
132
133
|
import { defineEmail } from "./mail/define-email.js";
|
|
133
134
|
import { startJobs } from "./jobs/runtime.js";
|
|
134
135
|
import { jobsDrainApp } from "./jobs/drain-route.js";
|
|
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 };
|
|
136
|
+
export { ConnectionsBusy, DeviceStoreError, FatalJobError, HistoryStoreError, HttpProblem, 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, 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/jobs/job-types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DecryptField } from "../encryption/decrypt-field-types.js";
|
|
2
2
|
import { StandardSchema } from "../functions/read-json.js";
|
|
3
|
-
import { Mailer } from "../mail/
|
|
3
|
+
import { Mailer } from "../mail/mail-message.js";
|
|
4
4
|
import { SendNotification } from "../notifications/send-input.js";
|
|
5
5
|
import { Db } from "@protobase/query";
|
|
6
6
|
//#region src/jobs/job-types.d.ts
|
package/dist/jobs/runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FieldDecrypter } from "../encryption/decrypt-field-types.js";
|
|
2
|
-
import { Mailer } from "../mail/
|
|
2
|
+
import { Mailer } from "../mail/mail-message.js";
|
|
3
3
|
import { JobDefinition } from "./job-types.js";
|
|
4
4
|
import { JobsEnqueuer } from "./current.js";
|
|
5
5
|
import { Db } from "@protobase/query";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/mail/composer-message.ts
|
|
2
|
+
/**
|
|
3
|
+
* `message` as Nodemailer composes it: its header fields checked, and its attachments as their bytes alone, with
|
|
4
|
+
* Nodemailer's reads of a file path or URL turned off, so no attachment can name a file on the server or a URL to fetch.
|
|
5
|
+
*/
|
|
6
|
+
const composerMessage = ({ attachments, ...message }) => {
|
|
7
|
+
checkHeaders(message.headers);
|
|
8
|
+
if (!attachments?.length) return message;
|
|
9
|
+
return {
|
|
10
|
+
...message,
|
|
11
|
+
attachments: attachments.map(({ filename, content, contentType }) => ({
|
|
12
|
+
filename,
|
|
13
|
+
content: Buffer.from(content),
|
|
14
|
+
...contentType && { contentType }
|
|
15
|
+
})),
|
|
16
|
+
disableFileAccess: true,
|
|
17
|
+
disableUrlAccess: true
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const checkHeaders = (headers = {}) => {
|
|
21
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
22
|
+
if (!/^[!-9;-~]+$/.test(name)) throw new Error(`Mail header name "${name}" is not a valid header field name`);
|
|
23
|
+
if (/[\r\n]/.test(value)) throw new Error(`Mail header ${name} has a line break; a header value is one line`);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { composerMessage };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mailer } from "./
|
|
1
|
+
import { MailAttachment, Mailer } from "./mail-message.js";
|
|
2
2
|
//#region src/mail/define-email.d.ts
|
|
3
3
|
export type EmailOptions<Data extends object> = {
|
|
4
4
|
/** Names the email in errors, such as `welcome` or `listing-alert`. */
|
|
@@ -32,10 +32,13 @@ export type EmailTemplate<Data extends object> = {
|
|
|
32
32
|
render(data: Data): Promise<RenderedEmail>;
|
|
33
33
|
/**
|
|
34
34
|
* Renders the email for `data` and sends it to `to`: through `mailer` when given, such as a job's `context.mail`,
|
|
35
|
-
*
|
|
36
|
-
*
|
|
35
|
+
* or a function's `context.personalMail`, the caller's own mailbox, otherwise through the app's SMTP server
|
|
36
|
+
* (`PROTOBASE_SMTP_URL`, `PROTOBASE_MAIL_FROM`), with the `attachments` given. Rejects when mail is off or the server
|
|
37
|
+
* refuses the message.
|
|
37
38
|
*/
|
|
38
|
-
send(to: string, data: Data, mailer?: Mailer
|
|
39
|
+
send(to: string, data: Data, mailer?: Mailer, extra?: {
|
|
40
|
+
attachments?: MailAttachment[];
|
|
41
|
+
}): Promise<void>;
|
|
39
42
|
};
|
|
40
43
|
/**
|
|
41
44
|
* An email the app sends, with typed data: its subject and a React component for its body. Protobase renders it to
|
|
@@ -27,11 +27,12 @@ const defineEmail = (options) => {
|
|
|
27
27
|
...headers && { headers }
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
|
-
const send = async (to, data, mailer = platformMailer()) => {
|
|
30
|
+
const send = async (to, data, mailer = platformMailer(), { attachments } = {}) => {
|
|
31
31
|
if (!mailer) throw new Error(`Email "${options.name}" cannot be sent: mail is off; set ${smtpUrlVariable} and ${mailFromVariable}`);
|
|
32
32
|
await mailer.send({
|
|
33
33
|
to,
|
|
34
|
-
...await render(data)
|
|
34
|
+
...await render(data),
|
|
35
|
+
...attachments && attachments.length > 0 && { attachments }
|
|
35
36
|
});
|
|
36
37
|
};
|
|
37
38
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/mail/
|
|
1
|
+
//#region src/mail/mail-message.d.ts
|
|
2
2
|
export type MailMessage = {
|
|
3
3
|
to: string;
|
|
4
4
|
subject: string;
|
|
@@ -11,6 +11,14 @@ export type MailMessage = {
|
|
|
11
11
|
* of bulk mail. A value is one line.
|
|
12
12
|
*/
|
|
13
13
|
headers?: Record<string, string>;
|
|
14
|
+
/** Files sent with the message, such as an invoice's PDF. */
|
|
15
|
+
attachments?: MailAttachment[];
|
|
16
|
+
};
|
|
17
|
+
/** A file sent with a message: its name as the recipient sees it, its bytes, and its media type, else one its name implies. */
|
|
18
|
+
export type MailAttachment = {
|
|
19
|
+
filename: string;
|
|
20
|
+
content: Uint8Array;
|
|
21
|
+
contentType?: string;
|
|
14
22
|
};
|
|
15
23
|
/** Sends one message; rejects when the server refuses it. */
|
|
16
24
|
export type Mailer = {
|
package/dist/mail/smtp-mailer.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { composerMessage } from "./composer-message.js";
|
|
1
2
|
//#region src/mail/smtp-mailer.ts
|
|
2
3
|
/**
|
|
3
4
|
* Mail over SMTP with Nodemailer: the most used Node SMTP client, maintained, with no dependencies of its
|
|
@@ -10,14 +11,13 @@
|
|
|
10
11
|
const smtpMailer = (settings) => {
|
|
11
12
|
let transport;
|
|
12
13
|
return { send: async (message) => {
|
|
13
|
-
checkHeaders(message.headers);
|
|
14
14
|
transport ??= import("nodemailer").then(({ createTransport }) => createTransport({
|
|
15
15
|
url: settings.smtpUrl,
|
|
16
16
|
name: senderDomain(settings.from)
|
|
17
17
|
}));
|
|
18
18
|
await (await transport).sendMail({
|
|
19
19
|
from: sender(settings),
|
|
20
|
-
...message
|
|
20
|
+
...composerMessage(message)
|
|
21
21
|
});
|
|
22
22
|
} };
|
|
23
23
|
};
|
|
@@ -27,11 +27,5 @@ const sender = ({ from, name }) => name ? {
|
|
|
27
27
|
} : from;
|
|
28
28
|
/** The domain of a sender address `readMailSettings` accepted, so always a dotted hostname. */
|
|
29
29
|
const senderDomain = (from) => from.slice(from.lastIndexOf("@") + 1);
|
|
30
|
-
const checkHeaders = (headers = {}) => {
|
|
31
|
-
for (const [name, value] of Object.entries(headers)) {
|
|
32
|
-
if (!/^[!-9;-~]+$/.test(name)) throw new Error(`Mail header name "${name}" is not a valid header field name`);
|
|
33
|
-
if (/[\r\n]/.test(value)) throw new Error(`Mail header ${name} has a line break; a header value is one line`);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
30
|
//#endregion
|
|
37
31
|
export { smtpMailer };
|
package/dist/package.js
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { PersonalMailError } from "./personal-mail-error.js";
|
|
2
|
+
import { rfc822Message } from "./rfc822-message.js";
|
|
3
|
+
//#region src/personal-mail/gmail.ts
|
|
4
|
+
/** The Gmail API's scope that sends mail and nothing else: no reading of the mailbox. */
|
|
5
|
+
const gmailSendScope = "https://www.googleapis.com/auth/gmail.send";
|
|
6
|
+
/** Its upload endpoint takes the message as it is, up to 35 MB, where the JSON one takes it base64-encoded. */
|
|
7
|
+
const gmailSendUrl = "https://gmail.googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=media";
|
|
8
|
+
/**
|
|
9
|
+
* Gmail, linked through Google sign-in: offline access, so Google gives a refresh token, asked with `prompt=consent`
|
|
10
|
+
* so it gives one again on a second link. Gmail sets the From header to the linked address.
|
|
11
|
+
*/
|
|
12
|
+
const gmail = (fetcher = (...args) => fetch(...args)) => ({
|
|
13
|
+
id: "gmail",
|
|
14
|
+
name: "Gmail",
|
|
15
|
+
signInProvider: "google",
|
|
16
|
+
scopes: [gmailSendScope],
|
|
17
|
+
linkParams: {
|
|
18
|
+
access_type: "offline",
|
|
19
|
+
prompt: "consent"
|
|
20
|
+
},
|
|
21
|
+
send: async (message, accessToken) => {
|
|
22
|
+
const body = await rfc822Message(message);
|
|
23
|
+
const response = await fetcher(gmailSendUrl, {
|
|
24
|
+
method: "POST",
|
|
25
|
+
headers: {
|
|
26
|
+
authorization: `Bearer ${accessToken}`,
|
|
27
|
+
"content-type": "message/rfc822"
|
|
28
|
+
},
|
|
29
|
+
body: new Uint8Array(body)
|
|
30
|
+
});
|
|
31
|
+
if (response.ok) return;
|
|
32
|
+
if (response.status === 401 || response.status === 403 && await gmailReason(response) === "insufficientPermissions") throw new PersonalMailError("link_expired", "gmail");
|
|
33
|
+
throw new Error(`Gmail refused the message: ${response.status} ${response.statusText}`);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const gmailReason = async (response) => {
|
|
37
|
+
if (!response.headers.get("content-type")?.includes("json")) return;
|
|
38
|
+
const body = await response.json();
|
|
39
|
+
const reasons = [...body.error?.errors ?? [], ...body.error?.details ?? []].map((entry) => entry.reason);
|
|
40
|
+
return reasons.includes("insufficientPermissions") || reasons.includes("ACCESS_TOKEN_SCOPE_INSUFFICIENT") ? "insufficientPermissions" : reasons[0];
|
|
41
|
+
};
|
|
42
|
+
//#endregion
|
|
43
|
+
export { gmail, gmailSendScope, gmailSendUrl };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { PersonalMailError } from "./personal-mail-error.js";
|
|
2
|
+
import { APIError } from "better-auth/api";
|
|
3
|
+
//#region src/personal-mail/linked-accounts.ts
|
|
4
|
+
const storedScopes = (scope) => (scope ?? "").split(/[\s,]+/).filter(Boolean);
|
|
5
|
+
/**
|
|
6
|
+
* The accounts Better Auth keeps, with the tokens it stores, decrypted when `encryptOAuthTokens` is on. Its
|
|
7
|
+
* `getAccessToken` refreshes a token within five seconds of expiry with the provider's refresh token and stores the new
|
|
8
|
+
* one; when the provider refuses the refresh, as for a revoked grant, that is `link_expired`.
|
|
9
|
+
*/
|
|
10
|
+
const betterAuthLinkedAccounts = (auth) => ({
|
|
11
|
+
accounts: async (userId) => {
|
|
12
|
+
return (await (await auth.$context).internalAdapter.findAccounts(userId)).map((account) => ({
|
|
13
|
+
id: account.id,
|
|
14
|
+
providerId: account.providerId,
|
|
15
|
+
scopes: storedScopes(account.scope)
|
|
16
|
+
}));
|
|
17
|
+
},
|
|
18
|
+
accessToken: async (userId, account, provider) => {
|
|
19
|
+
const accessToken = await validAccessToken(auth, userId, account.id, provider);
|
|
20
|
+
if (!accessToken) throw new PersonalMailError("link_expired", provider);
|
|
21
|
+
return accessToken;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
const validAccessToken = async (auth, userId, accountId, provider) => {
|
|
25
|
+
try {
|
|
26
|
+
return (await auth.api.getAccessToken({ body: {
|
|
27
|
+
accountId,
|
|
28
|
+
userId
|
|
29
|
+
} })).accessToken;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (error instanceof APIError && error.body?.code === "FAILED_TO_GET_ACCESS_TOKEN") throw new PersonalMailError("link_expired", provider);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
export { betterAuthLinkedAccounts };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HttpProblem } from "../problem.js";
|
|
2
|
+
//#region src/personal-mail/personal-mail-error.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Why a message cannot go out from someone's own mailbox: `not_linked`, they linked no mail provider of the app's, or
|
|
5
|
+
* linked the sign-in account without allowing it to send mail; `link_expired`, the provider no longer honours the
|
|
6
|
+
* link, as when they revoked it or its refresh token expired, so they link it again.
|
|
7
|
+
*/
|
|
8
|
+
export type PersonalMailErrorCode = 'not_linked' | 'link_expired';
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when a message cannot go out from someone's own mailbox, and nothing was sent. Out of a function it answers as
|
|
11
|
+
* a 409 problem whose `code` and `provider` say which, so the app can offer to link the mailbox; in code,
|
|
12
|
+
* `error instanceof PersonalMailError` and its `code` tell.
|
|
13
|
+
*/
|
|
14
|
+
export declare class PersonalMailError extends HttpProblem {
|
|
15
|
+
readonly code: PersonalMailErrorCode;
|
|
16
|
+
/** The mail provider at fault, such as `gmail`; none when nothing is linked. */
|
|
17
|
+
readonly provider?: string | undefined;
|
|
18
|
+
constructor(code: PersonalMailErrorCode,
|
|
19
|
+
/** The mail provider at fault, such as `gmail`; none when nothing is linked. */
|
|
20
|
+
provider?: string | undefined);
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HttpProblem } from "../problem.js";
|
|
2
|
+
//#region src/personal-mail/personal-mail-error.ts
|
|
3
|
+
const details = {
|
|
4
|
+
not_linked: "Link a mailbox to send mail from it",
|
|
5
|
+
link_expired: "The link to your mailbox has expired: link it again to send mail from it"
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Thrown when a message cannot go out from someone's own mailbox, and nothing was sent. Out of a function it answers as
|
|
9
|
+
* a 409 problem whose `code` and `provider` say which, so the app can offer to link the mailbox; in code,
|
|
10
|
+
* `error instanceof PersonalMailError` and its `code` tell.
|
|
11
|
+
*/
|
|
12
|
+
var PersonalMailError = class extends HttpProblem {
|
|
13
|
+
code;
|
|
14
|
+
provider;
|
|
15
|
+
constructor(code, provider) {
|
|
16
|
+
super(409, `personal-mail-${code.replace("_", "-")}`, "Conflict", details[code], {
|
|
17
|
+
code,
|
|
18
|
+
...provider && { provider }
|
|
19
|
+
});
|
|
20
|
+
this.code = code;
|
|
21
|
+
this.provider = provider;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { PersonalMailError };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MailMessage } from "../mail/mail-message.js";
|
|
2
|
+
//#region src/personal-mail/personal-mail-provider.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* A mail provider people link their own mailbox with, through the app's sign-in provider of the same company: linking
|
|
5
|
+
* asks the sign-in provider for `scopes` with `linkParams`, the sign-in account Better Auth keeps holds the tokens, and
|
|
6
|
+
* `send` sends a message with its access token.
|
|
7
|
+
*/
|
|
8
|
+
export type PersonalMailProvider = {
|
|
9
|
+
/** Its id, such as `gmail`, as `auth.personalMail` names it. */
|
|
10
|
+
id: string;
|
|
11
|
+
/** The name the account page shows, such as `Gmail`. */
|
|
12
|
+
name: string;
|
|
13
|
+
/** The sign-in provider whose account holds the tokens, such as `google`: one of the app's `socialProviders`. */
|
|
14
|
+
signInProvider: string;
|
|
15
|
+
/** The scopes linking asks for, which the account must hold to send. */
|
|
16
|
+
scopes: string[];
|
|
17
|
+
/** More authorization parameters of the link, such as those that ask for a refresh token. */
|
|
18
|
+
linkParams: Record<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Sends `message` from the mailbox. Rejects with a `PersonalMailError` of `link_expired` when the provider refuses the
|
|
21
|
+
* token, and with an error naming the status for anything else it refuses.
|
|
22
|
+
*/
|
|
23
|
+
send: (message: MailMessage, accessToken: string) => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PersonalMailProvider } from "./personal-mail-provider.js";
|
|
2
|
+
//#region src/personal-mail/personal-mail-providers.d.ts
|
|
3
|
+
/** The mail providers Protobase links mailboxes with, by the id `auth.personalMail` names them with. */
|
|
4
|
+
export declare const personalMailProviders: {
|
|
5
|
+
gmail: (fetcher?: typeof fetch) => PersonalMailProvider;
|
|
6
|
+
};
|
|
7
|
+
export type PersonalMailProviderId = keyof typeof personalMailProviders;
|
|
8
|
+
//#endregion
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { gmail } from "./gmail.js";
|
|
2
|
+
//#region src/personal-mail/personal-mail-providers.ts
|
|
3
|
+
/** The mail providers Protobase links mailboxes with, by the id `auth.personalMail` names them with. */
|
|
4
|
+
const personalMailProviders = { gmail };
|
|
5
|
+
/**
|
|
6
|
+
* The providers of `ids`, each checked against the app's sign-in providers: linking one goes through its sign-in
|
|
7
|
+
* provider, so an app without it is a configuration error at startup.
|
|
8
|
+
*/
|
|
9
|
+
const resolvePersonalMail = (ids, signInProviders) => ids.map((id) => {
|
|
10
|
+
if (!Object.hasOwn(personalMailProviders, id)) throw new Error(`auth.personalMail: "${id}" is not a mail provider; use one of ${Object.keys(personalMailProviders).join(", ")}`);
|
|
11
|
+
const provider = personalMailProviders[id]();
|
|
12
|
+
if (!signInProviders.includes(provider.signInProvider)) throw new Error(`auth.personalMail: ${provider.name} links through the sign-in provider "${provider.signInProvider}"; add it to auth.socialProviders`);
|
|
13
|
+
return provider;
|
|
14
|
+
});
|
|
15
|
+
//#endregion
|
|
16
|
+
export { personalMailProviders, resolvePersonalMail };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { PersonalMailError } from "./personal-mail-error.js";
|
|
2
|
+
//#region src/personal-mail/personal-mailer.ts
|
|
3
|
+
/** The mail provider `userId` linked, of the app's `providers` in their order, with the account that holds its tokens. */
|
|
4
|
+
const linkedProvider = async (accounts, providers, userId) => {
|
|
5
|
+
const linked = await accounts.accounts(userId);
|
|
6
|
+
for (const provider of providers) {
|
|
7
|
+
const account = linked.find((candidate) => candidate.providerId === provider.signInProvider && provider.scopes.every((scope) => candidate.scopes.includes(scope)));
|
|
8
|
+
if (account) return {
|
|
9
|
+
provider,
|
|
10
|
+
account
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Mail from `userId`'s own mailbox: each message goes out through the mail provider they linked, with an access token
|
|
16
|
+
* refreshed when it expired. Rejects with a `PersonalMailError` and sends nothing when they linked none (`not_linked`)
|
|
17
|
+
* or the provider no longer honours the link (`link_expired`).
|
|
18
|
+
*/
|
|
19
|
+
const personalMailer = (accounts, providers, userId) => ({ send: async (message) => {
|
|
20
|
+
const linked = await linkedProvider(accounts, providers, userId);
|
|
21
|
+
if (!linked) throw new PersonalMailError("not_linked");
|
|
22
|
+
const accessToken = await accounts.accessToken(userId, linked.account, linked.provider.id);
|
|
23
|
+
await linked.provider.send(message, accessToken);
|
|
24
|
+
} });
|
|
25
|
+
//#endregion
|
|
26
|
+
export { linkedProvider, personalMailer };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { composerMessage } from "../mail/composer-message.js";
|
|
2
|
+
//#region src/personal-mail/rfc822-message.ts
|
|
3
|
+
/**
|
|
4
|
+
* `message` as an RFC 5322 message, attachments and all, the way the SMTP mailer composes it, with Nodemailer's
|
|
5
|
+
* composer. Without `from`, the provider fills in the From header with the mailbox it sends from.
|
|
6
|
+
*/
|
|
7
|
+
const rfc822Message = async (message, from) => {
|
|
8
|
+
const { default: MailComposer } = await import("nodemailer/lib/mail-composer");
|
|
9
|
+
return new MailComposer({
|
|
10
|
+
...from && { from },
|
|
11
|
+
...composerMessage(message)
|
|
12
|
+
}).compile().build();
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { rfc822Message };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protobase/server",
|
|
3
|
-
"version": "0.62.
|
|
3
|
+
"version": "0.62.5",
|
|
4
4
|
"description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -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.62.
|
|
46
|
-
"@protobase/query": "0.62.
|
|
47
|
-
"@protobase/schema": "0.62.
|
|
45
|
+
"@protobase/layout": "0.62.5",
|
|
46
|
+
"@protobase/query": "0.62.5",
|
|
47
|
+
"@protobase/schema": "0.62.5",
|
|
48
48
|
"@react-email/render": "^2.1.0",
|
|
49
49
|
"@scalar/hono-api-reference": "^0.12.10",
|
|
50
50
|
"@sentry/core": "^11.7.0",
|