export type LockServiceResolvedConfigType = { /** * - Shared secret enforced by the host, when configured. */ authToken?: string; /** * - Base backoff between connection retries. */ connectBackoffMs: number; /** * - Bounded connection retries before giving up. */ connectRetries: number; /** * - Handshake timeout. */ connectTimeoutMs: number; /** * - What to do when the service is unreachable. */ fallback: "database" | "none"; /** * - Lock-service host. */ host: string; /** * - Lease duration advertised to clients. */ leaseMs: number; /** * - Where the authority lives. */ mode: "beacon" | "in-process" | "off"; /** * - Prefix applied to every lock name. */ namespace: string; /** * - Lock-service port. */ port: number; /** * - Durable mirror for epochs and holders. */ statePath: string | null; }; export type ApplicationProcessContext = { /** * - Generic process type supplied to `configuration.initialize()`. */ type: string; /** * - Opaque identity unique to this lifecycle. */ instanceId: string; }; export type CorsType = (args: { request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default; response: import("./http-server/client/response.js").default; }) => Promise; export type WebsocketChannelResolverType = (args: { request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined; subscription?: { channel: string; params?: Record>; }; client: import("./http-server/client/index.js").default; websocketSession: import("./http-server/client/websocket-session.js").default; configuration: import("./configuration.js").default; }) => typeof import("./http-server/websocket-channel.js").default | import("./http-server/websocket-channel.js").default | void | Promise; export type WebsocketMessageHandler = { /** * - Handler for incoming websocket messages. */ onMessage?: (args: { message: ReturnType; session: import("./http-server/client/websocket-session.js").default; }) => Promise | void; /** * - Handler when the websocket session opens. */ onOpen?: (args: { session: import("./http-server/client/websocket-session.js").default; }) => Promise | void; /** * - Handler when the websocket session closes. */ onClose?: (args: { session: import("./http-server/client/websocket-session.js").default; }) => Promise | void; /** * - Handler when a websocket message errors. */ onError?: (args: { error: Error; session: import("./http-server/client/websocket-session.js").default; }) => Promise | void; }; export type WebsocketMessageHandlerResolverType = (args: { request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined; client: import("./http-server/client/index.js").default; configuration: import("./configuration.js").default; }) => WebsocketMessageHandler | void | Promise; export type InitializersRequireContextType = (id: string) => { default: typeof import("./initializer.js").default; }; export type WebpackRequireContext = InitializersRequireContextType & { keys: () => string[]; id: string; }; export type InitializersExportType = { requireContext: WebpackRequireContext; }; export type InitializersType = (args: { configuration: import("./configuration.js").default; }) => Promise; export type SqlConfig = { /** * - Database name for the SQL driver. */ database?: string; /** * - Driver-specific connection options. */ options?: { encrypt?: boolean; schema?: string; serverName?: string; trustServerCertificate?: boolean; }; /** * - Password for the SQL user. */ password?: string; /** * - Connection pool configuration. */ pool?: { max?: number | null; min?: number; idleTimeoutMillis?: number; checkoutTimeoutMillis?: number | null; }; /** * - SQL server hostname. */ server?: string; /** * - SQL username. */ user?: string; }; export type DatabasePoolConfiguration = { /** * - Timeout while a checkout waits for an available async-tracked connection after the max live connection cap is reached. Set null to wait indefinitely. Default: 10000. */ checkoutTimeoutMillis?: number | null; /** * - Idle timeout before closing a checked-in async-tracked connection. Set null to disable idle reaping. Default: 5000. */ idleTimeoutMillis?: number | null; /** * - Maximum live async-tracked connections for this pool. Defaults to 10. Extra checkouts wait until a matching connection is checked in or capacity is freed. Set null to disable the cap. */ max?: number | null; }; export type DatabaseConfigurationType = { /** * - Bound (ms) a blocking advisory-lock acquisition waits for a contended lock before reporting failure. Default: `900000` (15 minutes). `null` opts out and restores the driver's indefinite wait. A per-call `timeoutMs` argument always overrides this. */ advisoryLockAcquireTimeoutMs?: number | null; /** * - Event-driven advisory-lock duration telemetry thresholds. `slowAcquireMs` (default `5000`) reports an acquire wait that completed slower than the threshold, including the eventual outcome; `advisory-lock-acquire-timeout` always fires when a wait exceeds its bound and carries the holder identity available on the tier at that moment. `slowHoldMs` (default `60000`) reports a hold that outlives the threshold at release. `null` disables that report. Reports fire on the events themselves — no periodic scanner — on `getTelemetryEvents()` as `telemetry` with `context: "advisory-lock-telemetry"`. See [docs/advisory-locks.md](../docs/advisory-locks.md). */ advisoryLockTelemetry?: { slowAcquireMs?: number | null; slowHoldMs?: number | null; }; /** * - Default character set applied by `db:create` via mysql/mariadb `CREATE DATABASE ... CHARACTER SET`. Distinct from `charset`, which is the client connection charset forwarded to the mysql2 driver. */ databaseCharset?: string; /** * - Default collation applied by `db:create` via mysql/mariadb `CREATE DATABASE ... COLLATE`. */ databaseCollation?: string; /** * - Database name for this connection. */ database?: string; /** * - Maximum attempts for the outermost transaction when it keeps hitting deadlocks. Defaults to 8. */ deadlockMaxRetries?: number; /** * - Base delay (ms) for the deadlock retry backoff; the per-attempt ceiling doubles from here. Defaults to 50. */ deadlockBaseWaitMs?: number; /** * - Cap (ms) on the deadlock retry backoff ceiling so the jittered wait stays bounded. Defaults to 1000. */ deadlockMaxWaitMs?: number; /** * - Driver class to use for this database. */ driver?: typeof import("./database/drivers/base.js").default; /** * - Pool class to use for this database. */ poolType?: typeof import("./database/pool/base.js").default; /** * - Custom connection factory override. */ getConnection?: () => ReturnType; /** * - Database host. */ host?: string; /** * - Whether migrations are enabled for this database. */ migrations?: boolean; /** * - (MySQL) Opt in to multi-statement queries so structure SQL loads and all-table cleanup can batch into one round-trip. Off by default; ordinary queries otherwise reject stacked statements. */ multipleStatements?: boolean; /** * - Maximum rows per `INSERT ... VALUES (...), (...), ...` statement generated by `Record.insertMultiple`. Defaults to 500. */ maxRowsPerInsert?: number; /** * - Maximum serialized SQL size, in bytes, for a single `INSERT ... VALUES (...), (...), ...` statement. Defaults to 1 MiB (1048576). */ maxInsertSqlBytes?: number; /** * - Maximum values in a single `IN (...)` cohort used by preloads, association counts, and queryData aggregates. Defaults to 999. */ maxInClauseValues?: number; /** * - Maximum serialized SQL size, in bytes, for a single cohort query used by preloads, association counts, and queryData aggregates. Defaults to 1 MiB (1048576). */ maxQuerySqlBytes?: number; /** * - Password for the database user. */ password?: string; /** * - Database port. */ port?: number; /** * - Default type for implicit migration primary keys and references. Defaults to `uuid`. */ primaryKeyType?: string; /** * - Velocious database pool lifecycle configuration. */ pool?: DatabasePoolConfiguration; /** * - Friendly name for the configuration. */ name?: string; /** * - Optional sqlite-web sql.js wasm resolver (`initSqlJs({locateFile})`). */ locateFile?: (file: string) => string; /** * - Whether writes should be blocked for this database. */ readOnly?: boolean; /** * - Default schema for unqualified table lookups (MSSQL). */ schema?: string; /** * - Whether schema metadata should be cached on the driver. Defaults to true. */ schemaCache?: boolean; /** * - Bounded deadline (ms) for outlasting a cached schema-metadata read the server skipped because concurrent online DDL is modifying the table. Defaults to 60000. */ schemaMetadataRetryDeadlineMs?: number; /** * - Record-level configuration. */ record?: { transactions?: boolean; }; /** * - Whether to reset the database on startup. */ reset?: boolean; /** * - Driver-specific SQL config. */ sqlConfig?: SqlConfig; /** * - Whether this database identifier is only active inside a resolved tenant context. */ tenantOnly?: boolean; /** * - Database type identifier. */ type?: "mssql" | "mysql" | "pgsql" | "sqlite"; /** * - Database to switch to after connecting. */ useDatabase?: string; /** * - Username for database authentication. */ username?: string; }; export type LogLevel = "debug-low-level" | "debug" | "info" | "warn" | "error"; export type LoggingOutputPayload = { /** * - Log level. */ level: LogLevel; /** * - Formatted message. */ message: string; /** * - Log subject. */ subject: string; /** * - Timestamp. */ timestamp: Date; }; export type LoggingOutput = { /** * - Write a log entry. */ write: (arg: LoggingOutputPayload) => Promise | void; /** * - Default levels for this output. */ levels?: LogLevel[]; }; export type LoggingOutputConfig = { /** * - Output instance. */ output: LoggingOutput; /** * - Levels enabled for this output. */ levels?: Array; }; export type LoggerConfig = LoggingOutputConfig | LoggingOutput | import("./logger/base-logger.js").default; export type LoggingConfiguration = { /** * - Enable/disable console logging for request logging. Defaults to true outside of "test" and for HTTP server logs. */ console?: boolean; /** * - Enable/disable writing logs to a file. Defaults to true. */ file?: boolean; /** * - Directory where log files are stored. Defaults to "/log". */ directory?: string; /** * - Explicit path for the log file. Defaults to "/.log". */ filePath?: string; /** * - Override which log levels are emitted. */ levels?: Array<"debug-low-level" | "debug" | "info" | "warn" | "error">; /** * - Convenience flag to include very low-level debug logs. */ debugLowLevel?: boolean; /** * - Enable/disable database query logging. Defaults to true outside test and false in test. */ queryLogging?: boolean; /** * - Additional case-insensitive sensitive header/parameter names to redact from logging. */ sensitiveNames?: string[]; /** * - Logger instances (converted to outputs when configured). */ loggers?: LoggerConfig[]; /** * - Explicit logger outputs (overrides console/file defaults when provided). */ outputs?: LoggingOutputConfig[]; }; export type StructureSqlConfiguration = { /** * - Environments allowed to write structure sql files during automatic migration dumps. */ enabledEnvironments?: string[]; /** * - Environments that should skip writing structure sql files. */ disabledEnvironments?: string[]; }; export type BackgroundJobsDispatchStrategy = "beacon" | "polling"; export type BackgroundJobsMode = "background" | "inline"; export type BackgroundJobsGenerationInitialState = "candidate" | "active" | "retired"; export type BackgroundJobsAdapterFactory = (args: { configuration: import("./configuration.js").default; }) => import("./background-jobs/adapter.js").default; export type BackgroundJobClass = typeof import("./background-jobs/platform-job.js").default; export type BackgroundJobsConfiguration = { /** * - Adapter instance or synchronous factory. A factory creates one adapter per configuration lifecycle; the framework closes adapters it resolves. */ adapter?: import("./background-jobs/adapter.js").default | BackgroundJobsAdapterFactory; /** * - Static portable job classes available to Browser/Expo local dispatch. Defaults to `[]`; Node keeps its filesystem registry. */ jobClasses?: BackgroundJobClass[]; /** * - `"background"` uses the configured adapter/transport and durable queue semantics; `"inline"` performs immediately without durable queue state. Defaults to `"background"`. */ mode?: BackgroundJobsMode; /** * - Opt-in release generation identity. Must match `^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$` and agree with environment/API/CLI sources. */ generationId?: string; /** * - Generation-aware boot state. Defaults to `"candidate"`; invalid without `generationId`. */ initialGenerationState?: BackgroundJobsGenerationInitialState; /** * - Absolute release-local Unix socket used by acknowledged activation and retirement commands. */ lifecycleSocketPath?: string; /** * - Hostname for the background jobs main process. */ host?: string; /** * - Port for the background jobs main process. */ port?: number; /** * - Database identifier used to store background jobs. Browser/Expo local dispatch uses this existing SQLite database and defaults to `"default"`. */ databaseIdentifier?: string; /** * - How many `forked: false` jobs a single * `background-jobs-worker` process is allowed to run in parallel. Concurrency * is at the JS event-loop level: every concurrent job shares the worker's * process and DB connection pool, so this should fit the pool size, not the * CPU count. Forking remains the right tool for memory isolation across * long-running jobs and for using more cores. Default: `4`. */ maxConcurrentInlineJobs?: number; /** * - How many out-of-process * `"forked"` or `"spawned"` jobs a single `background-jobs-worker` is * allowed to keep in flight. Default: `4`. This is a per-worker safety cap; * for workload-shaped limits use per-queue caps (`queues`) instead, which are * enforced cluster-wide and are immune to duplicate worker processes. */ maxConcurrentForkedJobs?: number; /** * - Number of warm, reusable child runners owned by each worker. Pooled capacity is separate from inline and forked/spawned capacity. Default: `4`. */ pooledRunnerCount?: number; /** * - Number of jobs each pooled child runs concurrently on its own event loop. Total per-worker pooled capacity is `pooledRunnerCount × pooledRunnerConcurrency`. `1` (default) keeps each child serial; raise it for I/O-bound jobs so a bounded set of isolated processes handles high concurrency (like the inline lane) without one process per concurrent job. Default: `1`. */ pooledRunnerConcurrency?: number; /** * - Number of sequential jobs a pooled child runs before it is replaced, bounding process-level resource accumulation. Default: `100`. */ pooledRunnerMaxJobs?: number; /** * - Peak RSS (the kernel `VmHWM` high-water mark reported by the child) at which a pooled child is replaced after an acknowledged job. The child's peak, not its settled RSS at job-outcome time, is the trigger, so a burst working-set that reclaims before the outcome still retires the child. Default: `536870912` (512 MiB). */ pooledRunnerMaxRssBytes?: number; /** * - Age after an acknowledged job at which a pooled child is replaced. Default: `3600000` (one hour). */ pooledRunnerMaxLifetimeMs?: number; /** * - IPC-silence bound for a pooled child with in-flight jobs. A child that sends nothing (readiness, acceptance, memory observation, or job outcome) for longer than this is declared wedged: its in-flight jobs are reported failed for requeue, its capacity is re-advertised, and the wedged process is terminated. A healthy child samples itself every 10 seconds while jobs run, so the bound only fires on a child that cannot prove it is alive. Default: `120000`. */ pooledRunnerSilenceTimeoutMs?: number; /** * - V8 heap cap (`--max-old-space-size`, MiB) applied to every background-jobs runner child process (pooled, forked, and spawned) so a single child can never commit multiple GBs of heap. Default: `2048`. */ runnerMaxOldSpaceSizeMb?: number; /** * - `MALLOC_ARENA_MAX` exported to every background-jobs runner child process, bounding glibc per-thread arenas. Defaults to an inherited `MALLOC_ARENA_MAX`, else `4`. */ runnerMallocArenaMax?: number; /** * - Per-queue * concurrency caps and dispatch priorities, Sidekiq-style. A job declares its queue (static * `queue` on the job class, or the `queue` enqueue option; defaults to `"default"`), and * `queues[name].maxConcurrent` bounds how many jobs from that queue may be * in flight across the whole cluster (enforced via durable per-key * concurrency, so it holds regardless of how many worker processes run). * Size each queue to its workload: I/O-bound queues (e.g. build runners * waiting on remote Docker servers) can run far above the core count, while * CPU-bound queues should stay near it. `queues[name].priority` (default `0`) * makes the main process dispatch higher-priority queues before lower-priority * ones regardless of enqueue order, so a small time-critical queue can never be * starved by a flood of low-priority work sharing a worker pool. Unlike * Sidekiq's strict queue ordering, priority composes with the per-queue caps: * a higher-priority queue that is already at its `maxConcurrent` is skipped and * dispatch falls through to the next eligible lower-priority job, so a busy * high-priority queue does not block everything else. This fallthrough is a * property of the queue-derived cap; a job that supplies its own explicit * `concurrencyKey`/`maxConcurrency` bypasses the queue cap entirely (an * explicit key always wins — see above) and is bounded only by that key, so it * is not held back by the queue's cap and priority simply orders it normally. * Priorities may be any number, including negative to sink a queue below the * default. Jobs within the same priority keep FIFO (`scheduled_at`, then * `created_at`) order. Default: `{}` (no queue caps, all queues priority `0`). */ queues?: Record; /** * - Bounds one scheduled enqueue attempt in the main process. A durable enqueue that never settles (wedged DB connection, contended advisory lock) would otherwise keep its schedule key permanently in flight, so every later tick skipped itself and shutdown could never drain. On timeout the attempt is reported as `background-jobs-scheduled-enqueue-stall` and the key clears for the next tick. Default: 20 minutes — deliberately 5 minutes above `advisoryLockAcquireTimeoutMs` so the precise lock error surfaces first. `null` opts out. */ scheduledEnqueueTimeoutMs?: number | null; /** * - How the main process * detects new work. Defaults to `"beacon"` (event-driven). Set to `"polling"` * to restore the legacy fixed-interval poll. */ dispatchStrategy?: BackgroundJobsDispatchStrategy; /** * - Poll interval in milliseconds. Only used * when `dispatchStrategy === "polling"`. Default: `1000`. */ pollIntervalMs?: number; /** * - Bounds one drain-critical * store operation in the main process: the queued-job lookup, the durable * handoff claim, and handoff-recovery transitions. A store call that never * settles (wedged DB connection, lost acknowledgement) would otherwise freeze * the coalesced drain and every later dispatch queued behind it until the * process is killed; on timeout the drain fails into its existing * error/retry path and the stall is reported as a framework error. * Default: `60000`. */ drainStoreOperationTimeoutMs?: number; /** * - Wall-clock backstop, in ms, for a * `"forked"` job runner. A forked job still running after this is terminated * (SIGTERM, then SIGKILL after the reaping grace) and reported failed, so a * single genuinely-hung runner can't pin a draining worker — and its full-app * boot and DB connections — indefinitely (e.g. across a deploy where a retired * worker drains in-flight jobs). This is a coarse safety net, not per-job * tuning: set it well above the longest legitimate forked job (build runners, * long imports) so only genuinely-stuck runners are killed. Omit, `null`, or * `<= 0` to disable (default), which preserves the prior unbounded behavior. */ jobTimeoutMs?: number | null; /** * - Retention/pruning * of terminal job rows. Without pruning the jobs table grows unbounded * (completed rows accumulate forever), which bloats storage and indexes and * eventually slows dispatch. The main process sweeps terminal rows past their * window on an interval. */ retention?: BackgroundJobsRetentionConfiguration; }; export type BackgroundJobsRetentionConfiguration = { /** * - Delete `completed` jobs whose * `completed_at_ms` is older than this many ms. `null` or `<= 0` disables * completed pruning. Default: `604800000` (7 days). */ completedTtlMs?: number | null; /** * - Delete terminal `failed`/`orphaned` * jobs older than this many ms. `null` or `<= 0` disables (keeps them for * debugging). Default: `2592000000` (30 days). */ failedTtlMs?: number | null; /** * - Rows deleted per batch. Default: `1000`. */ batchSize?: number; /** * - How often the retention sweep runs. * Default: `3600000` (1 hour). */ sweepIntervalMs?: number; }; export type ResolvedBackgroundJobsRetentionConfiguration = { /** * - Resolved completed-job TTL in ms (`null` disables). */ completedTtlMs: number | null; /** * - Resolved failed/orphaned TTL in ms (`null` disables). */ failedTtlMs: number | null; /** * - Resolved delete batch size. */ batchSize: number; /** * - Resolved sweep interval in ms. */ sweepIntervalMs: number; }; export type BeaconConfiguration = { /** * - Whether to connect to a Beacon broker. Defaults to false unless `host`/`port` or `inProcess: true` are set, or env vars are present. Explicit `false` disables Beacon even when env vars are set. */ enabled?: boolean; /** * - When true, use a module-level in-process broker singleton instead of connecting over TCP. Mutually exclusive with `host`/`port`. Useful for tests and single-process deployments. */ inProcess?: boolean; /** * - Hostname of the Beacon broker daemon. */ host?: string; /** * - Port of the Beacon broker daemon. */ port?: number; /** * - Optional human-readable label for this peer (e.g. "server", "background-jobs-worker"). */ peerType?: string; /** * - Grace window (ms) a beacon connect/disconnect blip must persist before it is reported as a framework-error. Transient outages that recover within this window (e.g. a deploy restarting the broker) are not reported. Defaults to 30000. */ unreachableReportMs?: number; }; export type HttpCompressionConfiguration = { /** * - Whether buffered response compression is enabled. Defaults to true; set false to disable globally. */ enabled?: boolean; /** * - Minimum buffered body size in bytes before compression is applied. Defaults to 1024. */ threshold?: number; /** * - Brotli encoder quality (0-11). Defaults to 4. */ brotliQuality?: number; /** * - Gzip compression level (0-9). Defaults to 6. */ gzipLevel?: number; }; export type NormalizedHttpCompressionConfiguration = { /** * - Whether buffered HTTP response compression is enabled. */ enabled: boolean; /** * - Minimum buffered body size in bytes before compression is applied. */ threshold: number; /** * - Brotli encoder quality (0-11). */ brotliQuality: number; /** * - Gzip compression level (0-9). */ gzipLevel: number; }; export type HttpRequestBodyPolicyResolverArgs = { /** * - Complete request headers as received by the parser. */ headers: Record; /** * - Uppercase HTTP method. */ httpMethod: string; /** * - Request target, including its query string when present. */ path: string; }; export type HttpRequestBodyPolicy = { /** * - Per-request decoded body limit. Falls back to the global limit when omitted. */ maxRequestBodyBytes?: number; /** * - Parsed params by default; raw preserves exact bytes and skips body decoding. */ mode?: "parsed" | "raw"; }; export type HttpRequestBodyPolicyResolver = (args: HttpRequestBodyPolicyResolverArgs) => HttpRequestBodyPolicy | undefined; export type ResolvedHttpRequestBodyPolicy = { /** * - Effective decoded body limit. */ maxRequestBodyBytes: number | undefined; /** * - Effective body handling mode. */ mode: "parsed" | "raw"; }; export type HttpServerConfiguration = { /** * - Buffered response compression. Enabled with documented defaults when absent; false or {enabled: false} disables it globally. */ compression?: boolean | HttpCompressionConfiguration; /** * - Hostname to bind the HTTP server to. */ host?: string; /** * - Run HTTP handlers in the main thread instead of worker threads. */ inProcess?: boolean; /** * - Maximum UTF-8/binary byte length accepted by buffered response bodies. Unbounded when absent; streamed file responses are unaffected. */ maxBufferedResponseBodyBytes?: number; /** * - Maximum decoded request-body bytes accepted before routing. Unbounded when absent, except the built-in MCP endpoint, which defaults to a 1 MiB cap that this option overrides. */ maxRequestBodyBytes?: number; /** * - Optional synchronous header-stage resolver for per-request limits and raw-body handling. */ requestBodyPolicyResolver?: HttpRequestBodyPolicyResolver; /** * - Backward-compatible alias for workers. */ maxWorkers?: number; /** * - Port to bind the HTTP server to. */ port?: number; /** * - Per-session retained inbound WebSocket message limits. */ websocketInboundQueue?: { maxPendingBytes?: number; maxPendingMessages?: number; }; /** * - Per-client retained outbound WebSocket frame limits. */ websocketOutboundQueue?: { maxPendingBytes?: number; maxPendingFrames?: number; }; /** * - Worker handlers to start for the HTTP server. */ workers?: number; }; export type ScheduledBackgroundJobEveryOptions = { /** * - Delay before the first enqueue. */ firstIn?: number | string; }; export type ScheduledBackgroundJobConfiguration = { /** * - Arguments passed to the job when enqueued. */ args?: Array>; /** * - Job class to enqueue. */ class: typeof import("./background-jobs/job.js").default; /** * - Crontab expression (5-field POSIX, plus `@hourly`/`@daily`/`@weekly`/`@monthly`/`@yearly`/`@midnight`). Mutually exclusive with `every`. */ cron?: string; /** * - Whether the schedule is enabled. */ enabled?: boolean; /** * - Repeat interval. Either `every` or `cron` must be set. */ every?: number | string | [number | string, ScheduledBackgroundJobEveryOptions]; /** * - Job options. */ options?: import("./background-jobs/types.js").BackgroundJobOptions; }; export type VelociousParams = Record; export type ClientErrorPayloadReporterPayload = Record; export type ErrorRequestDetails = { /** * - Sanitized parsed request body, when available. */ body?: ReturnType; /** * - Request HTTP method. */ httpMethod: string; /** * - Request path. */ path: string; }; export type ClientErrorPayloadContext = { /** * - Controller class name. */ controller: string; /** * - Controller action or endpoint label. */ action?: string; /** * - Frontend-model command type. */ commandType?: "index" | "find" | "create" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url" | "custom-command"; /** * - Server-generated identifier shared by an unexpected client error and framework reports. */ correlationId?: string; /** * - Whether the error is an expected user-flow failure. */ expectedError?: boolean; /** * - Whether the error came from the frontend-model endpoint. */ frontendModelEndpoint?: boolean; /** * - Frontend-model name from the failed request. */ model?: string; /** * - Shared frontend-model request id. */ requestId?: string; }; export type ClientErrorPayloadReporterType = (args: { context: ClientErrorPayloadContext; error: Error; request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined; requestDetails: ErrorRequestDetails | null; }) => Promise | ClientErrorPayloadReporterPayload | void; export type VelociousLooseObject = Record & { configuration?: import("./configuration.js").default; currentDevice?: unknown; currentUser?: unknown; modelRegistry?: Record | { model: (name: string) => unknown; }; now?: Date | (() => Date); offlineGrant?: unknown; params?: VelociousParams; request?: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default; resourceRuntime?: "backend" | "frontend" | "offline"; }; export type AttachmentDriverConstructor = new (args: { attachmentName?: string; configuration: import("./configuration.js").default; modelClass?: typeof import("./database/record/index.js").default; name?: string; options?: Record>; }) => object; export type ScheduledBackgroundJobsConfiguration = { /** * - Scheduled jobs keyed by name. */ jobs: Record; }; export type ScheduledBackgroundJobsLoaderType = (args: { configuration: import("./configuration.js").default; }) => ScheduledBackgroundJobsConfiguration | Promise; export type AttachmentDriverConfiguration = { /** * - Optional factory for a custom attachment driver instance. */ create?: (args: { configuration: import("./configuration.js").default; name: string; options: Record>; }) => Record>; /** * - Optional custom attachment driver class. */ driverClass?: AttachmentDriverConstructor; /** * - Optional custom attachment driver instance. */ instance?: Record>; }; export type AttachmentSyncConfiguration = { /** * - Whether clients prefetch the attachment or wait until it is requested. */ fetch: "eager" | "on-demand"; /** * - Whether an offline-ready scope requires the attachment bytes. */ offlineRequirement: "optional" | "required"; /** * - Whether clients may evict the attachment under storage pressure. */ retention: "durable" | "evictable"; }; export type RecordAttachmentConfiguration = { /** * - Attachment driver name, class, or instance. */ driver?: string | AttachmentDriverConstructor | Record>; /** * - Client-safe synchronized asset policy. */ sync?: AttachmentSyncConfiguration; /** * - Attachment cardinality. */ type: "hasOne" | "hasMany"; }; export type AttachmentsConfiguration = { /** * - Default attachment storage driver name. */ defaultDriver?: string; /** * - Named attachment driver configurations. */ drivers?: Record>>; /** * - Whether `{path: ...}` attachment input is allowed. */ allowPathInput?: boolean; /** * - Optional allowlist of directories for `{path: ...}` input. */ allowedPathPrefixes?: string[]; }; export type MailerBackend = { /** * - Deliver a mailer payload. */ deliver: (args: { payload: import("./mailer.js").MailerDeliveryPayload; configuration: import("./configuration.js").default; }) => Promise> | ReturnType; /** * - Explicit provider-backed duplicate-suppression capability. Generic SMTP omits this and remains at-least-once. */ deliveryIdempotencyCapability?: () => import("./mailer.js").MailerDeliveryIdempotencyCapability; /** * - Resolves provider defaults into the immutable payload before required-operation hashing and enqueue. */ prepareDeliveryOperationPayload?: (args: { payload: import("./mailer.js").MailerDeliveryPayload; }) => import("./mailer.js").MailerDeliveryPayload; /** * - Provider-specific operation and payload validation performed before enqueue and every network attempt. */ validateDeliveryOperation?: (args: { deliveryOperation: import("./mailer.js").MailerDeliveryOperationRequest | import("./mailer.js").MailerDeliveryOperation; payload: import("./mailer.js").MailerDeliveryPayload; }) => void; }; export type LocaleFallbacksType = Record; export type FrontendModelRelationshipConfiguration = { /** * - Relationship type. */ type: "belongsTo" | "hasOne" | "hasMany"; /** * - Target model class name. */ model?: string; /** * - Alias of target model class name. */ className?: string; /** * - Explicit target model class name. */ modelClassName?: string; }; export type FrontendModelAttributeConfiguration = { /** * - Column type name. */ type?: string; /** * - Alias for column type name. */ columnType?: string; /** * - Alias for column type name. */ sqlType?: string; /** * - Alias for column type name. */ dataType?: string; /** * - Exact generated JSDoc type for non-column attributes. */ jsDocType?: string; /** * - Attribute name when configured as an array entry. */ name?: string; /** * - Whether value can be null. */ null?: boolean; /** * - Whether included in default serialization. Defaults to true. */ selectedByDefault?: boolean; }; export type FrontendModelAttachmentConfiguration = { /** * - Client-side synchronized asset policy. */ sync?: AttachmentSyncConfiguration; /** * - Attachment cardinality. */ type: "hasOne" | "hasMany"; }; export type FrontendModelQuickSearchColumn = { /** * - Relationship path from the root model to the column's table. */ path?: string[]; /** * - Database column name to search. */ column: string; }; export type FrontendModelResourceConfiguration = { /** * - Attributes to expose on the frontend model. */ attributes: Array | Record; /** * - Declarative quick-search text columns; an index search on the pseudo-column `quickSearch` expands to an OR of LIKE conditions over these columns. */ quickSearchColumns?: Array; /** * - Declarative quick-search numeric columns; an integer quick-search value also matches these columns exactly. */ quickSearchNumericColumns?: Array; /** * - Additional camelCase ability action names to expose for per-record `record.can(action)` reads. Base CRUD actions (`read`, `create`, `update`, `destroy`) are always included and must not be listed here. */ abilities?: string[]; /** * - Attachment helpers keyed by attachment name. */ attachments?: Record; /** * - Legacy built-in command names (`index`, `find`, `create`, `update`, `destroy`, `attach`, `download`, `url`). */ commands?: string[]; /** * - Custom collection commands. Each entry is a camelCase method name, or a `{name, args?, returnType?}` object declaring typed arguments and/or a response type. The runtime derives the kebab-case command slug from the name. */ collectionCommands?: Array; /** * - Custom member commands. Each entry is a camelCase method name, or a `{name, args?, returnType?}` object declaring typed arguments and/or a response type. The runtime derives the kebab-case command slug from the name. */ memberCommands?: Array; /** * - Built-in collection command names (`index`, `create`). */ builtInCollectionCommands?: string[]; /** * - Built-in member command names (`find`, `update`, `destroy`, `attach`, `download`, `url`). */ builtInMemberCommands?: string[]; /** * - Frontend model name override. */ modelName?: string; /** * - Relationship names to expose in frontend models. Type and target model are inferred from the backend model's registered relationships. */ relationships?: string[]; /** * - Primary key attribute name or ordered composite primary-key attribute names. */ primaryKey?: string | string[]; /** * - Optional legacy backend behavior overrides for built-in frontend actions. */ server?: FrontendModelResourceServerConfiguration; /** * - Optional safe local/offline sync policy metadata. `policy` participates in the hash but is not exposed to generated frontend config/manifest. */ sync?: FrontendModelResourceSyncConfiguration | boolean; }; export type FrontendModelResourceCustomCommandObject = { /** * - camelCase command method name. */ name: string; /** * - Typed command arguments; each generates a named, typed method parameter mapped positionally into the command payload. `type` is a JSDoc type string. */ args?: Array<{ name: string; type: string; }>; /** * - JSDoc type for the command response. When set, the generated method is typed `Promise` instead of `Promise>>`. Emitted verbatim into the generated frontend model, so it must resolve there. */ returnType?: string; }; export type FrontendModelResourceCustomCommand = string | FrontendModelResourceCustomCommandObject; export type FrontendModelSyncJsonValue = null | string | number | boolean | unknown[] | Record; export type FrontendModelResourceSyncConfiguration = { /** * - Strategy used when replay detects server/client divergence. Defaults to `optimisticVersion`. */ conflictStrategy?: "optimisticVersion" | "serverWins" | "lastWriterWins" | "fieldThreeWay" | "appendOnly"; /** * - Whether the resource is sync-enabled. Defaults to true when `sync` is configured. */ enabled?: boolean; /** * - Sync operation names such as `index`, `find`, `create`, `update`, custom domain commands, etc. */ operations?: string[]; /** * - App-controlled policy version used as a stable change signal. */ policyVersion?: string | number; /** * - Safe frontend-visible metadata. */ metadata?: Record; /** * - Deterministic non-secret policy inputs included in the policy hash only. */ policy?: Record; }; export type VelociousSyncApiConfiguration = { /** * - Mount path for the sync endpoints. Defaults to "/velocious/sync". */ mountPath?: string; /** * - App sync resource class served by the auto-mounted sync endpoints. */ resourceClass: FrontendModelResourceClassType; }; export type VelociousSyncClientTransport = { /** * - Posts one request and resolves a response with a json accessor. */ post: (path: string, body?: ReturnType, options?: { headers?: Record; signal?: AbortSignal; }) => Promise<{ json: () => ReturnType; }>; }; export type VelociousSyncRealtimeWebsocketClient = { /** * - Connects the websocket. */ connect: (options?: { signal?: AbortSignal; }) => Promise>; /** * - Opens one channel subscription. */ subscribeChannel: (channelType: string, options?: { params?: Record>; onMessage?: (body: ReturnType) => void; onResume?: () => void; onClose?: (reason: string) => void; }) => VelociousSyncRealtimeSubscription; /** * - Closes the socket and stops auto-reconnect. */ disconnectAndStopReconnect: () => Promise; }; export type VelociousSyncRealtimeSubscription = { /** * - Closes the subscription. */ close: () => void; /** * - Whether the subscription is acknowledged and ready. */ isReady: () => boolean; /** * - Resolves once the server acknowledges the subscription. */ waitForReady: (params?: { signal?: AbortSignal; timeoutMs?: number; }) => Promise; }; export type VelociousSyncRealtimeChannelDescriptor = { /** * - Server channel name to subscribe. */ channel: string; /** * - Subscribe params (runtime scope values). The framework injects `authenticationToken` automatically. */ params?: Record>; /** * - Default resource/model name for pushed changes that do not carry their own resourceType. */ resourceType?: string; }; export type VelociousSyncClientRealtimeConfiguration = { /** * - Builds the (unconnected) websocket client; the framework owns connect/disconnect. */ createClient: () => VelociousSyncRealtimeWebsocketClient | Promise; /** * - Deprecated legacy escape hatch: resolves extra app-channel descriptors from the `subscribeRealtime(context)` context. Declared pull scopes subscribe the framework sync channel automatically. */ channels?: (context: ReturnType) => Array | Promise>; /** * - Resolves this device's echo origin; pushed messages with a matching `echoOrigin` are dropped. */ localOrigin?: () => string | Promise; /** * - Deprecated no-op: realtime catch-up now replays the server-side sync cursor on subscribe and resume, so the former pull-on-reconnect no longer fires. Kept so existing app configs still typecheck. */ pullOnReconnect?: boolean; }; export type VelociousSyncClientConfiguration = { /** * - Resolves the auth token sent with sync requests. */ authenticationToken: () => string | Promise; /** * - Max syncs per request. */ batchSize?: number; /** * - Connectivity gate for pulls and replays. Defaults to always online. */ isOnline?: () => boolean | Promise; /** * - Mount path the server serves the sync endpoints under (match the server's `sync.api.mountPath`). Defaults to "/velocious/sync"; normalization strips trailing slashes and always fills in the default. */ mountPath?: string; /** * - Reports background replay/pull failures. Defaults to rethrowing. */ onError?: (error: Error) => void; /** * - Long-offline session configuration consumed by `startOfflineSession()`: device identity, enrollment, grant scopes, signed-replay path, and the backend public key for peer import. */ offline?: VelociousSyncClientOfflineConfiguration; /** * - Realtime push configuration consumed by `subscribeRealtime(...)`. */ realtime?: VelociousSyncClientRealtimeConfiguration; /** * - Transport posting to the framework sync endpoints (e.g. the frontend-model websocket client). */ transport: VelociousSyncClientTransport; /** * - Shared app-lifetime websocket client (the low-level form) that all sync traffic rides. Provide the same instance the frontend-model transport uses so one connection carries everything. When set, the realtime bridge subscribes channels on it and never owns its lifecycle: unsubscribing closes only channel subscriptions, leaving the socket connected. */ websocketClient?: VelociousSyncRealtimeWebsocketClient; /** * - Shared app-lifetime websocket URL. When set (and no `websocketClient` is given), the framework builds and owns one reconnecting `VelociousWebsocketClient` for all sync traffic, connected on first use. */ websocketUrl?: string | (() => string | null | undefined); }; export type VelociousSyncClientDeviceIdentityStorage = { /** * - Reads the stored identity (null when the device has none yet). */ load: () => import("./sync/sync-offline-session.js").SyncOfflineDeviceIdentity | null | undefined | Promise; /** * - Persists the identity. */ save: (identity: import("./sync/sync-offline-session.js").SyncOfflineDeviceIdentity) => Promise | void; }; export type VelociousSyncClientGrantStorage = { /** * - Reads the retained grants. */ load: () => Array | Promise>; /** * - Persists the retained grants. */ save: (grants: Array) => Promise | void; }; export type VelociousSyncClientOfflineConfiguration = { /** * - App-owned durable device-identity storage adapter. */ deviceIdentityStorage: VelociousSyncClientDeviceIdentityStorage; /** * - App-owned enrollment hook: asks the backend to register the device public key and returns the backend-signed certificate. */ enrollDevice: (args: { configuration: import("./configuration.js").default; publicKey: import("./sync/device-identity.js").SyncJsonWebKey; }) => import("./sync/device-identity.js").DeviceCertificate | Promise; /** * - Resolves the scopes the bootstrap request asks the backend to materialize into the grant. */ grantScopes: (args: { configuration: import("./configuration.js").default; }) => Record | Promise>; /** * - Signed-bootstrap endpoint path. Defaults to "/frontend-models/sync/bootstrap". */ bootstrapPath?: string; /** * - Signed-replay endpoint path. Defaults to "/frontend-models/sync/replay". */ replayPath?: string; /** * - Backend public key used to verify device certificates and imported peer mutations. */ backendPublicKey?: import("./sync/device-identity.js").SyncJsonWebKey; /** * - Optional durable grant retention adapter. */ grantStorage?: VelociousSyncClientGrantStorage; /** * - Durable local mutation log the offline session replays and exports. Defaults to the conflict-tracking log declared by the synced models. */ mutationLog?: import("./sync/local-mutation-log.js").default; /** * - Session clock. Defaults to the current time. */ now?: () => Date; }; export type NormalizedVelociousSyncClientOfflineConfiguration = VelociousSyncClientOfflineConfiguration & { bootstrapPath: string; configuration: import("./configuration.js").default; now: () => Date; replayPath: string; }; export type NormalizedVelociousSyncClientConfiguration = VelociousSyncClientConfiguration & { mountPath: string; offline: NormalizedVelociousSyncClientOfflineConfiguration | undefined; }; export type NormalizedVelociousSyncConfiguration = VelociousSyncConfiguration & { client: NormalizedVelociousSyncClientConfiguration | undefined; }; export type VelociousSyncConfiguration = { /** * - Auto-mounts the Velocious sync changes/replay endpoints for this resource class. */ api?: VelociousSyncApiConfiguration; /** * - Client-side sync configuration as written by the app. The framework normalizes it into {@link NormalizedVelociousSyncClientConfiguration} (see {@link NormalizedVelociousSyncConfiguration}). */ client?: VelociousSyncClientConfiguration; /** * - Public backend key used to verify offline device certificates for sync replay. */ deviceCertificateBackendPublicKey?: import("./sync/device-identity.js").SyncJsonWebKey | null; /** * - Number of accepted server changes retained before clients must refresh from snapshot. */ changeFeedRetentionSize?: number; /** * - Signing keys used to issue and verify offline grants. Secrets must never be exposed to clients. */ offlineGrantSigningKeys: Array; /** * - Default offline grant TTL in milliseconds. Defaults to 24 hours. */ offlineGrantTtlMs?: number; }; export type NormalizedFrontendModelResourceSyncConfiguration = { /** * - Normalized replay conflict strategy. */ conflictStrategy: "optimisticVersion" | "serverWins" | "lastWriterWins" | "fieldThreeWay" | "appendOnly"; /** * - Whether the resource is sync-enabled. */ enabled: boolean; /** * - Sorted, duplicate-free sync operation names. */ operations: string[]; /** * - App-controlled policy version, or null. */ policyVersion: string | null; /** * - Deterministic sha256 hash of safe policy inputs. */ policyHash: string; /** * - Safe frontend-visible metadata. */ metadata?: Record; }; export type NormalizedFrontendModelResourceConfiguration = Omit & { abilities: FrontendModelResourceAbilitiesConfiguration; builtInCollectionCommands: Record; builtInMemberCommands: Record; collectionCommands: Record; commandMetadata: Record; returnType: string | null; }>; memberCommands: Record; quickSearchColumns: FrontendModelQuickSearchColumn[] | null; quickSearchNumericColumns: FrontendModelQuickSearchColumn[] | null; sync?: NormalizedFrontendModelResourceSyncConfiguration; }; export type UnboundFrontendModelResourceClassType = Omit & { modelClass: () => typeof import("./database/record/index.js").default; new (args: never): import("./frontend-model-resource/base-resource.js").default; }; export type BoundFrontendModelResourceClassType = Omit & { ModelClass: TModelClass | undefined; modelClass: () => TModelClass; new (args: import("./frontend-model-resource/base-resource.js").FrontendModelResourceAbilityArgs | import("./frontend-model-resource/base-resource.js").FrontendModelResourceControllerArgs): import("./frontend-model-resource/base-resource.js").default; }; export type FrontendModelResourceClassType> = [TModelClass] extends [never] ? UnboundFrontendModelResourceClassType : BoundFrontendModelResourceClassType; export type FrontendModelResourceDefinition = FrontendModelResourceClassType; export type FrontendModelResourceAbilitiesConfiguration = { /** * - Ability action for frontend index. */ index?: string; /** * - Ability action for frontend find. */ find?: string; /** * - Ability action for frontend create. */ create?: string; /** * - Ability action for frontend update. */ update?: string; /** * - Ability action for frontend destroy. */ destroy?: string; }; export type FrontendModelResourceServerConfiguration = { /** * - Optional callback run before built-in frontend actions. */ beforeAction?: (args: { action: "index" | "find" | "create" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; }) => (boolean | void | Promise); /** * - Records loader for frontendIndex. */ records?: (args: { action: "index"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; }) => Promise; /** * - Record serializer for response payloads. */ serialize?: (args: { action: "index" | "find" | "create" | "update"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; model: import("./database/record/index.js").default; }) => Record> | Promise>>; /** * - Record loader for find/update/destroy/attach/download/url actions. */ find?: (args: { action: "find" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; id: string | number; }) => Promise; /** * - Custom create callback. */ create?: (args: { action: "create"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; attributes: Record>; }) => Promise; /** * - Custom update callback. */ update?: (args: { action: "update"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; model: import("./database/record/index.js").default; attributes: Record>; }) => Promise; /** * - Custom destroy callback. */ destroy?: (args: { action: "destroy"; controller: import("./controller.js").default; params: Record>; modelClass: typeof import("./database/record/index.js").default; model: import("./database/record/index.js").default; }) => Promise; }; export type BackendProjectConfiguration = { /** * - Path to the backend project. May be an app root or a contributing package root (package entries are appended internally from `packages`). */ path: string; /** * - Optional output project path where `src/frontend-models` should be generated. */ frontendModelsOutputPath?: string; /** * - Optional override for the resources directory to auto-discover; defaults to `/src/resources`. Set internally for package entries. */ resourcesPath?: string; /** * - Auto-discovered frontend model definitions keyed by model class name. Set internally by the environment handler — do not set manually. */ frontendModels?: Record; /** * - Auto-discovered ability resource classes (frontend-model and authorization) from this project's resources directory. Set internally by the environment handler — do not set manually. */ abilityResources?: AbilityResourceClassType[]; }; export type VelociousPackageDescriptor = { /** * - The package name. */ name: string; /** * - The descriptor module's `import.meta.url`; the package root is derived from it when `path` is omitted. */ url?: string; /** * - The package root directory (the one containing `src`). Derived from `url` when omitted. */ path?: string; /** * - Override for the package's models directory (default `/src/models`). */ modelsPath?: string; /** * - Override for the package's frontend-model resources directory (default `/src/resources`). */ resourcesPath?: string; /** * - Override for the package's migrations directory (default `/src/database/migrations`). */ migrationsPath?: string; }; export type VelociousPackageConfiguration = import("./packages/velocious-package.js").default | VelociousPackageDescriptor; export type RouteResolverHookArgs = { /** * - Configuration instance. */ configuration: import("./configuration.js").default; /** * - Mutable request params object. */ params: Record>; /** * - Request path without query. */ currentPath: string; /** * - True when matching a configured custom route. */ hasMatchingCustomRoute?: boolean; /** * - Request object. */ request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default; /** * - Response object. */ response: import("./http-server/client/response.js").default; /** * - Resolver instance. */ resolver: import("./routes/resolver.js").default; }; export type RouteResolverHookResult = { /** * - Dasherized action name (for example `frontend-index`). */ action: string; /** * - Controller path (for example `accounts`). */ controller: string; /** * - Optional controller class override. */ controllerClass?: typeof import("./controller.js").default; /** * - Optional absolute/relative controller file path override. */ controllerPath?: string; /** * - Extra params to merge for controller/action. */ params?: Record>; /** * - Whether to run the controller action without resolving request ability. */ skipAbilityResolution?: boolean; /** * - Whether to run the controller action without the automatic database checkout wrapper. */ skipControllerConnections?: boolean; /** * - Whether to run the controller action without resolving request tenant. */ skipTenantResolution?: boolean; /** * - Optional view path override used by controller render lookups. */ viewPath?: string; }; export type RouteResolverHookType = (arg: RouteResolverHookArgs) => RouteResolverHookResult | null | Promise; export type AbilityResourceClassType = typeof import("./authorization/base-resource.js").default; export type AbilityResolverType = (args: { configuration: import("./configuration.js").default; params: Record>; request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined; response: import("./http-server/client/response.js").default | undefined; }) => import("./authorization/ability.js").default | void | Promise; export type TenantResolverType = (args: { configuration: import("./configuration.js").default; params: Record>; request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined; response: import("./http-server/client/response.js").default | undefined; subscription?: { channel: string; params?: Record>; }; }) => ReturnType | void | Promise | void>; export type TenantDatabaseResolverType = (args: { configuration: import("./configuration.js").default; databaseConfiguration: DatabaseConfigurationType; identifier: string; tenant: ReturnType; }) => DatabaseConfigurationType | Partial | void; export type ApiManifestConfiguration = { /** * - HTTP path for the built-in API manifest endpoint. Defaults to `/api/manifest`. */ path?: string; /** * - Bearer token required in the `Authorization: Bearer ` header. When set, requests without a matching token are not routed (404), so the endpoint stays hidden. */ token?: string; }; export type McpConfiguration = { /** * - HTTP path for the built-in MCP endpoint. Defaults to `/mcp`. */ path?: string; /** * - Bearer token required in the `Authorization` header. When set, requests without a matching token are not routed (404), so the endpoint stays hidden. */ token?: string; }; export type DebugEndpointConfiguration = { /** * - HTTP path for the built-in debug endpoint. Defaults to `/velocious/debug`. */ path?: string; /** * - Bearer token required in the `Authorization: Bearer ` header. When set, requests without a matching token are not routed (404), so the endpoint stays hidden. */ token?: string; }; export type TestTenantPoolConfiguration = { /** * - Pool members: the tenant descriptors whose databases the pool pre-provisions and re-uses. Pool size is the array length. */ tenants: Array>; /** * - App-owned provisioning override for one member (runs instead of the framework create + structure-load + ledger-baseline default). */ provisionTenant?: (args: { configuration: import("./configuration.js").default; databaseIdentifier: string; tenant: ReturnType; }) => void | Promise; /** * - App-owned per-test reset override (runs instead of the framework truncate + ledger-baseline default). */ resetTenant?: (args: { configuration: import("./configuration.js").default; databaseIdentifier: string; tenant: ReturnType; }) => void | Promise; }; export type TestTenantPoolsConfiguration = Record; export type TenantDatabaseProviderType = { /** * - Lists tenants that should be created, checked, or migrated for this database identifier. */ listTenants: (args: { configuration: import("./configuration.js").default; identifier: string; }) => Array> | Promise>>; /** * - Resolves one explicit tenant descriptor for schema/base-model generation without enumerating lifecycle tenants. */ resolveGenerationTenant?: (args: { configuration: import("./configuration.js").default; identifier: string; }) => ReturnType | void | Promise | void>; /** * - Lists existing tenants that should be checked for dependent restrict destroys. Defaults to listTenants. */ listRestrictTenants?: (args: { configuration: import("./configuration.js").default; identifier: string; }) => Array> | Promise>>; /** * - Creates the tenant database/schema for one tenant. */ createDatabase?: (args: { configuration: import("./configuration.js").default; databaseConfiguration: DatabaseConfigurationType; identifier: string; tenant: ReturnType; }) => void | Promise; /** * - Drops the tenant database/schema for one tenant. */ dropDatabase?: (args: { configuration: import("./configuration.js").default; databaseConfiguration: DatabaseConfigurationType; identifier: string; tenant: ReturnType; }) => void | Promise; /** * - Checks one tenant database before generic connection validation. */ checkTenant?: (args: { configuration: import("./configuration.js").default; databaseConfiguration: DatabaseConfigurationType; identifier: string; tenant: ReturnType; }) => void | Promise; /** * - Runs app-owned tenant work after generic migrations for one tenant. `migrationsApplied` is how many migrations actually ran (0 when the tenant was already up to date), so the app can skip expensive per-tenant work on no-op deploys. */ afterMigrateTenant?: (args: { configuration: import("./configuration.js").default; databaseConfiguration: DatabaseConfigurationType; identifier: string; migrationsApplied: number; tenant: ReturnType; }) => void | Promise; }; export type AdvisoryLocksConfiguration = { /** * - Backend enablement. `file.enabled` defaults to false; enabling it is the deployment's explicit single-host declaration. `lockServer` defaults to enabled when a host/port/url or the `VELOCIOUS_LOCK_SERVER_HOST`/`_PORT` env pair is configured. */ backends?: { file?: { directory?: string; enabled?: boolean; leaseMs?: number; renewIntervalMs?: number; }; lockServer?: { authToken?: string; connectTimeoutMs?: number; enabled?: boolean; host?: string; leaseMs?: number; port?: number; reprobeCooldownMs?: number; url?: string; }; }; /** * - Per-lock-name minimum/allowed/preferred tier rules (design §5). */ policy?: import("./database/advisory-lock-backend-policy.js").AdvisoryLockBackendPolicyEntry[]; }; export type ConfigurationArgsType = { /** * - Globally enable auto-batch-preload of relationships on lazy access. Default true. */ autoload?: boolean; /** * - CORS configuration for the HTTP server. */ cors?: CorsType; /** * - Secret for encrypting cookies. */ cookieSecret?: string; /** * - Resource classes used to define abilities per model. */ abilityResources?: AbilityResourceClassType[]; /** * - Resolver for creating request-scoped ability instances. */ abilityResolver?: AbilityResolverType; /** * - Advisory-lock backend chain configuration (backends + per-lock-name tier policy). Defaults to today's driver-native-only behavior. */ advisoryLocks?: AdvisoryLocksConfiguration; /** * - Attachment storage configuration. */ attachments?: AttachmentsConfiguration; /** * - Backend project definitions used for frontend model generation. */ backendProjects?: BackendProjectConfiguration[]; /** * - External Velocious packages that contribute models, frontend-model resources and migrations. */ packages?: VelociousPackageConfiguration[]; /** * - Database configurations keyed by environment and identifier, or false for an explicitly database-free application. */ database?: false | { [key: string]: { [key: string]: DatabaseConfigurationType; }; }; /** * - Enable debug logging. */ debug?: boolean; /** * - Enable the built-in debug endpoint. Defaults to false. */ debugEndpoint?: boolean | DebugEndpointConfiguration; /** * - Enable the built-in API manifest endpoint. Defaults to false. */ apiManifest?: boolean | ApiManifestConfiguration; /** * - Enable the built-in MCP endpoint on the HTTP server (JSON-RPC over HTTP in addition to the `velocious mcp` stdio server). Defaults to false. */ mcp?: boolean | McpConfiguration; /** * - Base directory for the project. */ directory?: string; /** * - Require tenant-switched model queries to resolve a tenant database identifier. Defaults to true. */ enforceTenantDatabaseScopes?: boolean; /** * - Current environment name. */ environment?: string; /** * - Environment handler instance. */ environmentHandler: import("./environment-handlers/base.js").default; /** * - Return unexpected internal error messages and stack traces in frontend-model client payloads in every environment. Defaults to true. */ exposeInternalErrorsToClients?: boolean; /** * - Bounded frontend tenant SQLite lifecycle configuration. */ frontendTenantSqlite?: { maxOpenHandles?: number; }; /** * - Deprecated compatibility alias for `exposeInternalErrorsToClients: false` when the authoritative option is omitted. */ secureFrontendModelErrors?: boolean; /** * - Default HTTP server configuration for applications started from this configuration. */ httpServer?: HttpServerConfiguration; /** * - Logging configuration. */ logging?: LoggingConfiguration; /** * - Background jobs configuration. */ backgroundJobs?: BackgroundJobsConfiguration; /** * - Beacon broadcast bus configuration. */ beacon?: BeaconConfiguration; /** * - Scheduled background jobs configuration. */ scheduledBackgroundJobs?: ScheduledBackgroundJobsConfiguration | ScheduledBackgroundJobsLoaderType; /** * - Mail delivery backend. */ mailerBackend?: MailerBackend; /** * - Hook to register models for a given initialization type. */ initializeModels: (args: { configuration: import("./configuration.js").default; processContext: ApplicationProcessContext | undefined; type: string; }) => void; /** * - Initializer loader for environment bootstrapping. */ initializers?: InitializersType; /** * - Default locale or locale resolver. */ locale: string | (() => string); /** * - Supported locales. */ locales: string[]; /** * - Locale fallback map. */ localeFallbacks: LocaleFallbacksType; /** * - Structure SQL generation configuration. */ structureSql?: StructureSqlConfiguration; /** * - Local/offline sync framework configuration. */ sync?: VelociousSyncConfiguration; /** * - Resolver for creating request-scoped tenant context objects. */ tenantResolver?: TenantResolverType; /** * - Resolver for deriving tenant-specific database config overrides. */ tenantDatabaseResolver?: TenantDatabaseResolverType; /** * - Tenant database lifecycle providers keyed by database identifier. */ tenantDatabaseProviders?: Record; /** * - Opt-in reusable test tenant-database pools keyed by tenant database identifier. Consumed only by the test harness; ordinary runtime ignores it. */ testTenantPools?: TestTenantPoolsConfiguration; /** * - Path to the testing configuration file. */ testing?: string; /** * - Default timezone for timezone-less datetime strings. */ timeZone?: string | (() => string | undefined); /** * - Default timezone offset in minutes. */ timezoneOffsetMinutes?: number | (() => number); /** * - Trusted reverse proxy address ranges used to resolve request remote addresses from forwarding headers. */ trustedProxies?: string | string[]; /** * - Timeout in seconds for completing a HTTP request. */ requestTimeoutMs?: number | (() => number); /** * - Hook callbacks that can hijack unresolved routes. */ routeResolverHooks?: RouteResolverHookType[]; /** * - Resolve a websocket channel class/instance for each connection. */ websocketChannelResolver?: WebsocketChannelResolverType; /** * - Resolve a raw websocket message handler for each connection. */ websocketMessageHandlerResolver?: WebsocketMessageHandlerResolverType; }; /** * Resolved lock-service configuration after environment and Beacon defaults. * @typedef {object} LockServiceResolvedConfigType * @property {string} [authToken] - Shared secret enforced by the host, when configured. * @property {number} connectBackoffMs - Base backoff between connection retries. * @property {number} connectRetries - Bounded connection retries before giving up. * @property {number} connectTimeoutMs - Handshake timeout. * @property {"database" | "none"} fallback - What to do when the service is unreachable. * @property {string} host - Lock-service host. * @property {number} leaseMs - Lease duration advertised to clients. * @property {"beacon" | "in-process" | "off"} mode - Where the authority lives. * @property {string} namespace - Prefix applied to every lock name. * @property {number} port - Lock-service port. * @property {string | null} statePath - Durable mirror for epochs and holders. */ /** * @module types */ /** * Immutable identity shared by application hooks and initializers for one process lifecycle. * @typedef {object} ApplicationProcessContext * @property {string} type - Generic process type supplied to `configuration.initialize()`. * @property {string} instanceId - Opaque identity unique to this lifecycle. */ /** * @typedef {(args: {request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default, response: import("./http-server/client/response.js").default}) => Promise} CorsType */ /** * @typedef {(args: {request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined, subscription?: {channel: string, params?: Record>}, client: import("./http-server/client/index.js").default, websocketSession: import("./http-server/client/websocket-session.js").default, configuration: import("./configuration.js").default}) => typeof import("./http-server/websocket-channel.js").default | import("./http-server/websocket-channel.js").default | void | Promise} WebsocketChannelResolverType */ /** * @typedef {object} WebsocketMessageHandler * @property {(args: {message: ReturnType, session: import("./http-server/client/websocket-session.js").default}) => Promise | void} [onMessage] - Handler for incoming websocket messages. * @property {(args: {session: import("./http-server/client/websocket-session.js").default}) => Promise | void} [onOpen] - Handler when the websocket session opens. * @property {(args: {session: import("./http-server/client/websocket-session.js").default}) => Promise | void} [onClose] - Handler when the websocket session closes. * @property {(args: {error: Error, session: import("./http-server/client/websocket-session.js").default}) => Promise | void} [onError] - Handler when a websocket message errors. */ /** * @typedef {(args: {request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined, client: import("./http-server/client/index.js").default, configuration: import("./configuration.js").default}) => WebsocketMessageHandler | void | Promise} WebsocketMessageHandlerResolverType */ /** * @typedef {(id: string) => {default: typeof import("./initializer.js").default}} InitializersRequireContextType * @typedef {InitializersRequireContextType & { * keys: () => string[], * id: string * }} WebpackRequireContext * @typedef {{requireContext: WebpackRequireContext}} InitializersExportType * @typedef {(args: {configuration: import("./configuration.js").default}) => Promise} InitializersType */ /** * @typedef {object} SqlConfig * @property {string} [database] - Database name for the SQL driver. * @property {object} [options] - Driver-specific connection options. * @property {boolean} [options.encrypt] - Whether to encrypt the connection (MSSQL). * @property {string} [options.schema] - Default schema for unqualified table lookups (MSSQL). * @property {string} [options.serverName] - TLS SNI server name override for MSSQL (empty string disables SNI). * @property {boolean} [options.trustServerCertificate] - Whether to trust the server certificate (MSSQL). * @property {string} [password] - Password for the SQL user. * @property {object} [pool] - Connection pool configuration. * @property {number | null} [pool.max] - Maximum number of connections. Set null to disable the cap. * @property {number} [pool.min] - Minimum number of connections. * @property {number} [pool.idleTimeoutMillis] - Idle timeout before releasing a connection. * @property {number | null} [pool.checkoutTimeoutMillis] - Timeout while waiting for an available connection after the max connection cap is reached. Set null to wait indefinitely. * @property {string} [server] - SQL server hostname. * @property {string} [user] - SQL username. */ /** * @typedef {object} DatabasePoolConfiguration * @property {number | null} [checkoutTimeoutMillis] - Timeout while a checkout waits for an available async-tracked connection after the max live connection cap is reached. Set null to wait indefinitely. Default: 10000. * @property {number | null} [idleTimeoutMillis] - Idle timeout before closing a checked-in async-tracked connection. Set null to disable idle reaping. Default: 5000. * @property {number | null} [max] - Maximum live async-tracked connections for this pool. Defaults to 10. Extra checkouts wait until a matching connection is checked in or capacity is freed. Set null to disable the cap. */ /** * @typedef {object} DatabaseConfigurationType * @property {number | null} [advisoryLockAcquireTimeoutMs] - Bound (ms) a blocking advisory-lock acquisition waits for a contended lock before reporting failure. Default: `900000` (15 minutes). `null` opts out and restores the driver's indefinite wait. A per-call `timeoutMs` argument always overrides this. * @property {{slowAcquireMs?: number | null, slowHoldMs?: number | null}} [advisoryLockTelemetry] - Event-driven advisory-lock duration telemetry thresholds. `slowAcquireMs` (default `5000`) reports an acquire wait that completed slower than the threshold, including the eventual outcome; `advisory-lock-acquire-timeout` always fires when a wait exceeds its bound and carries the holder identity available on the tier at that moment. `slowHoldMs` (default `60000`) reports a hold that outlives the threshold at release. `null` disables that report. Reports fire on the events themselves — no periodic scanner — on `getTelemetryEvents()` as `telemetry` with `context: "advisory-lock-telemetry"`. See [docs/advisory-locks.md](../docs/advisory-locks.md). * @property {string} [databaseCharset] - Default character set applied by `db:create` via mysql/mariadb `CREATE DATABASE ... CHARACTER SET`. Distinct from `charset`, which is the client connection charset forwarded to the mysql2 driver. * @property {string} [databaseCollation] - Default collation applied by `db:create` via mysql/mariadb `CREATE DATABASE ... COLLATE`. * @property {string} [database] - Database name for this connection. * @property {number} [deadlockMaxRetries] - Maximum attempts for the outermost transaction when it keeps hitting deadlocks. Defaults to 8. * @property {number} [deadlockBaseWaitMs] - Base delay (ms) for the deadlock retry backoff; the per-attempt ceiling doubles from here. Defaults to 50. * @property {number} [deadlockMaxWaitMs] - Cap (ms) on the deadlock retry backoff ceiling so the jittered wait stays bounded. Defaults to 1000. * @property {typeof import("./database/drivers/base.js").default} [driver] - Driver class to use for this database. * @property {typeof import("./database/pool/base.js").default} [poolType] - Pool class to use for this database. * @property {() => ReturnType} [getConnection] - Custom connection factory override. * @property {string} [host] - Database host. * @property {boolean} [migrations] - Whether migrations are enabled for this database. * @property {boolean} [multipleStatements] - (MySQL) Opt in to multi-statement queries so structure SQL loads and all-table cleanup can batch into one round-trip. Off by default; ordinary queries otherwise reject stacked statements. * @property {number} [maxRowsPerInsert] - Maximum rows per `INSERT ... VALUES (...), (...), ...` statement generated by `Record.insertMultiple`. Defaults to 500. * @property {number} [maxInsertSqlBytes] - Maximum serialized SQL size, in bytes, for a single `INSERT ... VALUES (...), (...), ...` statement. Defaults to 1 MiB (1048576). * @property {number} [maxInClauseValues] - Maximum values in a single `IN (...)` cohort used by preloads, association counts, and queryData aggregates. Defaults to 999. * @property {number} [maxQuerySqlBytes] - Maximum serialized SQL size, in bytes, for a single cohort query used by preloads, association counts, and queryData aggregates. Defaults to 1 MiB (1048576). * @property {string} [password] - Password for the database user. * @property {number} [port] - Database port. * @property {string} [primaryKeyType] - Default type for implicit migration primary keys and references. Defaults to `uuid`. * @property {DatabasePoolConfiguration} [pool] - Velocious database pool lifecycle configuration. * @property {string} [name] - Friendly name for the configuration. * @property {(file: string) => string} [locateFile] - Optional sqlite-web sql.js wasm resolver (`initSqlJs({locateFile})`). * @property {boolean} [readOnly] - Whether writes should be blocked for this database. * @property {string} [schema] - Default schema for unqualified table lookups (MSSQL). * @property {boolean} [schemaCache] - Whether schema metadata should be cached on the driver. Defaults to true. * @property {number} [schemaMetadataRetryDeadlineMs] - Bounded deadline (ms) for outlasting a cached schema-metadata read the server skipped because concurrent online DDL is modifying the table. Defaults to 60000. * @property {object} [record] - Record-level configuration. * @property {boolean} [record.transactions] - Whether record operations should use transactions. * @property {boolean} [reset] - Whether to reset the database on startup. * @property {SqlConfig} [sqlConfig] - Driver-specific SQL config. * @property {boolean} [tenantOnly] - Whether this database identifier is only active inside a resolved tenant context. * @property {"mssql" | "mysql" | "pgsql" | "sqlite"} [type] - Database type identifier. * @property {string} [useDatabase] - Database to switch to after connecting. * @property {string} [username] - Username for database authentication. */ /** * @typedef {"debug-low-level" | "debug" | "info" | "warn" | "error"} LogLevel */ /** * @typedef {object} LoggingOutputPayload * @property {LogLevel} level - Log level. * @property {string} message - Formatted message. * @property {string} subject - Log subject. * @property {Date} timestamp - Timestamp. */ /** * @typedef {object} LoggingOutput * @property {(arg: LoggingOutputPayload) => Promise | void} write - Write a log entry. * @property {LogLevel[]} [levels] - Default levels for this output. */ /** * @typedef {object} LoggingOutputConfig * @property {LoggingOutput} output - Output instance. * @property {Array} [levels] - Levels enabled for this output. */ /** * @typedef {LoggingOutputConfig | LoggingOutput | import("./logger/base-logger.js").default} LoggerConfig */ /** * @typedef {object} LoggingConfiguration * @property {boolean} [console] - Enable/disable console logging for request logging. Defaults to true outside of "test" and for HTTP server logs. * @property {boolean} [file] - Enable/disable writing logs to a file. Defaults to true. * @property {string} [directory] - Directory where log files are stored. Defaults to "/log". * @property {string} [filePath] - Explicit path for the log file. Defaults to "/.log". * @property {Array<"debug-low-level" | "debug" | "info" | "warn" | "error">} [levels] - Override which log levels are emitted. * @property {boolean} [debugLowLevel] - Convenience flag to include very low-level debug logs. * @property {boolean} [queryLogging] - Enable/disable database query logging. Defaults to true outside test and false in test. * @property {string[]} [sensitiveNames] - Additional case-insensitive sensitive header/parameter names to redact from logging. * @property {LoggerConfig[]} [loggers] - Logger instances (converted to outputs when configured). * @property {LoggingOutputConfig[]} [outputs] - Explicit logger outputs (overrides console/file defaults when provided). */ /** * @typedef {object} StructureSqlConfiguration * @property {string[]} [enabledEnvironments] - Environments allowed to write structure sql files during automatic migration dumps. * @property {string[]} [disabledEnvironments] - Environments that should skip writing structure sql files. */ /** * @typedef {"beacon" | "polling"} BackgroundJobsDispatchStrategy * * - `"beacon"` (default): event-driven dispatch. The * `background-jobs-main` process drains the queue on enqueue, on * worker readiness, on Beacon broadcasts (so cross-process enqueues * wake it), and arms a `setTimeout` for the soonest future-scheduled * job. Falls back gracefully to direct in-process triggering when * Beacon is not configured. * - `"polling"`: legacy mode, runs a fixed-interval poll over the * `background_jobs` table (see `pollIntervalMs`). */ /** @typedef {"background" | "inline"} BackgroundJobsMode */ /** @typedef {"candidate" | "active" | "retired"} BackgroundJobsGenerationInitialState */ /** @typedef {(args: {configuration: import("./configuration.js").default}) => import("./background-jobs/adapter.js").default} BackgroundJobsAdapterFactory */ /** @typedef {typeof import("./background-jobs/platform-job.js").default} BackgroundJobClass */ /** * @typedef {object} BackgroundJobsConfiguration * @property {import("./background-jobs/adapter.js").default | BackgroundJobsAdapterFactory} [adapter] - Adapter instance or synchronous factory. A factory creates one adapter per configuration lifecycle; the framework closes adapters it resolves. * @property {BackgroundJobClass[]} [jobClasses] - Static portable job classes available to Browser/Expo local dispatch. Defaults to `[]`; Node keeps its filesystem registry. * @property {BackgroundJobsMode} [mode] - `"background"` uses the configured adapter/transport and durable queue semantics; `"inline"` performs immediately without durable queue state. Defaults to `"background"`. * @property {string} [generationId] - Opt-in release generation identity. Must match `^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$` and agree with environment/API/CLI sources. * @property {BackgroundJobsGenerationInitialState} [initialGenerationState] - Generation-aware boot state. Defaults to `"candidate"`; invalid without `generationId`. * @property {string} [lifecycleSocketPath] - Absolute release-local Unix socket used by acknowledged activation and retirement commands. * @property {string} [host] - Hostname for the background jobs main process. * @property {number} [port] - Port for the background jobs main process. * @property {string} [databaseIdentifier] - Database identifier used to store background jobs. Browser/Expo local dispatch uses this existing SQLite database and defaults to `"default"`. * @property {number} [maxConcurrentInlineJobs] - How many `forked: false` jobs a single * `background-jobs-worker` process is allowed to run in parallel. Concurrency * is at the JS event-loop level: every concurrent job shares the worker's * process and DB connection pool, so this should fit the pool size, not the * CPU count. Forking remains the right tool for memory isolation across * long-running jobs and for using more cores. Default: `4`. * @property {number} [maxConcurrentForkedJobs] - How many out-of-process * `"forked"` or `"spawned"` jobs a single `background-jobs-worker` is * allowed to keep in flight. Default: `4`. This is a per-worker safety cap; * for workload-shaped limits use per-queue caps (`queues`) instead, which are * enforced cluster-wide and are immune to duplicate worker processes. * @property {number} [pooledRunnerCount] - Number of warm, reusable child runners owned by each worker. Pooled capacity is separate from inline and forked/spawned capacity. Default: `4`. * @property {number} [pooledRunnerConcurrency] - Number of jobs each pooled child runs concurrently on its own event loop. Total per-worker pooled capacity is `pooledRunnerCount × pooledRunnerConcurrency`. `1` (default) keeps each child serial; raise it for I/O-bound jobs so a bounded set of isolated processes handles high concurrency (like the inline lane) without one process per concurrent job. Default: `1`. * @property {number} [pooledRunnerMaxJobs] - Number of sequential jobs a pooled child runs before it is replaced, bounding process-level resource accumulation. Default: `100`. * @property {number} [pooledRunnerMaxRssBytes] - Peak RSS (the kernel `VmHWM` high-water mark reported by the child) at which a pooled child is replaced after an acknowledged job. The child's peak, not its settled RSS at job-outcome time, is the trigger, so a burst working-set that reclaims before the outcome still retires the child. Default: `536870912` (512 MiB). * @property {number} [pooledRunnerMaxLifetimeMs] - Age after an acknowledged job at which a pooled child is replaced. Default: `3600000` (one hour). * @property {number} [pooledRunnerSilenceTimeoutMs] - IPC-silence bound for a pooled child with in-flight jobs. A child that sends nothing (readiness, acceptance, memory observation, or job outcome) for longer than this is declared wedged: its in-flight jobs are reported failed for requeue, its capacity is re-advertised, and the wedged process is terminated. A healthy child samples itself every 10 seconds while jobs run, so the bound only fires on a child that cannot prove it is alive. Default: `120000`. * @property {number} [runnerMaxOldSpaceSizeMb] - V8 heap cap (`--max-old-space-size`, MiB) applied to every background-jobs runner child process (pooled, forked, and spawned) so a single child can never commit multiple GBs of heap. Default: `2048`. * @property {number} [runnerMallocArenaMax] - `MALLOC_ARENA_MAX` exported to every background-jobs runner child process, bounding glibc per-thread arenas. Defaults to an inherited `MALLOC_ARENA_MAX`, else `4`. * @property {Record} [queues] - Per-queue * concurrency caps and dispatch priorities, Sidekiq-style. A job declares its queue (static * `queue` on the job class, or the `queue` enqueue option; defaults to `"default"`), and * `queues[name].maxConcurrent` bounds how many jobs from that queue may be * in flight across the whole cluster (enforced via durable per-key * concurrency, so it holds regardless of how many worker processes run). * Size each queue to its workload: I/O-bound queues (e.g. build runners * waiting on remote Docker servers) can run far above the core count, while * CPU-bound queues should stay near it. `queues[name].priority` (default `0`) * makes the main process dispatch higher-priority queues before lower-priority * ones regardless of enqueue order, so a small time-critical queue can never be * starved by a flood of low-priority work sharing a worker pool. Unlike * Sidekiq's strict queue ordering, priority composes with the per-queue caps: * a higher-priority queue that is already at its `maxConcurrent` is skipped and * dispatch falls through to the next eligible lower-priority job, so a busy * high-priority queue does not block everything else. This fallthrough is a * property of the queue-derived cap; a job that supplies its own explicit * `concurrencyKey`/`maxConcurrency` bypasses the queue cap entirely (an * explicit key always wins — see above) and is bounded only by that key, so it * is not held back by the queue's cap and priority simply orders it normally. * Priorities may be any number, including negative to sink a queue below the * default. Jobs within the same priority keep FIFO (`scheduled_at`, then * `created_at`) order. Default: `{}` (no queue caps, all queues priority `0`). * @property {number | null} [scheduledEnqueueTimeoutMs] - Bounds one scheduled enqueue attempt in the main process. A durable enqueue that never settles (wedged DB connection, contended advisory lock) would otherwise keep its schedule key permanently in flight, so every later tick skipped itself and shutdown could never drain. On timeout the attempt is reported as `background-jobs-scheduled-enqueue-stall` and the key clears for the next tick. Default: 20 minutes — deliberately 5 minutes above `advisoryLockAcquireTimeoutMs` so the precise lock error surfaces first. `null` opts out. * @property {BackgroundJobsDispatchStrategy} [dispatchStrategy] - How the main process * detects new work. Defaults to `"beacon"` (event-driven). Set to `"polling"` * to restore the legacy fixed-interval poll. * @property {number} [pollIntervalMs] - Poll interval in milliseconds. Only used * when `dispatchStrategy === "polling"`. Default: `1000`. * @property {number} [drainStoreOperationTimeoutMs] - Bounds one drain-critical * store operation in the main process: the queued-job lookup, the durable * handoff claim, and handoff-recovery transitions. A store call that never * settles (wedged DB connection, lost acknowledgement) would otherwise freeze * the coalesced drain and every later dispatch queued behind it until the * process is killed; on timeout the drain fails into its existing * error/retry path and the stall is reported as a framework error. * Default: `60000`. * @property {number | null} [jobTimeoutMs] - Wall-clock backstop, in ms, for a * `"forked"` job runner. A forked job still running after this is terminated * (SIGTERM, then SIGKILL after the reaping grace) and reported failed, so a * single genuinely-hung runner can't pin a draining worker — and its full-app * boot and DB connections — indefinitely (e.g. across a deploy where a retired * worker drains in-flight jobs). This is a coarse safety net, not per-job * tuning: set it well above the longest legitimate forked job (build runners, * long imports) so only genuinely-stuck runners are killed. Omit, `null`, or * `<= 0` to disable (default), which preserves the prior unbounded behavior. * @property {BackgroundJobsRetentionConfiguration} [retention] - Retention/pruning * of terminal job rows. Without pruning the jobs table grows unbounded * (completed rows accumulate forever), which bloats storage and indexes and * eventually slows dispatch. The main process sweeps terminal rows past their * window on an interval. */ /** * @typedef {object} BackgroundJobsRetentionConfiguration * @property {number | null} [completedTtlMs] - Delete `completed` jobs whose * `completed_at_ms` is older than this many ms. `null` or `<= 0` disables * completed pruning. Default: `604800000` (7 days). * @property {number | null} [failedTtlMs] - Delete terminal `failed`/`orphaned` * jobs older than this many ms. `null` or `<= 0` disables (keeps them for * debugging). Default: `2592000000` (30 days). * @property {number} [batchSize] - Rows deleted per batch. Default: `1000`. * @property {number} [sweepIntervalMs] - How often the retention sweep runs. * Default: `3600000` (1 hour). */ /** * Fully-resolved retention config as returned by `getBackgroundJobsConfig()` * (every field defaulted), as opposed to the partial user-provided input. * @typedef {object} ResolvedBackgroundJobsRetentionConfiguration * @property {number | null} completedTtlMs - Resolved completed-job TTL in ms (`null` disables). * @property {number | null} failedTtlMs - Resolved failed/orphaned TTL in ms (`null` disables). * @property {number} batchSize - Resolved delete batch size. * @property {number} sweepIntervalMs - Resolved sweep interval in ms. */ /** * @typedef {object} BeaconConfiguration * @property {boolean} [enabled] - Whether to connect to a Beacon broker. Defaults to false unless `host`/`port` or `inProcess: true` are set, or env vars are present. Explicit `false` disables Beacon even when env vars are set. * @property {boolean} [inProcess] - When true, use a module-level in-process broker singleton instead of connecting over TCP. Mutually exclusive with `host`/`port`. Useful for tests and single-process deployments. * @property {string} [host] - Hostname of the Beacon broker daemon. * @property {number} [port] - Port of the Beacon broker daemon. * @property {string} [peerType] - Optional human-readable label for this peer (e.g. "server", "background-jobs-worker"). * @property {number} [unreachableReportMs] - Grace window (ms) a beacon connect/disconnect blip must persist before it is reported as a framework-error. Transient outages that recover within this window (e.g. a deploy restarting the broker) are not reported. Defaults to 30000. */ /** * @typedef {object} HttpCompressionConfiguration * @property {boolean} [enabled] - Whether buffered response compression is enabled. Defaults to true; set false to disable globally. * @property {number} [threshold] - Minimum buffered body size in bytes before compression is applied. Defaults to 1024. * @property {number} [brotliQuality] - Brotli encoder quality (0-11). Defaults to 4. * @property {number} [gzipLevel] - Gzip compression level (0-9). Defaults to 6. */ /** * @typedef {object} NormalizedHttpCompressionConfiguration * @property {boolean} enabled - Whether buffered HTTP response compression is enabled. * @property {number} threshold - Minimum buffered body size in bytes before compression is applied. * @property {number} brotliQuality - Brotli encoder quality (0-11). * @property {number} gzipLevel - Gzip compression level (0-9). */ /** * @typedef {object} HttpRequestBodyPolicyResolverArgs * @property {Record} headers - Complete request headers as received by the parser. * @property {string} httpMethod - Uppercase HTTP method. * @property {string} path - Request target, including its query string when present. */ /** * @typedef {object} HttpRequestBodyPolicy * @property {number} [maxRequestBodyBytes] - Per-request decoded body limit. Falls back to the global limit when omitted. * @property {"parsed" | "raw"} [mode] - Parsed params by default; raw preserves exact bytes and skips body decoding. */ /** @typedef {(args: HttpRequestBodyPolicyResolverArgs) => HttpRequestBodyPolicy | undefined} HttpRequestBodyPolicyResolver */ /** * @typedef {object} ResolvedHttpRequestBodyPolicy * @property {number | undefined} maxRequestBodyBytes - Effective decoded body limit. * @property {"parsed" | "raw"} mode - Effective body handling mode. */ /** * @typedef {object} HttpServerConfiguration * @property {boolean | HttpCompressionConfiguration} [compression] - Buffered response compression. Enabled with documented defaults when absent; false or {enabled: false} disables it globally. * @property {string} [host] - Hostname to bind the HTTP server to. * @property {boolean} [inProcess] - Run HTTP handlers in the main thread instead of worker threads. * @property {number} [maxBufferedResponseBodyBytes] - Maximum UTF-8/binary byte length accepted by buffered response bodies. Unbounded when absent; streamed file responses are unaffected. * @property {number} [maxRequestBodyBytes] - Maximum decoded request-body bytes accepted before routing. Unbounded when absent, except the built-in MCP endpoint, which defaults to a 1 MiB cap that this option overrides. * @property {HttpRequestBodyPolicyResolver} [requestBodyPolicyResolver] - Optional synchronous header-stage resolver for per-request limits and raw-body handling. * @property {number} [maxWorkers] - Backward-compatible alias for workers. * @property {number} [port] - Port to bind the HTTP server to. * @property {{maxPendingBytes?: number, maxPendingMessages?: number}} [websocketInboundQueue] - Per-session retained inbound WebSocket message limits. * @property {{maxPendingBytes?: number, maxPendingFrames?: number}} [websocketOutboundQueue] - Per-client retained outbound WebSocket frame limits. * @property {number} [workers] - Worker handlers to start for the HTTP server. */ /** * @typedef {object} ScheduledBackgroundJobEveryOptions * @property {number | string} [firstIn] - Delay before the first enqueue. */ /** * @typedef {object} ScheduledBackgroundJobConfiguration * @property {Array>} [args] - Arguments passed to the job when enqueued. * @property {typeof import("./background-jobs/job.js").default} class - Job class to enqueue. * @property {string} [cron] - Crontab expression (5-field POSIX, plus `@hourly`/`@daily`/`@weekly`/`@monthly`/`@yearly`/`@midnight`). Mutually exclusive with `every`. * @property {boolean} [enabled] - Whether the schedule is enabled. * @property {number | string | [number | string, ScheduledBackgroundJobEveryOptions]} [every] - Repeat interval. Either `every` or `cron` must be set. * @property {import("./background-jobs/types.js").BackgroundJobOptions} [options] - Job options. */ /** * @typedef {Record} VelociousParams */ /** * @typedef {Record} ClientErrorPayloadReporterPayload */ /** * @typedef {object} ErrorRequestDetails * @property {ReturnType} [body] - Sanitized parsed request body, when available. * @property {string} httpMethod - Request HTTP method. * @property {string} path - Request path. */ /** * @typedef {object} ClientErrorPayloadContext * @property {string} controller - Controller class name. * @property {string} [action] - Controller action or endpoint label. * @property {"index" | "find" | "create" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url" | "custom-command"} [commandType] - Frontend-model command type. * @property {string} [correlationId] - Server-generated identifier shared by an unexpected client error and framework reports. * @property {boolean} [expectedError] - Whether the error is an expected user-flow failure. * @property {boolean} [frontendModelEndpoint] - Whether the error came from the frontend-model endpoint. * @property {string} [model] - Frontend-model name from the failed request. * @property {string} [requestId] - Shared frontend-model request id. */ /** * @typedef {(args: { * context: ClientErrorPayloadContext, * error: Error, * request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined, * requestDetails: ErrorRequestDetails | null * }) => Promise | ClientErrorPayloadReporterPayload | void} ClientErrorPayloadReporterType */ /** * @typedef {Record & {configuration?: import("./configuration.js").default, currentDevice?: unknown, currentUser?: unknown, modelRegistry?: Record | {model: (name: string) => unknown}, now?: Date | (() => Date), offlineGrant?: unknown, params?: VelociousParams, request?: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default, resourceRuntime?: "backend" | "frontend" | "offline"}} VelociousLooseObject */ /** * @typedef {new (args: {attachmentName?: string, configuration: import("./configuration.js").default, modelClass?: typeof import("./database/record/index.js").default, name?: string, options?: Record>}) => object} AttachmentDriverConstructor */ /** * @typedef {object} ScheduledBackgroundJobsConfiguration * @property {Record} jobs - Scheduled jobs keyed by name. */ /** * @typedef {(args: {configuration: import("./configuration.js").default}) => ScheduledBackgroundJobsConfiguration | Promise} ScheduledBackgroundJobsLoaderType */ /** * @typedef {object} AttachmentDriverConfiguration * @property {(args: {configuration: import("./configuration.js").default, name: string, options: Record>}) => Record>} [create] - Optional factory for a custom attachment driver instance. * @property {AttachmentDriverConstructor} [driverClass] - Optional custom attachment driver class. * @property {Record>} [instance] - Optional custom attachment driver instance. */ /** * Client-safe synchronization policy declared with a model attachment. * @typedef {object} AttachmentSyncConfiguration * @property {"eager" | "on-demand"} fetch - Whether clients prefetch the attachment or wait until it is requested. * @property {"optional" | "required"} offlineRequirement - Whether an offline-ready scope requires the attachment bytes. * @property {"durable" | "evictable"} retention - Whether clients may evict the attachment under storage pressure. */ /** * Model attachment declaration retained by the record class. * @typedef {object} RecordAttachmentConfiguration * @property {string | AttachmentDriverConstructor | Record>} [driver] - Attachment driver name, class, or instance. * @property {AttachmentSyncConfiguration} [sync] - Client-safe synchronized asset policy. * @property {"hasOne" | "hasMany"} type - Attachment cardinality. */ /** * @typedef {object} AttachmentsConfiguration * @property {string} [defaultDriver] - Default attachment storage driver name. * @property {Record>>} [drivers] - Named attachment driver configurations. * @property {boolean} [allowPathInput] - Whether `{path: ...}` attachment input is allowed. * @property {string[]} [allowedPathPrefixes] - Optional allowlist of directories for `{path: ...}` input. */ /** * @typedef {object} MailerBackend * @property {(args: {payload: import("./mailer.js").MailerDeliveryPayload, configuration: import("./configuration.js").default}) => Promise> | ReturnType} deliver - Deliver a mailer payload. * @property {() => import("./mailer.js").MailerDeliveryIdempotencyCapability} [deliveryIdempotencyCapability] - Explicit provider-backed duplicate-suppression capability. Generic SMTP omits this and remains at-least-once. * @property {(args: {payload: import("./mailer.js").MailerDeliveryPayload}) => import("./mailer.js").MailerDeliveryPayload} [prepareDeliveryOperationPayload] - Resolves provider defaults into the immutable payload before required-operation hashing and enqueue. * @property {(args: {deliveryOperation: import("./mailer.js").MailerDeliveryOperationRequest | import("./mailer.js").MailerDeliveryOperation, payload: import("./mailer.js").MailerDeliveryPayload}) => void} [validateDeliveryOperation] - Provider-specific operation and payload validation performed before enqueue and every network attempt. */ /** * @typedef {Record} LocaleFallbacksType */ /** * @typedef {object} FrontendModelRelationshipConfiguration * @property {"belongsTo" | "hasOne" | "hasMany"} type - Relationship type. * @property {string} [model] - Target model class name. * @property {string} [className] - Alias of target model class name. * @property {string} [modelClassName] - Explicit target model class name. */ /** * @typedef {object} FrontendModelAttributeConfiguration * @property {string} [type] - Column type name. * @property {string} [columnType] - Alias for column type name. * @property {string} [sqlType] - Alias for column type name. * @property {string} [dataType] - Alias for column type name. * @property {string} [jsDocType] - Exact generated JSDoc type for non-column attributes. * @property {string} [name] - Attribute name when configured as an array entry. * @property {boolean} [null] - Whether value can be null. * @property {boolean} [selectedByDefault] - Whether included in default serialization. Defaults to true. */ /** * @typedef {object} FrontendModelAttachmentConfiguration * @property {AttachmentSyncConfiguration} [sync] - Client-side synchronized asset policy. * @property {"hasOne" | "hasMany"} type - Attachment cardinality. */ /** * One declarative quick-search column. A plain string is a root-table column; * `{path, column}` searches a column on a joined relationship path. * @typedef {object} FrontendModelQuickSearchColumn * @property {string[]} [path] - Relationship path from the root model to the column's table. * @property {string} column - Database column name to search. */ /** * @typedef {object} FrontendModelResourceConfiguration * @property {Array | Record} attributes - Attributes to expose on the frontend model. * @property {Array} [quickSearchColumns] - Declarative quick-search text columns; an index search on the pseudo-column `quickSearch` expands to an OR of LIKE conditions over these columns. * @property {Array} [quickSearchNumericColumns] - Declarative quick-search numeric columns; an integer quick-search value also matches these columns exactly. * @property {string[]} [abilities] - Additional camelCase ability action names to expose for per-record `record.can(action)` reads. Base CRUD actions (`read`, `create`, `update`, `destroy`) are always included and must not be listed here. * @property {Record} [attachments] - Attachment helpers keyed by attachment name. * @property {string[]} [commands] - Legacy built-in command names (`index`, `find`, `create`, `update`, `destroy`, `attach`, `download`, `url`). * @property {Array} [collectionCommands] - Custom collection commands. Each entry is a camelCase method name, or a `{name, args?, returnType?}` object declaring typed arguments and/or a response type. The runtime derives the kebab-case command slug from the name. * @property {Array} [memberCommands] - Custom member commands. Each entry is a camelCase method name, or a `{name, args?, returnType?}` object declaring typed arguments and/or a response type. The runtime derives the kebab-case command slug from the name. * @property {string[]} [builtInCollectionCommands] - Built-in collection command names (`index`, `create`). * @property {string[]} [builtInMemberCommands] - Built-in member command names (`find`, `update`, `destroy`, `attach`, `download`, `url`). * @property {string} [modelName] - Frontend model name override. * @property {string[]} [relationships] - Relationship names to expose in frontend models. Type and target model are inferred from the backend model's registered relationships. * @property {string | string[]} [primaryKey] - Primary key attribute name or ordered composite primary-key attribute names. * @property {FrontendModelResourceServerConfiguration} [server] - Optional legacy backend behavior overrides for built-in frontend actions. * @property {FrontendModelResourceSyncConfiguration | boolean} [sync] - Optional safe local/offline sync policy metadata. `policy` participates in the hash but is not exposed to generated frontend config/manifest. */ /** * Object form of a custom command entry, declaring its typed arguments and/or * response type alongside the command name. * @typedef {object} FrontendModelResourceCustomCommandObject * @property {string} name - camelCase command method name. * @property {Array<{name: string, type: string}>} [args] - Typed command arguments; each generates a named, typed method parameter mapped positionally into the command payload. `type` is a JSDoc type string. * @property {string} [returnType] - JSDoc type for the command response. When set, the generated method is typed `Promise` instead of `Promise>>`. Emitted verbatim into the generated frontend model, so it must resolve there. */ /** * A custom command entry: a plain camelCase method name, or an object declaring * typed args and/or a response type. * @typedef {string | FrontendModelResourceCustomCommandObject} FrontendModelResourceCustomCommand */ /** * JSON value accepted by sync policy metadata/hash inputs. * @typedef {null | string | number | boolean | unknown[] | Record} FrontendModelSyncJsonValue */ /** * Frontend-model local/offline sync policy config. `metadata` is exposed to * frontends and peers; `policy` is hashed but intentionally omitted from * frontend-safe manifests. * @typedef {object} FrontendModelResourceSyncConfiguration * @property {"optimisticVersion" | "serverWins" | "lastWriterWins" | "fieldThreeWay" | "appendOnly"} [conflictStrategy] - Strategy used when replay detects server/client divergence. Defaults to `optimisticVersion`. * @property {boolean} [enabled] - Whether the resource is sync-enabled. Defaults to true when `sync` is configured. * @property {string[]} [operations] - Sync operation names such as `index`, `find`, `create`, `update`, custom domain commands, etc. * @property {string | number} [policyVersion] - App-controlled policy version used as a stable change signal. * @property {Record} [metadata] - Safe frontend-visible metadata. * @property {Record} [policy] - Deterministic non-secret policy inputs included in the policy hash only. */ /** * Velocious sync API endpoint configuration. * @typedef {object} VelociousSyncApiConfiguration * @property {string} [mountPath] - Mount path for the sync endpoints. Defaults to "/velocious/sync". * @property {FrontendModelResourceClassType} resourceClass - App sync resource class served by the auto-mounted sync endpoints. */ /** * Client-side sync transport owning HTTP POSTs to the framework sync endpoints, * matching the frontend-model websocket client post contract. * @typedef {object} VelociousSyncClientTransport * @property {(path: string, body?: ReturnType, options?: {headers?: Record, signal?: AbortSignal}) => Promise<{json: () => ReturnType}>} post - Posts one request and resolves a response with a json accessor. */ /** * Websocket client contract required from `sync.client.realtime.createClient`, * matching `VelociousWebsocketClient` / snapreq's websocket client. * @typedef {object} VelociousSyncRealtimeWebsocketClient * @property {(options?: {signal?: AbortSignal}) => Promise>} connect - Connects the websocket. * @property {(channelType: string, options?: {params?: Record>, onMessage?: (body: ReturnType) => void, onResume?: () => void, onClose?: (reason: string) => void}) => VelociousSyncRealtimeSubscription} subscribeChannel - Opens one channel subscription. * @property {() => Promise} disconnectAndStopReconnect - Closes the socket and stops auto-reconnect. */ /** * Channel subscription handle returned by `subscribeChannel`. * @typedef {object} VelociousSyncRealtimeSubscription * @property {() => void} close - Closes the subscription. * @property {() => boolean} isReady - Whether the subscription is acknowledged and ready. * @property {(params?: {signal?: AbortSignal, timeoutMs?: number}) => Promise} waitForReady - Resolves once the server acknowledges the subscription. */ /** * One realtime channel subscription descriptor. * @typedef {object} VelociousSyncRealtimeChannelDescriptor * @property {string} channel - Server channel name to subscribe. * @property {Record>} [params] - Subscribe params (runtime scope values). The framework injects `authenticationToken` automatically. * @property {string} [resourceType] - Default resource/model name for pushed changes that do not carry their own resourceType. */ /** * Realtime push configuration for the sync client. Only the genuinely * app-owned callback lives here: how to build the websocket client. * Everything else - deriving the framework sync channel subscriptions from * the declared pull scopes, subscribing, applying pushes through the derived * resource applier, echo suppression, and pull-on-reconnect - is derived. * @typedef {object} VelociousSyncClientRealtimeConfiguration * @property {() => VelociousSyncRealtimeWebsocketClient | Promise} createClient - Builds the (unconnected) websocket client; the framework owns connect/disconnect. * @property {(context: ReturnType) => Array | Promise>} [channels] - Deprecated legacy escape hatch: resolves extra app-channel descriptors from the `subscribeRealtime(context)` context. Declared pull scopes subscribe the framework sync channel automatically. * @property {() => string | Promise} [localOrigin] - Resolves this device's echo origin; pushed messages with a matching `echoOrigin` are dropped. * @property {boolean} [pullOnReconnect] - Deprecated no-op: realtime catch-up now replays the server-side sync cursor on subscribe and resume, so the former pull-on-reconnect no longer fires. Kept so existing app configs still typecheck. */ /** * Client-side sync configuration consumed by `SyncClient.fromConfiguration(...)`. * The framework owns the `${mountPath}/changes` and `${mountPath}/replay` * POSTers over the given transport. * @typedef {object} VelociousSyncClientConfiguration * @property {() => string | Promise} authenticationToken - Resolves the auth token sent with sync requests. * @property {number} [batchSize] - Max syncs per request. * @property {() => boolean | Promise} [isOnline] - Connectivity gate for pulls and replays. Defaults to always online. * @property {string} [mountPath] - Mount path the server serves the sync endpoints under (match the server's `sync.api.mountPath`). Defaults to "/velocious/sync"; normalization strips trailing slashes and always fills in the default. * @property {(error: Error) => void} [onError] - Reports background replay/pull failures. Defaults to rethrowing. * @property {VelociousSyncClientOfflineConfiguration} [offline] - Long-offline session configuration consumed by `startOfflineSession()`: device identity, enrollment, grant scopes, signed-replay path, and the backend public key for peer import. * @property {VelociousSyncClientRealtimeConfiguration} [realtime] - Realtime push configuration consumed by `subscribeRealtime(...)`. * @property {VelociousSyncClientTransport} transport - Transport posting to the framework sync endpoints (e.g. the frontend-model websocket client). * @property {VelociousSyncRealtimeWebsocketClient} [websocketClient] - Shared app-lifetime websocket client (the low-level form) that all sync traffic rides. Provide the same instance the frontend-model transport uses so one connection carries everything. When set, the realtime bridge subscribes channels on it and never owns its lifecycle: unsubscribing closes only channel subscriptions, leaving the socket connected. * @property {string | (() => string | null | undefined)} [websocketUrl] - Shared app-lifetime websocket URL. When set (and no `websocketClient` is given), the framework builds and owns one reconnecting `VelociousWebsocketClient` for all sync traffic, connected on first use. */ /** * App-owned durable storage for the device signing identity (the backend-signed * device certificate plus the device private key). Native apps back this with * secure storage; the framework never embeds a storage technology. * @typedef {object} VelociousSyncClientDeviceIdentityStorage * @property {() => import("./sync/sync-offline-session.js").SyncOfflineDeviceIdentity | null | undefined | Promise} load - Reads the stored identity (null when the device has none yet). * @property {(identity: import("./sync/sync-offline-session.js").SyncOfflineDeviceIdentity) => Promise | void} save - Persists the identity. */ /** * App-owned durable storage for retained offline grants. Pending mutations must * always replay with the grant they were signed under, so a device that * restarts while offline needs its issued grants back. * @typedef {object} VelociousSyncClientGrantStorage * @property {() => Array | Promise>} load - Reads the retained grants. * @property {(grants: Array) => Promise | void} save - Persists the retained grants. */ /** * Client-side long-offline session configuration consumed by * `SyncClient.startOfflineSession()`. The framework owns the session lifecycle * (identity, grant bootstrap/refresh, signing, signed replay, peer bundles) over * the built-in `/frontend-models/sync/bootstrap` and * `/frontend-models/sync/replay` endpoints; the app only owns durable storage, * the enrollment hook, and the grant scopes. * @typedef {object} VelociousSyncClientOfflineConfiguration * @property {VelociousSyncClientDeviceIdentityStorage} deviceIdentityStorage - App-owned durable device-identity storage adapter. * @property {(args: {configuration: import("./configuration.js").default, publicKey: import("./sync/device-identity.js").SyncJsonWebKey}) => import("./sync/device-identity.js").DeviceCertificate | Promise} enrollDevice - App-owned enrollment hook: asks the backend to register the device public key and returns the backend-signed certificate. * @property {(args: {configuration: import("./configuration.js").default}) => Record | Promise>} grantScopes - Resolves the scopes the bootstrap request asks the backend to materialize into the grant. * @property {string} [bootstrapPath] - Signed-bootstrap endpoint path. Defaults to "/frontend-models/sync/bootstrap". * @property {string} [replayPath] - Signed-replay endpoint path. Defaults to "/frontend-models/sync/replay". * @property {import("./sync/device-identity.js").SyncJsonWebKey} [backendPublicKey] - Backend public key used to verify device certificates and imported peer mutations. * @property {VelociousSyncClientGrantStorage} [grantStorage] - Optional durable grant retention adapter. * @property {import("./sync/local-mutation-log.js").default} [mutationLog] - Durable local mutation log the offline session replays and exports. Defaults to the conflict-tracking log declared by the synced models. * @property {() => Date} [now] - Session clock. Defaults to the current time. */ /** * Normalized client-side long-offline session configuration. Same shape as * {@link VelociousSyncClientOfflineConfiguration} with the defaults filled in. * @typedef {VelociousSyncClientOfflineConfiguration & { * bootstrapPath: string, * configuration: import("./configuration.js").default, * now: () => Date, * replayPath: string * }} NormalizedVelociousSyncClientOfflineConfiguration */ /** * Normalized client-side sync configuration. Same shape as * {@link VelociousSyncClientConfiguration} with the defaults filled in. * @typedef {VelociousSyncClientConfiguration & { * mountPath: string, * offline: NormalizedVelociousSyncClientOfflineConfiguration | undefined * }} NormalizedVelociousSyncClientConfiguration */ /** * Normalized sync configuration as stored and returned by * `Configuration.getSyncConfiguration()`. Same shape as * {@link VelociousSyncConfiguration} with the defaults filled in. * @typedef {VelociousSyncConfiguration & { * client: NormalizedVelociousSyncClientConfiguration | undefined * }} NormalizedVelociousSyncConfiguration */ /** * Velocious sync configuration. * @typedef {object} VelociousSyncConfiguration * @property {VelociousSyncApiConfiguration} [api] - Auto-mounts the Velocious sync changes/replay endpoints for this resource class. * @property {VelociousSyncClientConfiguration} [client] - Client-side sync configuration as written by the app. The framework normalizes it into {@link NormalizedVelociousSyncClientConfiguration} (see {@link NormalizedVelociousSyncConfiguration}). * @property {import("./sync/device-identity.js").SyncJsonWebKey | null} [deviceCertificateBackendPublicKey] - Public backend key used to verify offline device certificates for sync replay. * @property {number} [changeFeedRetentionSize] - Number of accepted server changes retained before clients must refresh from snapshot. * @property {Array} offlineGrantSigningKeys - Signing keys used to issue and verify offline grants. Secrets must never be exposed to clients. * @property {number} [offlineGrantTtlMs] - Default offline grant TTL in milliseconds. Defaults to 24 hours. */ /** * Frontend-safe normalized sync metadata. * @typedef {object} NormalizedFrontendModelResourceSyncConfiguration * @property {"optimisticVersion" | "serverWins" | "lastWriterWins" | "fieldThreeWay" | "appendOnly"} conflictStrategy - Normalized replay conflict strategy. * @property {boolean} enabled - Whether the resource is sync-enabled. * @property {string[]} operations - Sorted, duplicate-free sync operation names. * @property {string | null} policyVersion - App-controlled policy version, or null. * @property {string} policyHash - Deterministic sha256 hash of safe policy inputs. * @property {Record} [metadata] - Safe frontend-visible metadata. */ /** * @typedef {Omit & { * abilities: FrontendModelResourceAbilitiesConfiguration * builtInCollectionCommands: Record * builtInMemberCommands: Record * collectionCommands: Record * commandMetadata: Record, returnType: string | null}> * memberCommands: Record * quickSearchColumns: FrontendModelQuickSearchColumn[] | null * quickSearchNumericColumns: FrontendModelQuickSearchColumn[] | null * sync?: NormalizedFrontendModelResourceSyncConfiguration * }} NormalizedFrontendModelResourceConfiguration */ /** * Unbound resource class used by model-agnostic registries. * @typedef {Omit & {modelClass: () => typeof import("./database/record/index.js").default, new (args: never): import("./frontend-model-resource/base-resource.js").default}} UnboundFrontendModelResourceClassType */ /** * Resource class bound to a specific model class. * @template {import("./frontend-model-resource/base-resource.js").FrontendModelResourceModelClass} TModelClass * @template {typeof import("./database/record/index.js").default} TDatabaseModelClass * @typedef {Omit & {ModelClass: TModelClass | undefined, modelClass: () => TModelClass, new (args: import("./frontend-model-resource/base-resource.js").FrontendModelResourceAbilityArgs | import("./frontend-model-resource/base-resource.js").FrontendModelResourceControllerArgs): import("./frontend-model-resource/base-resource.js").default}} BoundFrontendModelResourceClassType */ /** * @template {import("./frontend-model-resource/base-resource.js").FrontendModelResourceModelClass} [TModelClass=never] * @template {typeof import("./database/record/index.js").default} [TDatabaseModelClass=Extract] * @typedef {[TModelClass] extends [never] ? UnboundFrontendModelResourceClassType : BoundFrontendModelResourceClassType} FrontendModelResourceClassType */ /** * @template {import("./frontend-model-resource/base-resource.js").FrontendModelResourceModelClass} [TModelClass=never] * @typedef {FrontendModelResourceClassType} FrontendModelResourceDefinition */ /** * @typedef {object} FrontendModelResourceAbilitiesConfiguration * @property {string} [index] - Ability action for frontend index. * @property {string} [find] - Ability action for frontend find. * @property {string} [create] - Ability action for frontend create. * @property {string} [update] - Ability action for frontend update. * @property {string} [destroy] - Ability action for frontend destroy. */ /** * @typedef {object} FrontendModelResourceServerConfiguration * @property {(args: {action: "index" | "find" | "create" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default}) => (boolean | void | Promise)} [beforeAction] - Optional callback run before built-in frontend actions. * @property {(args: {action: "index", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default}) => Promise} [records] - Records loader for frontendIndex. * @property {(args: {action: "index" | "find" | "create" | "update", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default, model: import("./database/record/index.js").default}) => Record> | Promise>>} [serialize] - Record serializer for response payloads. * @property {(args: {action: "find" | "update" | "destroy" | "attach" | "attachmentList" | "download" | "url", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default, id: string | number}) => Promise} [find] - Record loader for find/update/destroy/attach/download/url actions. * @property {(args: {action: "create", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default, attributes: Record>}) => Promise} [create] - Custom create callback. * @property {(args: {action: "update", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default, model: import("./database/record/index.js").default, attributes: Record>}) => Promise} [update] - Custom update callback. * @property {(args: {action: "destroy", controller: import("./controller.js").default, params: Record>, modelClass: typeof import("./database/record/index.js").default, model: import("./database/record/index.js").default}) => Promise} [destroy] - Custom destroy callback. */ /** * @typedef {object} BackendProjectConfiguration * @property {string} path - Path to the backend project. May be an app root or a contributing package root (package entries are appended internally from `packages`). * @property {string} [frontendModelsOutputPath] - Optional output project path where `src/frontend-models` should be generated. * @property {string} [resourcesPath] - Optional override for the resources directory to auto-discover; defaults to `/src/resources`. Set internally for package entries. * @property {Record} [frontendModels] - Auto-discovered frontend model definitions keyed by model class name. Set internally by the environment handler — do not set manually. * @property {AbilityResourceClassType[]} [abilityResources] - Auto-discovered ability resource classes (frontend-model and authorization) from this project's resources directory. Set internally by the environment handler — do not set manually. */ /** * A descriptor for an external Velocious package (engine) that contributes models, * resources and migrations. A package usually exports `new VelociousPackage({name, url: import.meta.url})`. * @typedef {object} VelociousPackageDescriptor * @property {string} name - The package name. * @property {string} [url] - The descriptor module's `import.meta.url`; the package root is derived from it when `path` is omitted. * @property {string} [path] - The package root directory (the one containing `src`). Derived from `url` when omitted. * @property {string} [modelsPath] - Override for the package's models directory (default `/src/models`). * @property {string} [resourcesPath] - Override for the package's frontend-model resources directory (default `/src/resources`). * @property {string} [migrationsPath] - Override for the package's migrations directory (default `/src/database/migrations`). */ /** * @typedef {import("./packages/velocious-package.js").default | VelociousPackageDescriptor} VelociousPackageConfiguration */ /** * @typedef {object} RouteResolverHookArgs * @property {import("./configuration.js").default} configuration - Configuration instance. * @property {Record>} params - Mutable request params object. * @property {string} currentPath - Request path without query. * @property {boolean} [hasMatchingCustomRoute] - True when matching a configured custom route. * @property {import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default} request - Request object. * @property {import("./http-server/client/response.js").default} response - Response object. * @property {import("./routes/resolver.js").default} resolver - Resolver instance. */ /** * @typedef {object} RouteResolverHookResult * @property {string} action - Dasherized action name (for example `frontend-index`). * @property {string} controller - Controller path (for example `accounts`). * @property {typeof import("./controller.js").default} [controllerClass] - Optional controller class override. * @property {string} [controllerPath] - Optional absolute/relative controller file path override. * @property {Record>} [params] - Extra params to merge for controller/action. * @property {boolean} [skipAbilityResolution] - Whether to run the controller action without resolving request ability. * @property {boolean} [skipControllerConnections] - Whether to run the controller action without the automatic database checkout wrapper. * @property {boolean} [skipTenantResolution] - Whether to run the controller action without resolving request tenant. * @property {string} [viewPath] - Optional view path override used by controller render lookups. */ /** * @typedef {(arg: RouteResolverHookArgs) => RouteResolverHookResult | null | Promise} RouteResolverHookType */ /** * @typedef {typeof import("./authorization/base-resource.js").default} AbilityResourceClassType */ /** * @typedef {(args: {configuration: import("./configuration.js").default, params: Record>, request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined, response: import("./http-server/client/response.js").default | undefined}) => import("./authorization/ability.js").default | void | Promise} AbilityResolverType */ /** * @typedef {(args: {configuration: import("./configuration.js").default, params: Record>, request: import("./http-server/client/request.js").default | import("./http-server/client/websocket-request.js").default | undefined, response: import("./http-server/client/response.js").default | undefined, subscription?: {channel: string, params?: Record>}}) => ReturnType | void | Promise | void>} TenantResolverType */ /** * @typedef {(args: {configuration: import("./configuration.js").default, databaseConfiguration: DatabaseConfigurationType, identifier: string, tenant: ReturnType}) => DatabaseConfigurationType | Partial | void} TenantDatabaseResolverType */ /** * @typedef {object} ApiManifestConfiguration * @property {string} [path] - HTTP path for the built-in API manifest endpoint. Defaults to `/api/manifest`. * @property {string} [token] - Bearer token required in the `Authorization: Bearer ` header. When set, requests without a matching token are not routed (404), so the endpoint stays hidden. */ /** * @typedef {object} McpConfiguration * @property {string} [path] - HTTP path for the built-in MCP endpoint. Defaults to `/mcp`. * @property {string} [token] - Bearer token required in the `Authorization` header. When set, requests without a matching token are not routed (404), so the endpoint stays hidden. */ /** * @typedef {object} DebugEndpointConfiguration * @property {string} [path] - HTTP path for the built-in debug endpoint. Defaults to `/velocious/debug`. * @property {string} [token] - Bearer token required in the `Authorization: Bearer ` header. When set, requests without a matching token are not routed (404), so the endpoint stays hidden. */ /** * @typedef {object} TestTenantPoolConfiguration * @property {Array>} tenants - Pool members: the tenant descriptors whose databases the pool pre-provisions and re-uses. Pool size is the array length. * @property {(args: {configuration: import("./configuration.js").default, databaseIdentifier: string, tenant: ReturnType}) => void | Promise} [provisionTenant] - App-owned provisioning override for one member (runs instead of the framework create + structure-load + ledger-baseline default). * @property {(args: {configuration: import("./configuration.js").default, databaseIdentifier: string, tenant: ReturnType}) => void | Promise} [resetTenant] - App-owned per-test reset override (runs instead of the framework truncate + ledger-baseline default). */ /** * @typedef {Record} TestTenantPoolsConfiguration */ /** * @typedef {object} TenantDatabaseProviderType * @property {(args: {configuration: import("./configuration.js").default, identifier: string}) => Array> | Promise>>} listTenants - Lists tenants that should be created, checked, or migrated for this database identifier. * @property {(args: {configuration: import("./configuration.js").default, identifier: string}) => ReturnType | void | Promise | void>} [resolveGenerationTenant] - Resolves one explicit tenant descriptor for schema/base-model generation without enumerating lifecycle tenants. * @property {(args: {configuration: import("./configuration.js").default, identifier: string}) => Array> | Promise>>} [listRestrictTenants] - Lists existing tenants that should be checked for dependent restrict destroys. Defaults to listTenants. * @property {(args: {configuration: import("./configuration.js").default, databaseConfiguration: DatabaseConfigurationType, identifier: string, tenant: ReturnType}) => void | Promise} [createDatabase] - Creates the tenant database/schema for one tenant. * @property {(args: {configuration: import("./configuration.js").default, databaseConfiguration: DatabaseConfigurationType, identifier: string, tenant: ReturnType}) => void | Promise} [dropDatabase] - Drops the tenant database/schema for one tenant. * @property {(args: {configuration: import("./configuration.js").default, databaseConfiguration: DatabaseConfigurationType, identifier: string, tenant: ReturnType}) => void | Promise} [checkTenant] - Checks one tenant database before generic connection validation. * @property {(args: {configuration: import("./configuration.js").default, databaseConfiguration: DatabaseConfigurationType, identifier: string, migrationsApplied: number, tenant: ReturnType}) => void | Promise} [afterMigrateTenant] - Runs app-owned tenant work after generic migrations for one tenant. `migrationsApplied` is how many migrations actually ran (0 when the tenant was already up to date), so the app can skip expensive per-tenant work on no-op deploys. */ /** * Advisory-lock backend chain configuration (STC-210 design §10, file tier * implemented by STC-213). Everything defaults to today's driver-native-only * behavior; the file backend is disabled by default and only selectable by * explicit configuration. * @typedef {object} AdvisoryLocksConfiguration * @property {{file?: {directory?: string, enabled?: boolean, leaseMs?: number, renewIntervalMs?: number}, lockServer?: {authToken?: string, connectTimeoutMs?: number, enabled?: boolean, host?: string, leaseMs?: number, port?: number, reprobeCooldownMs?: number, url?: string}}} [backends] - Backend enablement. `file.enabled` defaults to false; enabling it is the deployment's explicit single-host declaration. `lockServer` defaults to enabled when a host/port/url or the `VELOCIOUS_LOCK_SERVER_HOST`/`_PORT` env pair is configured. * @property {import("./database/advisory-lock-backend-policy.js").AdvisoryLockBackendPolicyEntry[]} [policy] - Per-lock-name minimum/allowed/preferred tier rules (design §5). */ /** * @typedef {object} ConfigurationArgsType * @property {boolean} [autoload] - Globally enable auto-batch-preload of relationships on lazy access. Default true. * @property {CorsType} [cors] - CORS configuration for the HTTP server. * @property {string} [cookieSecret] - Secret for encrypting cookies. * @property {AbilityResourceClassType[]} [abilityResources] - Resource classes used to define abilities per model. * @property {AbilityResolverType} [abilityResolver] - Resolver for creating request-scoped ability instances. * @property {AdvisoryLocksConfiguration} [advisoryLocks] - Advisory-lock backend chain configuration (backends + per-lock-name tier policy). Defaults to today's driver-native-only behavior. * @property {AttachmentsConfiguration} [attachments] - Attachment storage configuration. * @property {BackendProjectConfiguration[]} [backendProjects] - Backend project definitions used for frontend model generation. * @property {VelociousPackageConfiguration[]} [packages] - External Velocious packages that contribute models, frontend-model resources and migrations. * @property {false | {[key: string]: {[key: string]: DatabaseConfigurationType}}} [database] - Database configurations keyed by environment and identifier, or false for an explicitly database-free application. * @property {boolean} [debug] - Enable debug logging. * @property {boolean | DebugEndpointConfiguration} [debugEndpoint] - Enable the built-in debug endpoint. Defaults to false. * @property {boolean | ApiManifestConfiguration} [apiManifest] - Enable the built-in API manifest endpoint. Defaults to false. * @property {boolean | McpConfiguration} [mcp] - Enable the built-in MCP endpoint on the HTTP server (JSON-RPC over HTTP in addition to the `velocious mcp` stdio server). Defaults to false. * @property {string} [directory] - Base directory for the project. * @property {boolean} [enforceTenantDatabaseScopes] - Require tenant-switched model queries to resolve a tenant database identifier. Defaults to true. * @property {string} [environment] - Current environment name. * @property {import("./environment-handlers/base.js").default} environmentHandler - Environment handler instance. * @property {boolean} [exposeInternalErrorsToClients] - Return unexpected internal error messages and stack traces in frontend-model client payloads in every environment. Defaults to true. * @property {{maxOpenHandles?: number}} [frontendTenantSqlite] - Bounded frontend tenant SQLite lifecycle configuration. * @property {boolean} [secureFrontendModelErrors] - Deprecated compatibility alias for `exposeInternalErrorsToClients: false` when the authoritative option is omitted. * @property {HttpServerConfiguration} [httpServer] - Default HTTP server configuration for applications started from this configuration. * @property {LoggingConfiguration} [logging] - Logging configuration. * @property {BackgroundJobsConfiguration} [backgroundJobs] - Background jobs configuration. * @property {BeaconConfiguration} [beacon] - Beacon broadcast bus configuration. * @property {ScheduledBackgroundJobsConfiguration | ScheduledBackgroundJobsLoaderType} [scheduledBackgroundJobs] - Scheduled background jobs configuration. * @property {MailerBackend} [mailerBackend] - Mail delivery backend. * @property {(args: {configuration: import("./configuration.js").default, processContext: ApplicationProcessContext | undefined, type: string}) => void} initializeModels - Hook to register models for a given initialization type. * @property {InitializersType} [initializers] - Initializer loader for environment bootstrapping. * @property {string | (() => string)} locale - Default locale or locale resolver. * @property {string[]} locales - Supported locales. * @property {LocaleFallbacksType} localeFallbacks - Locale fallback map. * @property {StructureSqlConfiguration} [structureSql] - Structure SQL generation configuration. * @property {VelociousSyncConfiguration} [sync] - Local/offline sync framework configuration. * @property {TenantResolverType} [tenantResolver] - Resolver for creating request-scoped tenant context objects. * @property {TenantDatabaseResolverType} [tenantDatabaseResolver] - Resolver for deriving tenant-specific database config overrides. * @property {Record} [tenantDatabaseProviders] - Tenant database lifecycle providers keyed by database identifier. * @property {TestTenantPoolsConfiguration} [testTenantPools] - Opt-in reusable test tenant-database pools keyed by tenant database identifier. Consumed only by the test harness; ordinary runtime ignores it. * @property {string} [testing] - Path to the testing configuration file. * @property {string | (() => string | undefined)} [timeZone] - Default timezone for timezone-less datetime strings. * @property {number | (() => number)} [timezoneOffsetMinutes] - Default timezone offset in minutes. * @property {string | string[]} [trustedProxies] - Trusted reverse proxy address ranges used to resolve request remote addresses from forwarding headers. * @property {number | (() => number)} [requestTimeoutMs] - Timeout in seconds for completing a HTTP request. * @property {RouteResolverHookType[]} [routeResolverHooks] - Hook callbacks that can hijack unresolved routes. * @property {WebsocketChannelResolverType} [websocketChannelResolver] - Resolve a websocket channel class/instance for each connection. * @property {WebsocketMessageHandlerResolverType} [websocketMessageHandlerResolver] - Resolve a raw websocket message handler for each connection. */ export declare const nothing: {}; //# sourceMappingURL=configuration-types.d.ts.map