@protobase/server 0.25.10 → 0.25.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ //#region src/api-keys/api-key-settings.d.ts
2
+ /**
3
+ * The app's two keys, for clients that call it the way they call Supabase. `publishable_key` is safe in a browser and
4
+ * makes a request anonymous or its signed-in user's; `secret_key` stays on servers and makes a request the app's own.
5
+ * Each falls back to `PROTOBASE_PUBLISHABLE_KEY` and `PROTOBASE_SECRET_KEY`; without either, nothing is admitted by key.
6
+ */
7
+ export type ApiKeysOptions = {
8
+ publishable_key?: string;
9
+ secret_key?: string;
10
+ };
11
+ export type ApiKeys = {
12
+ publishable?: string;
13
+ secret?: string;
14
+ };
15
+ export declare const apiKeyVariables: {
16
+ readonly publishable_key: "PROTOBASE_PUBLISHABLE_KEY";
17
+ readonly secret_key: "PROTOBASE_SECRET_KEY";
18
+ };
19
+ /**
20
+ * The keys that are set, unless the option is `false`. A publishable key that looks like a secret one, the other way
21
+ * round, or both the same stop the server at startup, without printing the keys.
22
+ */
23
+ export declare const apiKeySettings: (option: ApiKeysOptions | false | undefined, env: Record<string, string | undefined>) => ApiKeys;
24
+ //#endregion
@@ -0,0 +1,32 @@
1
+ //#region src/api-keys/api-key-settings.ts
2
+ const apiKeyVariables = {
3
+ publishable_key: "PROTOBASE_PUBLISHABLE_KEY",
4
+ secret_key: "PROTOBASE_SECRET_KEY"
5
+ };
6
+ const wrongPrefix = {
7
+ publishable_key: "sb_secret_",
8
+ secret_key: "sb_publishable_"
9
+ };
10
+ /**
11
+ * The keys that are set, unless the option is `false`. A publishable key that looks like a secret one, the other way
12
+ * round, or both the same stop the server at startup, without printing the keys.
13
+ */
14
+ const apiKeySettings = (option, env) => {
15
+ if (option === false) return {};
16
+ const read = (name) => {
17
+ const value = (option?.[name] ?? env[apiKeyVariables[name]])?.trim();
18
+ if (!value) return void 0;
19
+ const source = option?.[name] === void 0 ? apiKeyVariables[name] : `The ${name} option`;
20
+ if (value.startsWith(wrongPrefix[name])) throw new Error(`${source} starts with ${wrongPrefix[name]}, the other key's prefix; swap the two keys`);
21
+ return value;
22
+ };
23
+ const publishable = read("publishable_key");
24
+ const secret = read("secret_key");
25
+ if (publishable !== void 0 && publishable === secret) throw new Error("The publishable and the secret key are the same; the secret key must be one of its own");
26
+ return {
27
+ ...publishable && { publishable },
28
+ ...secret && { secret }
29
+ };
30
+ };
31
+ //#endregion
32
+ export { apiKeySettings, apiKeyVariables };
@@ -0,0 +1,35 @@
1
+ import { ApiKeys } from "./api-key-settings.js";
2
+ import { JWTPayload } from "jose";
3
+ //#region src/api-keys/resolve-caller.d.ts
4
+ /**
5
+ * Who a key-admitted request runs as. `anon` and `authenticated` are the database roles of the same names; `app` is
6
+ * the app's own role, the one that owns its tables. `claims` are those of the signed-in user's token, or for the keys
7
+ * alone the `role` claim that Supabase gives them, so `auth.jwt()` reads the same.
8
+ */
9
+ export type Caller = {
10
+ role: 'anon';
11
+ claims: {
12
+ role: 'anon';
13
+ };
14
+ } | {
15
+ role: 'authenticated';
16
+ claims: JWTPayload;
17
+ } | {
18
+ role: 'app';
19
+ claims: {
20
+ role: 'service_role';
21
+ };
22
+ };
23
+ export type CallerOptions = {
24
+ keys: ApiKeys;
25
+ /** Verifies a user's token against the app's key set and returns its claims, such as `jwtVerifier(betterAuthTokens(...))`. */
26
+ verify: (token: string) => Promise<JWTPayload>;
27
+ };
28
+ /**
29
+ * Resolves the `apikey` header and `Authorization: Bearer` of a request to its caller. The key picks the role: the
30
+ * publishable key is `anon`, the secret key `app`. A user's token in the bearer makes either `authenticated` with its
31
+ * claims. A bearer that is no token must be the key itself, as supabase-js sends it when nobody is signed in. A
32
+ * missing or wrong key, a wrong bearer or a token that does not verify or names no user is a 401 problem.
33
+ */
34
+ export declare const apiKeyCaller: (options: CallerOptions) => (request: Request) => Promise<Caller>;
35
+ //#endregion
@@ -0,0 +1,39 @@
1
+ import { unauthorized } from "../problem.js";
2
+ import { createHash, timingSafeEqual } from "node:crypto";
3
+ //#region src/api-keys/resolve-caller.ts
4
+ const digest = (text) => createHash("sha256").update(text).digest();
5
+ const sameKey = (given, key) => key !== void 0 && timingSafeEqual(digest(given), digest(key));
6
+ const isJwt = (token) => token.split(".").length === 3;
7
+ /**
8
+ * Resolves the `apikey` header and `Authorization: Bearer` of a request to its caller. The key picks the role: the
9
+ * publishable key is `anon`, the secret key `app`. A user's token in the bearer makes either `authenticated` with its
10
+ * claims. A bearer that is no token must be the key itself, as supabase-js sends it when nobody is signed in. A
11
+ * missing or wrong key, a wrong bearer or a token that does not verify or names no user is a 401 problem.
12
+ */
13
+ const apiKeyCaller = (options) => async (request) => {
14
+ const key = request.headers.get("apikey")?.trim();
15
+ if (!key) throw unauthorized("Send the app's publishable or secret key in the apikey header");
16
+ const publishable = sameKey(key, options.keys.publishable);
17
+ if (!publishable && !sameKey(key, options.keys.secret)) throw unauthorized("The apikey header holds no key of this app");
18
+ const header = request.headers.get("authorization");
19
+ const [scheme, bearer] = header?.split(" ") ?? [];
20
+ if (header !== null && (scheme?.toLowerCase() !== "bearer" || !bearer)) throw unauthorized("Send a bearer token in the Authorization header");
21
+ if (bearer !== void 0 && isJwt(bearer)) {
22
+ const claims = await options.verify(bearer);
23
+ if (!claims.sub) throw unauthorized("The bearer token has no subject");
24
+ return {
25
+ role: "authenticated",
26
+ claims
27
+ };
28
+ }
29
+ if (bearer !== void 0 && !sameKey(bearer, key)) throw unauthorized("The bearer is neither a token nor the key in the apikey header");
30
+ return publishable ? {
31
+ role: "anon",
32
+ claims: { role: "anon" }
33
+ } : {
34
+ role: "app",
35
+ claims: { role: "service_role" }
36
+ };
37
+ };
38
+ //#endregion
39
+ export { apiKeyCaller };
@@ -1,5 +1,5 @@
1
1
  import { Authenticator, TenantValue } from "../types.js";
2
- import { JWTVerifyGetKey } from "jose";
2
+ import { JWTPayload, JWTVerifyGetKey } from "jose";
3
3
  //#region src/auth/jwt.d.ts
4
4
  export type JwtOptions = {
5
5
  /** JWKS endpoint of the identity provider; or pass `keys`, for example `createLocalJWKSet`. */
@@ -20,6 +20,9 @@ export type JwtOptions = {
20
20
  /** A fixed tenant (or resolver) used instead of any claim, for single-tenant deployments. */
21
21
  tenant?: TenantValue | (() => Promise<TenantValue | undefined>);
22
22
  };
23
+ export type JwtVerifyOptions = Pick<JwtOptions, 'jwksUrl' | 'keys' | 'issuer' | 'audience' | 'algorithms'>;
24
+ /** Verifies a JWT against a JWKS and returns its claims; a token that does not verify is a 401 problem. */
25
+ export declare const jwtVerifier: (options: JwtVerifyOptions) => (token: string) => Promise<JWTPayload>;
23
26
  /** Verifies `Authorization: Bearer <jwt>` against a JWKS; `sub` is the user id. Without the header, `MissingCredentials`. */
24
27
  export declare const jwtAuthenticator: (options: JwtOptions) => Authenticator;
25
28
  //#endregion
package/dist/auth/jwt.js CHANGED
@@ -17,26 +17,33 @@ const rolesOf = (claim) => {
17
17
  if (typeof claim === "string") return claim.split(/[\s,]+/).filter(Boolean);
18
18
  return Array.isArray(claim) ? claim.filter((role) => typeof role === "string") : [];
19
19
  };
20
- /** Verifies `Authorization: Bearer <jwt>` against a JWKS; `sub` is the user id. Without the header, `MissingCredentials`. */
21
- const jwtAuthenticator = (options) => {
22
- const { rolesClaim = "roles", tenantClaim = "tenant" } = options;
20
+ /** Verifies a JWT against a JWKS and returns its claims; a token that does not verify is a 401 problem. */
21
+ const jwtVerifier = (options) => {
23
22
  const keys = options.keys ?? (options.jwksUrl ? createRemoteJWKSet(new URL(options.jwksUrl)) : void 0);
24
23
  if (!keys) throw new Error("jwtAuthenticator needs jwksUrl or keys");
25
- return async (request) => {
26
- const header = request.headers.get("authorization");
27
- if (header === null) throw new MissingCredentials("Send a bearer token in the Authorization header");
28
- const [scheme, token] = header.split(" ");
29
- if (scheme?.toLowerCase() !== "bearer" || !token) throw unauthorized("Send a bearer token in the Authorization header");
30
- const verified = await jwtVerify(token, keys, {
24
+ return async (token) => {
25
+ return (await jwtVerify(token, keys, {
31
26
  algorithms: options.algorithms ?? asymmetric,
32
27
  ...options.issuer && { issuer: options.issuer },
33
28
  ...options.audience && { audience: options.audience }
34
29
  }).catch((error) => {
35
30
  if (error instanceof errors.JOSEError) throw unauthorized("The bearer token is invalid or expired");
36
31
  throw error;
37
- });
38
- const { sub, [tenantClaim]: tenant, [rolesClaim]: roles } = verified.payload;
39
- const extraRoles = options.extraRolesClaim === void 0 ? [] : rolesOf(verified.payload[options.extraRolesClaim]);
32
+ })).payload;
33
+ };
34
+ };
35
+ /** Verifies `Authorization: Bearer <jwt>` against a JWKS; `sub` is the user id. Without the header, `MissingCredentials`. */
36
+ const jwtAuthenticator = (options) => {
37
+ const { rolesClaim = "roles", tenantClaim = "tenant" } = options;
38
+ const verify = jwtVerifier(options);
39
+ return async (request) => {
40
+ const header = request.headers.get("authorization");
41
+ if (header === null) throw new MissingCredentials("Send a bearer token in the Authorization header");
42
+ const [scheme, token] = header.split(" ");
43
+ if (scheme?.toLowerCase() !== "bearer" || !token) throw unauthorized("Send a bearer token in the Authorization header");
44
+ const payload = await verify(token);
45
+ const { sub, [tenantClaim]: tenant, [rolesClaim]: roles } = payload;
46
+ const extraRoles = options.extraRolesClaim === void 0 ? [] : rolesOf(payload[options.extraRolesClaim]);
40
47
  if (!sub) throw unauthorized("The bearer token has no subject");
41
48
  const claimed = typeof tenant === "string" || typeof tenant === "number" ? tenant : void 0;
42
49
  const tenantValue = options.tenant === void 0 ? claimed : typeof options.tenant === "function" ? await options.tenant() : options.tenant;
@@ -50,4 +57,4 @@ const jwtAuthenticator = (options) => {
50
57
  };
51
58
  };
52
59
  //#endregion
53
- export { jwtAuthenticator };
60
+ export { jwtAuthenticator, jwtVerifier };
@@ -1,5 +1,6 @@
1
1
  import { AdminAuth } from "./create-auth.js";
2
2
  import { Authenticator, TenantValue } from "../types.js";
3
+ import { JwtVerifyOptions } from "../auth/jwt.js";
3
4
  import { TrustedApp } from "./app-tokens.js";
4
5
  import { JwksCacheOptions } from "./jwks-cache.js";
5
6
  //#region src/better-auth/authenticator.d.ts
@@ -19,6 +20,10 @@ export type BetterAuthAuthenticatorOptions = {
19
20
  /** Other Protobase apps whose users this API admits with their own tokens, so their admin apps can draw its resources (see `TrustedApp`). */
20
21
  apps?: TrustedApp[];
21
22
  };
23
+ /** How the tokens of this Better Auth instance verify: its key set, and its issuer as both issuer and audience. */
24
+ export declare const betterAuthTokens: (options: Pick<BetterAuthAuthenticatorOptions, "auth" | "jwksUrl" | "issuer" | "cache">) => JwtVerifyOptions & {
25
+ issuer: string;
26
+ };
22
27
  /**
23
28
  * Verifies the bearer JWT that Better Auth's jwt plugin issues. `sub` is the user id, the `role` claim (a comma
24
29
  * separated string from the admin plugin) becomes `roles`. With organizations, the `org` claim is the tenant and the
@@ -3,6 +3,17 @@ import { jwtAuthenticator } from "../auth/jwt.js";
3
3
  import { withTrustedApps } from "./app-tokens.js";
4
4
  import { cachedKeys } from "./jwks-cache.js";
5
5
  //#region src/better-auth/authenticator.ts
6
+ /** How the tokens of this Better Auth instance verify: its key set, and its issuer as both issuer and audience. */
7
+ const betterAuthTokens = (options) => {
8
+ const issuer = options.issuer ?? options.auth?.issuer;
9
+ if (!issuer) throw new Error("betterAuthAuthenticator needs `issuer` (or an `auth` instance with a baseURL)");
10
+ if (!options.auth && !options.jwksUrl) throw new Error("betterAuthAuthenticator needs `auth` or `jwksUrl`");
11
+ return {
12
+ ...options.auth ? { keys: cachedKeys(() => options.auth.api.getJwks(), options.cache) } : { jwksUrl: options.jwksUrl },
13
+ issuer,
14
+ audience: issuer
15
+ };
16
+ };
6
17
  /**
7
18
  * Verifies the bearer JWT that Better Auth's jwt plugin issues. `sub` is the user id, the `role` claim (a comma
8
19
  * separated string from the admin plugin) becomes `roles`. With organizations, the `org` claim is the tenant and the
@@ -10,14 +21,11 @@ import { cachedKeys } from "./jwks-cache.js";
10
21
  * role, is left out. With `apps`, the tokens of those apps are admitted too, with the roles each gives its users here.
11
22
  */
12
23
  const betterAuthAuthenticator = (options) => {
13
- const issuer = options.issuer ?? options.auth?.issuer;
14
- if (!issuer) throw new Error("betterAuthAuthenticator needs `issuer` (or an `auth` instance with a baseURL)");
15
- if (!options.auth && !options.jwksUrl) throw new Error("betterAuthAuthenticator needs `auth` or `jwksUrl`");
24
+ const tokens = betterAuthTokens(options);
25
+ const { issuer } = tokens;
16
26
  const organizations = options.organizations ?? Boolean(options.auth?.organizations);
17
27
  const verify = jwtAuthenticator({
18
- ...options.auth ? { keys: cachedKeys(() => options.auth.api.getJwks(), options.cache) } : { jwksUrl: options.jwksUrl },
19
- issuer,
20
- audience: issuer,
28
+ ...tokens,
21
29
  rolesClaim: "role",
22
30
  ...organizations && {
23
31
  tenantClaim: "org",
@@ -39,4 +47,4 @@ const betterAuthAuthenticator = (options) => {
39
47
  }, issuer, options.apps ?? []);
40
48
  };
41
49
  //#endregion
42
- export { betterAuthAuthenticator };
50
+ export { betterAuthAuthenticator, betterAuthTokens };
package/dist/index.d.ts CHANGED
@@ -45,10 +45,12 @@ import { isBackgroundWork, runInBackground } from "./background-work.js";
45
45
  import { checkViewQueries } from "./check-view-queries.js";
46
46
  import { ProjectConfig, defineConfig, mergeConfig } from "./project-config.js";
47
47
  import { consoleAuditQueue } from "./audit/console-queue.js";
48
- import { JwtOptions, jwtAuthenticator } from "./auth/jwt.js";
48
+ import { JwtOptions, JwtVerifyOptions, jwtAuthenticator, jwtVerifier } from "./auth/jwt.js";
49
+ import { ApiKeys, ApiKeysOptions, apiKeySettings, apiKeyVariables } from "./api-keys/api-key-settings.js";
50
+ import { Caller, CallerOptions, apiKeyCaller } from "./api-keys/resolve-caller.js";
49
51
  import { HttpProblem, MissingCredentials, badRequest, forbidden, notFound, unauthorized } from "./problem.js";
50
52
  import { TrustedApp, withTrustedApps } from "./better-auth/app-tokens.js";
51
- import { BetterAuthAuthenticatorOptions, betterAuthAuthenticator } from "./better-auth/authenticator.js";
53
+ import { BetterAuthAuthenticatorOptions, betterAuthAuthenticator, betterAuthTokens } from "./better-auth/authenticator.js";
52
54
  import { parseRoles } from "./better-auth/parse-roles.js";
53
55
  import { LinkedAccount, NewUser, StoredUser, createUser, deleteUser, hasUsers, listUsers, roleChoices, setUserBanned, setUserRole } from "./better-auth/users.js";
54
56
  import { IssueTokenOptions, issueToken, maxTokenTtlSeconds } from "./better-auth/tokens.js";
@@ -93,4 +95,4 @@ import { FatalJobError } from "./jobs/run-job.js";
93
95
  import { DrainResult, JobsRuntime, StartJobsOptions, startJobs } from "./jobs/runtime.js";
94
96
  import { jobsDrainApp } from "./jobs/drain-route.js";
95
97
  import { checkJobsSchema, jobsSchema, jobsSchemaMigration } from "./jobs/schema.js";
96
- export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSource, type HistoryOptions, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type MemberInput, MissingCredentials, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
98
+ export { type Admin, type AdminAuth, type AdminOptions, type ApiFunction, type ApiKeys, type ApiKeysOptions, type ApprovalAnswer, type ApprovalRequest, type AssistantBackend, type AssistantOptions, type AssistantSettings, type AssistantTool, type AuditEvent, type AuditQueue, type Authenticator, type BetterAuthAuthenticatorOptions, type Caller, type CallerOptions, type CapturedRow, type ChatMessage, type ChatTextPart, type CheckAiInput, type CleanupEntry, type CleanupReport, type CleanupSchedule, type CoalescedChange, type CommentItem, type CommentUsers, type Completion, type CompletionOptions, type Conversation, type ConversationRecord, type ConversationStore, type ConversationsOptions, type CorsOptions, type CorsOrigins, type CreateAdminInput, type CreateAuthOptions, type DrainResult, type EmailComponent, type EmailOptions, type EmailTemplate, type EnqueueOptions, type ErrorReporter, type ErrorReportingOptions, type ErrorReportingSettings, type EventData, type EventsOptions, FatalJobError, type FileCleanupInput, type FileLimits, type FileObject, type FileProvider, type FileRef, type FileStore, type FileVariantObject, type FilesOptions, type FunctionApp, type FunctionCaller, type FunctionContext, type FunctionEnv, type FunctionHandler, type FunctionOptions, type FunctionRecords, type FunctionSource, type HistoryOptions, HttpProblem, type IssueTokenOptions, type JobContext, type JobDefinition, type JobOptions, type JobsRuntime, type JwtOptions, type JwtVerifyOptions, type LinkedAccount, type ListParams, type LocalFilesOptions, type MailMessage, type Mailer, type MapLayer, type MapOptions, type MapSettings, type MemberInput, MissingCredentials, ModelError, type ModelSettings, type NewOrganization, type NewUser, type OperatorProvider, type OrganizationRole, type OrganizationsOptions, type PipelineHook, type PlatformSignIn, type PluginOption, type PluginRef, type ProjectConfig, type ProtectedFunctionOptions, type PublicFunctionContext, type PublicFunctionEnv, type PublicFunctionHandler, type PublicFunctionOptions, type QueryOptions, type QueryResult, type ReasoningDetail, type ReasoningEffort, type RecordKeyInput, type RecordPage, type RenderedEmail, type ResourceChange, type ResourceSource, type RoleDefinition, type RolesInput, type RunContext, type RuntimeOptions, type S3Bucket, type S3FilesOptions, type S3ListPage, type S3Object, type ScanGuardMode, type ScheduledDelete, type Session, type SessionOrganization, type Sharp, type SignInPolicy, type SignInRule, type SignatureOptions, type SourceOption, type SourceRef, type StaffAccessRule, type StaffSignIn, type StandardSchema, type StandardWebhookOptions, type StartJobsOptions, type StoreFileInput, type StoredMember, type StoredObject, type StoredOrganization, type StoredUser, type SubscriptionDefinition, type SubscriptionEvent, type SubscriptionOptions, type TenantValue, type ToolCall, type ToolContext, type ToolRecord, type ToolRecords, type ToolSpec, type TrustedApp, type TurnOptions, type User, type UserCreatedHook, type ViewSource, type WebhooksOptions, type WidgetOptions, type WriteEvent, type WriteOperation, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
package/dist/index.js CHANGED
@@ -49,9 +49,11 @@ import { handleDroppedConnections } from "./dropped-connections.js";
49
49
  import { configExports } from "./resource-source.js";
50
50
  import { checkViewQueries } from "./check-view-queries.js";
51
51
  import { defineConfig, mergeConfig } from "./project-config.js";
52
- import { jwtAuthenticator } from "./auth/jwt.js";
52
+ import { jwtAuthenticator, jwtVerifier } from "./auth/jwt.js";
53
+ import { apiKeySettings, apiKeyVariables } from "./api-keys/api-key-settings.js";
54
+ import { apiKeyCaller } from "./api-keys/resolve-caller.js";
53
55
  import { withTrustedApps } from "./better-auth/app-tokens.js";
54
- import { betterAuthAuthenticator } from "./better-auth/authenticator.js";
56
+ import { betterAuthAuthenticator, betterAuthTokens } from "./better-auth/authenticator.js";
55
57
  import { issueToken, maxTokenTtlSeconds } from "./better-auth/tokens.js";
56
58
  import { authSchemaMigration, checkAuthSchema } from "./better-auth/auth-schema.js";
57
59
  import { checkComputed, computedMigration } from "./computed/computed-schema.js";
@@ -70,4 +72,4 @@ import { aspectRatio, fileSize, fileType, imageSize, processor } from "./files/p
70
72
  import { defineEmail } from "./mail/define-email.js";
71
73
  import { startJobs } from "./jobs/runtime.js";
72
74
  import { jobsDrainApp } from "./jobs/drain-route.js";
73
- export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
75
+ export { FatalJobError, HttpProblem, MissingCredentials, ModelError, addAppRoleToOwners, addMember, apiKeyCaller, apiKeySettings, apiKeyVariables, aspectRatio, assistantProtocolRoutes, assistantRoles, assistantSettings, assistantVariables, authSchemaMigration, badRequest, beforeSignInPluginsVariable, betterAuthAuthenticator, betterAuthTokens, changesMigration, checkAi, checkAuthSchema, checkChanges, checkComments, checkComputed, checkJobsSchema, checkSourceNames, checkViewQueries, checkWebhooksSchema, coalesce, commentsMigration, computedMigration, configExports, consoleAuditQueue, conversationKey, createAdmin, createAuth, createConversations, createFileCleanup, createOrganization, createUser, defaultSignInPolicy, defineConfig, defineEmail, defineFunction, defineJob, defineTool, deleteUser, errorReportingSettings, errorReportingVariable, eventMatcher, fileConversationStore, fileSize, fileType, forbidden, formatUri, functionApp, handleDroppedConnections, hasUsers, imageSize, isBackgroundWork, isCaptured, isJobDefinition, issueToken, jobDefinitions, jobsDrainApp, jobsSchema, jobsSchemaMigration, jwtAuthenticator, jwtVerifier, limitedFileStore, listOrganizations, listUsers, localFileStore, localFiles, mapSettings, mapStyleUrl, mapStyleVariable, maxTokenTtlSeconds, maxWidgetPropsBytes, mergeConfig, migrationCommand, newWebhookSecret, normalizeRoles, notFound, parseColumns, parseRoles, pluginOptions, pluginsBeforeSignIn, pluginsFor, pluginsVariable, processor, readJson, readOnlyQueryTool, readOperatorSettings, readOutbox, readPlatformSignIn, readWriteQueryTool, recordOf, removeMember, renderVariant, requestApproval, requireEnv, resourceChange, roleChoices, runInBackground, runReadOnlyQuery, runReadWriteQuery, runTurn, runtimeUrl, runtimeVariable, s3FileStore, s3Files, seesAssistant, seesRuntime, setMemberRoles, setUserBanned, setUserRole, signInPolicyMethods, sourceOptions, sourcesFor, sourcesVariable, startErrorReporting, startJobs, storageCleanupSchedule, storeFile, streamChatCompletion, subscription, thumbHash, unauthorized, variantPath, verifySignature, verifyStandardWebhook, webauthnPath, webhooks, webhooksMigration, widget, withCacheBreakpoints, withTrustedApps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.25.10",
3
+ "version": "0.25.11",
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": {
@@ -32,9 +32,9 @@
32
32
  "dependencies": {
33
33
  "@better-auth/passkey": "^1.7.7",
34
34
  "@better-auth/sso": "^1.7.7",
35
- "@protobase/layout": "0.25.10",
36
- "@protobase/query": "0.25.10",
37
- "@protobase/schema": "0.25.10",
35
+ "@protobase/layout": "0.25.11",
36
+ "@protobase/query": "0.25.11",
37
+ "@protobase/schema": "0.25.11",
38
38
  "@react-email/render": "^2.1.0",
39
39
  "@scalar/hono-api-reference": "^0.12.10",
40
40
  "@sentry/core": "^11.7.0",