@rebasepro/server 0.13.0 → 0.13.1-canary.g599dae0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es.js.map +1 -1
- package/dist/utils/logging.d.ts +0 -4
- package/package.json +5 -5
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","names":["core._coercedNumber","schemas.ZodNumber","RebaseClientError$1","RebaseApiError$1"],"sources":["../../types/src/errors.ts","../../types/src/types/storage_source.ts","../../common/src/data/sort-dialect.ts","../src/collections/BackendCollectionRegistry.ts","../src/collections/validate-config.ts","../src/collections/loader.ts","../src/services/driver-registry.ts","../src/services/routed-realtime-service.ts","../src/api/rest/query-parser.ts","../src/api/rest/write-validation.ts","../src/api/rest/idempotency.ts","../src/api/rest/api-generator.ts","../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/compat.js","../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/coerce.js","../src/utils/logging.ts","../src/utils/compression.ts","../src/utils/request-id.ts","../src/utils/request-logger.ts","../src/init/middlewares.ts","../src/storage/LocalStorageController.ts","../src/storage/image-transform.ts","../src/storage/tus-handler.ts","../src/storage/routes.ts","../src/storage/storage-registry.ts","../src/storage/index.ts","../src/init/storage.ts","../src/init/docs.ts","../src/init/health.ts","../src/init/shutdown.ts","../src/auth/collection-callback-warning.ts","../../client/dist/index.es.js","../src/history/history-routes.ts","../src/email/smtp-email-service.ts","../src/singleton.ts","../src/auth/require-auth.ts","../src/init.ts","../src/functions/define-function.ts","../src/cron/define-cron.ts","../src/utils/sql.ts","../src/env.ts","../src/services/webhook-service.ts","../src/utils/dev-port.ts","../src/serve-spa.ts","../src/boot/bundle.ts","../src/boot/env.ts","../src/boot/sources.ts","../src/boot/version-skew.ts","../src/boot/driver.ts","../src/boot/options.ts","../src/metrics/index.ts","../src/boot/fetch-bundle.ts","../src/boot/boot.ts"],"sourcesContent":["/**\n * Structured initializer for {@link RebaseApiError}.\n *\n * @group Errors\n */\nexport interface RebaseErrorInit {\n /**\n * HTTP status code, when the error originated from an HTTP response.\n * Left `undefined` for realtime/WebSocket, network, and client-side\n * logic errors that have no HTTP status.\n */\n status?: number;\n /** Stable, machine-readable error code (e.g. `\"NOT_FOUND\"`, `\"BAD_REQUEST\"`). */\n code?: string;\n /** Structured error payload returned by the server, when present. */\n details?: unknown;\n /** The underlying error this one wraps, if any. */\n cause?: unknown;\n}\n\n/**\n * The single error type thrown across the entire Rebase client surface —\n * HTTP data/control-plane calls, realtime/WebSocket operations, and\n * client-side logic errors (e.g. an unknown collection accessor). A `catch`\n * block only ever needs to check for this one class:\n *\n * ```ts\n * import { RebaseApiError } from \"@rebasepro/client\"; // re-exported\n *\n * try {\n * await client.data.products.update(id, { price: 9 });\n * } catch (e) {\n * if (e instanceof RebaseApiError) {\n * if (e.status === 404) { ... } // HTTP failures carry a status\n * console.error(e.code, e.details);\n * }\n * }\n * ```\n *\n * `status` is present for HTTP failures and `undefined` otherwise, so its\n * presence distinguishes transport-level errors from realtime/logic errors.\n *\n * @group Errors\n */\nexport class RebaseApiError extends Error {\n /** HTTP status code, or `undefined` for non-HTTP errors. */\n readonly status?: number;\n /** Stable machine-readable error code, when the server supplied one. */\n readonly code?: string;\n /** Structured error payload from the server, when present. */\n readonly details?: unknown;\n\n constructor(message: string, init: RebaseErrorInit = {}) {\n super(message);\n this.name = \"RebaseApiError\";\n this.status = init.status;\n this.code = init.code;\n this.details = init.details;\n if (init.cause !== undefined) {\n // `cause` is standard on Error but not always in the lib target's type.\n (this as { cause?: unknown }).cause = init.cause;\n }\n }\n}\n\n/**\n * Client-side logic error — raised before any request is made (e.g. accessing\n * an unknown collection accessor when a typed dictionary is configured).\n *\n * A subclass of {@link RebaseApiError} (with no `status`), so a single\n * `catch (e) { if (e instanceof RebaseApiError) ... }` handles it too.\n *\n * @group Errors\n */\nexport class RebaseClientError extends RebaseApiError {\n constructor(message: string) {\n super(message);\n this.name = \"RebaseClientError\";\n }\n}\n","/**\n * Describes a named storage backend — a place files live.\n *\n * Declared once and shared front + back: the frontend uses it to decide\n * transport (HTTP proxy vs direct SDK), the backend uses the same `key`\n * to resolve a StorageController, and collection properties reference\n * a definition by its `key` via `StorageConfig.storageSource`.\n *\n * This mirrors the {@link DataSourceDefinition} pattern used for databases.\n *\n * @group Models\n */\n\n/**\n * The default storage source key, used when a property does not specify\n * a `storageSource`. Shared by the frontend and backend registries so\n * both agree on \"the default storage backend\".\n * @group Models\n */\nexport const DEFAULT_STORAGE_SOURCE_KEY = \"(default)\";\n\n/**\n * How the *frontend* reaches a storage backend.\n *\n * - `\"server\"` — through the Rebase backend REST API (`/api/storage`).\n * The backend holds the actual `StorageController` and routes by\n * storage-source key. This is the default and covers Local, S3, GCS,\n * and any other server-mediated engine.\n * - `\"direct\"` — straight from the client to the external backend via\n * its own SDK (e.g. Firebase Storage via `@firebase/storage`).\n * The Rebase backend is **not** in the upload/download path.\n *\n * @group Models\n */\nexport type StorageSourceTransport = \"server\" | \"direct\";\n\n/**\n * Declarative definition of a storage source — a named place files live.\n *\n * Declared once and shared front and back: the frontend uses it to decide\n * transport (client HTTP proxy vs direct provider SDK), the backend uses\n * the same `key` to resolve a `StorageController`, and collection\n * properties reference a definition by its `key` via\n * `StorageConfig.storageSource`.\n *\n * @group Models\n */\nexport interface StorageSourceDefinition {\n /**\n * Unique identifier for this storage source. Collection properties\n * point at it via `StorageConfig.storageSource`.\n * Defaults to {@link DEFAULT_STORAGE_SOURCE_KEY}.\n */\n key: string;\n\n /**\n * The engine backing this storage source (e.g. `\"local\"`, `\"s3\"`,\n * `\"gcs\"`, `\"firebase\"`, `\"azure\"`, or a custom id).\n */\n engine: string;\n\n /**\n * How the frontend reaches this storage. Defaults to `\"server\"`.\n *\n * When `\"direct\"`, the client uses a provider-specific SDK\n * (e.g. `@firebase/storage`) and the backend does not proxy\n * upload/download traffic for this source.\n */\n transport: StorageSourceTransport;\n\n /** Human-readable label for the UI (e.g. \"Firebase Storage\", \"S3 Media\"). */\n label?: string;\n}\n\n/**\n * A resolved storage source: the single source of truth that the frontend\n * router and backend registry both derive from.\n *\n * @group Models\n */\nexport interface ResolvedStorageSource {\n /** Storage source key (routing key, shared front + back). */\n key: string;\n /** Engine backing the source. */\n engine: string;\n /** Frontend transport. */\n transport: StorageSourceTransport;\n /** Human-readable label. */\n label?: string;\n}\n\n/**\n * The environment-variable suffix for a storage or data source key.\n *\n * `\"\"` for the default source — so a single-bucket project keeps configuring\n * plain `S3_BUCKET` — and `__<KEY>` for every named one, uppercased with\n * non-alphanumerics collapsed to underscores: `media-cdn` → `S3_BUCKET__MEDIA_CDN`.\n *\n * The rule derives the variable name from the declared key rather than\n * discovering keys by scanning the environment. Scanning would have to guess how\n * `S3_BUCKET__MEDIA_CDN` splits into a key; deriving cannot be ambiguous, and a\n * typo surfaces as a missing source at boot instead of a silently ignored\n * variable.\n *\n * It lives in this package, with no dependencies, because four things must agree\n * on it exactly: the CLI (validating a build), the runtime (reading its own\n * environment), the control plane (writing a tenant's Secret), and the docs. A\n * second implementation of a naming convention is a second chance to disagree.\n *\n * @group Models\n */\nexport function storageEnvSuffix(key: string, defaultKey: string = DEFAULT_STORAGE_SOURCE_KEY): string {\n if (!key || key === defaultKey) return \"\";\n const normalized = key\n .replace(/[^A-Za-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toUpperCase();\n if (!normalized) {\n throw new Error(\n `Source key \"${key}\" cannot be turned into an environment variable name. ` +\n \"Use a key containing at least one letter or digit.\"\n );\n }\n return `__${normalized}`;\n}\n\n/**\n * Two distinct keys that collapse onto the same variable name, or `null`.\n *\n * `media-cdn` and `media_cdn` are different source keys but the same suffix, so\n * without this one of them silently reads the other's configuration. Returns the\n * offending pair rather than throwing, so each caller can raise it in its own\n * idiom — a `BundleError` at boot, a build failure in the CLI, a rejected deploy\n * in a control plane.\n *\n * @group Models\n */\nexport function findStorageSuffixCollision(\n keys: string[],\n defaultKey: string = DEFAULT_STORAGE_SOURCE_KEY\n): { a: string; b: string; suffix: string } | null {\n const seen = new Map<string, string>();\n for (const key of keys) {\n const suffix = storageEnvSuffix(key, defaultKey);\n const existing = seen.get(suffix);\n if (existing !== undefined && existing !== key) {\n return { a: existing, b: key, suffix };\n }\n seen.set(suffix, key);\n }\n return null;\n}\n\n/** The `storage` block of `rebase.json`, structurally. */\nexport type DeclaredStorageSources = Record<string, {\n engine: string;\n transport?: StorageSourceTransport;\n label?: string;\n}>;\n\n/**\n * Merge the two places a project may declare storage sources into one list.\n *\n * `rebase.json` is authoritative for every field it states. Config code may add\n * sources it does not mention and fill in fields it left out, but may not\n * contradict it: the manifest is what a host reads to decide which buckets need\n * configuring, and a runtime that quietly disagreed with it would put the\n * console back to describing a topology the tenant does not have — the exact\n * failure this whole mechanism exists to end.\n *\n * Note what is *not* here: no default source is invented when both inputs are\n * empty. That decision belongs to the resolver, which knows whether declaring\n * nothing means \"one plain bucket\" (it does) or \"no storage at all\".\n *\n * @group Models\n */\nexport function normalizeStorageSources(\n declared: DeclaredStorageSources | StorageSourceDefinition[] | undefined,\n exported: StorageSourceDefinition[] | undefined\n): StorageSourceDefinition[] {\n const merged = new Map<string, StorageSourceDefinition>();\n\n // Two shapes, one meaning. `rebase.json` states sources as a record keyed by\n // source key, which is how JSON expresses a set of named things; the bundle\n // manifest stores the already-resolved array. Accepting both is what lets the\n // CLI and the runtime call this with what each of them happens to hold.\n const declaredEntries: [string, { engine: string; transport?: StorageSourceTransport; label?: string }][] =\n Array.isArray(declared)\n ? declared.filter(d => d?.key).map(d => [d.key, d])\n : Object.entries(declared ?? {});\n\n for (const [key, config] of declaredEntries) {\n merged.set(key, {\n key,\n engine: config.engine,\n transport: config.transport ?? \"server\",\n ...(config.label !== undefined ? { label: config.label } : {})\n });\n }\n\n for (const definition of exported ?? []) {\n if (!definition?.key) continue;\n const existing = merged.get(definition.key);\n if (!existing) {\n merged.set(definition.key, {\n key: definition.key,\n engine: definition.engine,\n transport: definition.transport ?? \"server\",\n ...(definition.label !== undefined ? { label: definition.label } : {})\n });\n continue;\n }\n // Fill gaps only. `rebase.json` stated these; code does not overrule it.\n if (existing.label === undefined && definition.label !== undefined) {\n existing.label = definition.label;\n }\n }\n\n return Array.from(merged.values());\n}\n","import type { OrderByTuple } from \"@rebasepro/types\";\n\n/**\n * Sort-order wire codec.\n *\n * This is the ONLY module that knows about the colon-delimited wire format\n * (`\"field:direction\"`) used in HTTP query parameters.\n * Everything else speaks {@link OrderByTuple} exclusively.\n *\n * Mirrors the filter architecture in `filter-dialect.ts`.\n *\n * @module\n */\n\n/**\n * Serialize an {@link OrderByTuple} to the wire format `\"field:direction\"`.\n *\n * **Runtime tolerance:** if the input is already a well-formed wire string\n * (from an untyped JS caller), it is returned unchanged.\n * This is undocumented tolerance, not public API — don't rely on it.\n *\n * @param orderBy - A canonical `[field, direction]` tuple, or at runtime\n * possibly a pre-serialized string (undocumented tolerance).\n * @returns The wire-format string, or `undefined` if the input is falsy.\n *\n * @remarks\n * Field names containing `:` are representable in the tuple form but\n * **not** on the wire — this is an inherent limitation of the colon-delimited\n * encoding and is not resolved here.\n */\nexport function serializeOrderBy(orderBy?: OrderByTuple | string): string | undefined {\n if (!orderBy) return undefined;\n // Runtime tolerance: pass through a pre-serialized wire string unchanged.\n if (typeof orderBy === \"string\") return orderBy;\n return `${orderBy[0]}:${orderBy[1]}`;\n}\n\n/**\n * Deserialize a wire-format `\"field:direction\"` string into an {@link OrderByTuple}.\n *\n * Lenient parsing (matches existing server behaviour):\n * - Bare field name (no colon): `\"name\"` → `[\"name\", \"asc\"]`\n * - Unknown direction: `\"name:foo\"` → `[\"name\", \"asc\"]`\n * - Empty / falsy input: → `undefined`\n *\n * @param raw - The wire-format string from an HTTP query parameter.\n * @returns The canonical tuple, or `undefined` if the input is empty/falsy.\n */\nexport function deserializeOrderBy(raw?: string): OrderByTuple | undefined {\n if (!raw) return undefined;\n const idx = raw.indexOf(\":\");\n if (idx === -1) return [raw, \"asc\"];\n const field = raw.slice(0, idx);\n const dir = raw.slice(idx + 1);\n return [field, dir === \"desc\" ? \"desc\" : \"asc\"];\n}\n","import { CollectionRegistry } from \"@rebasepro/common\";\nimport { CollectionRegistryInterface } from \"../db/interfaces\";\nimport { CollectionConfig } from \"@rebasepro/types\";\n\n/**\n * Backend-agnostic collection registry.\n * Satisfies CollectionRegistryInterface through inheritance from CollectionRegistry.\n */\nexport class BackendCollectionRegistry extends CollectionRegistry implements CollectionRegistryInterface {\n\n /**\n * Get the available relation keys for a given collection path.\n * Maps from the collection's relation property names to the relation names.\n */\n getRelationKeysForCollection(collectionPath: string): string[] {\n const collection = this.getCollectionByPath(collectionPath) as (CollectionConfig & { relations?: { relationName?: string }[] }) | undefined;\n if (!collection?.relations) return [];\n return collection.relations.map(r => r.relationName ?? \"\").filter(Boolean);\n }\n}\n","import { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS } from \"@rebasepro/types\";\n\nimport { logger } from \"../utils/logger\";\n\n/**\n * A strict parse of every collection config, run at boot.\n *\n * Nothing used to check these files. A config written against an older version\n * loaded clean, and whichever keys had moved since were simply ignored — no\n * warning, no log line, no failed boot. The collection still served rows, so\n * the only signal was the feature quietly not being there: an icon that never\n * appeared, a relation that answered `[]`, a `readOnly` field the panel let you\n * edit. The renames are not the problem; a rename with no runtime signal is.\n *\n * Two severities, because two different things are being detected:\n *\n * - A **known-removed or known-renamed key** is high-confidence and actionable —\n * we know what it used to mean and what replaced it. That is an error, and\n * refusing to boot is the point. A minute of downtime beats a week of \"where\n * did my icons go\".\n * - An **unrecognised key** is not. Configs legitimately carry extra metadata,\n * and a key we do not know may simply be newer than this list. That warns,\n * loudly, and escalates to an error only when asked\n * (`REBASE_STRICT_COLLECTION_CONFIG=error`, or an explicit option).\n *\n * Everything is reported in one pass. Someone migrating a project wants the\n * whole list once, not fifty-five sequential boots.\n *\n * This is not `validateCollectionJson` in `@rebasepro/admin`. That one parses a\n * JSON string pasted into the panel's import dialog and checks value *shapes*\n * against the flat `AdminCollection` view model. This one checks key *identity*\n * against the authoring contract, on live objects, in a package that may not\n * import the admin. The two answer different questions about different types,\n * and merging them would mean the server depending on the admin panel.\n */\n\n/** How an unrecognised key is treated. */\nexport type UnknownKeyPolicy = \"warn\" | \"error\" | \"off\";\n\nexport interface ConfigProblem {\n severity: \"error\" | \"warning\";\n /** Dotted path into the config, e.g. `posts.properties.author`. */\n path: string;\n message: string;\n}\n\nexport interface ValidateCollectionConfigOptions {\n /**\n * What to do with a key that is in no known list. Defaults to the\n * `REBASE_STRICT_COLLECTION_CONFIG` environment variable, and to `\"warn\"`\n * when that is unset.\n */\n unknownKeys?: UnknownKeyPolicy;\n}\n\n/**\n * Read the unknown-key policy from the environment.\n *\n * `REBASE_STRICT_COLLECTION_CONFIG` accepts `error`/`strict`/`1`/`true` to\n * escalate, `off`/`0`/`false` to silence, and anything else warns.\n */\nexport function unknownKeyPolicyFromEnv(\n env: Record<string, string | undefined> = process.env\n): UnknownKeyPolicy {\n const raw = env.REBASE_STRICT_COLLECTION_CONFIG?.trim().toLowerCase();\n if (!raw) return \"warn\";\n if ([\"error\", \"strict\", \"1\", \"true\", \"yes\"].includes(raw)) return \"error\";\n if ([\"off\", \"0\", \"false\", \"no\", \"none\"].includes(raw)) return \"off\";\n return \"warn\";\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// The contract, as data.\n//\n// Every list below is derived from `packages/types/src/types/*` at the version\n// this file ships with. `ADMIN_COLLECTION_KEYS` and `ADMIN_PROPERTY_KEYS` are\n// imported rather than copied — core owns them and `@rebasepro/admin-types`\n// type-checks them against the option types, so those two cannot drift.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** `BaseCollectionConfig`, plus every engine-specific field, plus the `admin` block. */\nconst COLLECTION_KEYS = new Set<string>([\n // BaseCollectionConfig\n \"slug\",\n \"name\",\n \"singularName\",\n \"description\",\n \"childCollections\",\n \"dataSource\",\n \"engine\",\n \"databaseId\",\n \"properties\",\n \"auth\",\n \"disableDefaultPolicies\",\n \"callbacks\",\n \"ownerId\",\n \"metadata\",\n \"history\",\n \"strictWrites\",\n \"table\",\n \"relations\",\n \"securityRules\",\n // PostgresCollectionConfig\n \"schema\",\n // FirebaseCollectionConfig / MongoDBCollectionConfig\n \"path\",\n \"subcollections\",\n // Added back by @rebasepro/admin-types through declaration merging. Its\n // contents belong to the admin panel and are deliberately not checked here.\n \"admin\"\n]);\n\n/** `BaseProperty` — legal on a property of any type. */\nconst BASE_PROPERTY_KEYS = [\n \"type\",\n \"name\",\n \"description\",\n \"propertyConfig\",\n \"columnName\",\n \"defaultValue\",\n \"validation\",\n \"excludeFromApi\",\n \"dynamicProps\",\n \"conditions\",\n \"callbacks\",\n \"metadata\",\n // as above: added by @rebasepro/admin-types, contents not checked here.\n \"admin\"\n];\n\n/** The keys each property `type` adds on top of {@link BASE_PROPERTY_KEYS}. */\nconst PROPERTY_KEYS_BY_TYPE: Record<string, string[]> = {\n string: [\"columnType\", \"isId\", \"enum\", \"storage\", \"userSelect\", \"email\", \"url\"],\n number: [\"columnType\", \"isId\", \"enum\"],\n boolean: [],\n date: [\"columnType\", \"mode\", \"timezone\", \"autoValue\"],\n geopoint: [],\n binary: [],\n vector: [\"dimensions\"],\n reference: [\"isId\", \"path\", \"fixedFilter\", \"includeId\", \"includeEntityLink\"],\n relation: [\"isId\", \"relation\", \"resolvedRelation\", \"fixedFilter\", \"includeId\", \"includeEntityLink\", \"widget\"],\n array: [\"columnType\", \"of\", \"oneOf\", \"sortable\", \"canAddElements\"],\n map: [\"columnType\", \"properties\", \"propertiesOrder\", \"previewProperties\", \"keyValue\"]\n};\n\nconst PROPERTY_TYPES = Object.keys(PROPERTY_KEYS_BY_TYPE);\n\n/** `RelationBase` plus the fields of every `kind` in the tagged union. */\nconst RELATION_KEYS = new Set<string>([\n \"kind\",\n \"relationName\",\n \"target\",\n \"onUpdate\",\n \"onDelete\",\n \"overrides\",\n \"validation\",\n \"localKey\",\n \"foreignKeyOnTarget\",\n \"sourceKey\",\n \"through\",\n \"joinPath\",\n \"cardinality\"\n]);\n\nconst RELATION_KINDS = [\"belongsTo\", \"hasOne\", \"hasMany\", \"manyToMany\", \"via\"];\n\n/** Which link field each `kind` admits. Anything else is a leftover shape. */\nconst RELATION_FIELDS_BY_KIND: Record<string, string[]> = {\n belongsTo: [\"localKey\"],\n hasOne: [\"foreignKeyOnTarget\", \"sourceKey\"],\n hasMany: [\"foreignKeyOnTarget\", \"sourceKey\"],\n manyToMany: [\"through\"],\n via: [\"joinPath\", \"cardinality\"]\n};\n\nconst RELATION_LINK_FIELDS = [\"localKey\", \"foreignKeyOnTarget\", \"sourceKey\", \"through\", \"joinPath\", \"cardinality\"];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// What used to be legal, and is not.\n//\n// Sourced from the commits that made each change, not from recollection:\n// • 0.11 `def1195d1` + `e9eae2cf7` — the 38 presentation fields nest under\n// `admin`; the list is ADMIN_COLLECTION_KEYS in core.\n// • 0.11 `078798484` — a property's block is `admin`, not `ui`.\n// • 0.11 `7cee8f501` — the property's presentation fields nested in the first\n// place; the list is ADMIN_PROPERTY_KEYS in core.\n// • 0.11 `60c3a8ec7` — `Relation` becomes a tagged union, and every flat\n// relation field on `RelationProperty` moves into a nested `relation`.\n// • 0.10 `33d096cd5` — `editable` removed; everything is editable by default.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface Migration {\n /** What to do about it, in the imperative. */\n fix: string;\n /** The codemod that does it, if one exists. */\n codemod?: string;\n}\n\n/** Collection-level keys that no longer exist at the top level. */\nconst COLLECTION_MIGRATIONS: Record<string, Migration> = {\n editable: {\n fix: \"`editable` was removed in 0.10 — collections are editable by default. Delete it, or use `admin.disableDefaultActions` to take actions away\"\n }\n};\n\nfor (const key of ADMIN_COLLECTION_KEYS) {\n COLLECTION_MIGRATIONS[key] = {\n fix: `\\`${key}\\` moved into the collection's \\`admin\\` block in 0.11 — write \\`admin: { ${key}: … }\\``,\n codemod: \"node scripts/codemod/collections-admin-block.mjs\"\n };\n}\n\n/** Property-level keys that no longer exist at the top level of a property. */\nconst PROPERTY_MIGRATIONS: Record<string, Migration> = {\n ui: {\n fix: \"`ui` was renamed to `admin` in 0.11, to match the collection's block — rename the key\"\n },\n editable: {\n fix: \"`editable` was removed in 0.10 — properties are editable by default. Use `admin.readOnly` or `admin.disabled` instead\"\n }\n};\n\nfor (const key of ADMIN_PROPERTY_KEYS) {\n PROPERTY_MIGRATIONS[key] = {\n fix: `\\`${key}\\` belongs in the property's \\`admin\\` block — write \\`admin: { ${key}: … }\\``\n };\n}\n\n/**\n * The flat relation fields that `RelationProperty` used to carry.\n *\n * All of them moved into the nested `relation` object. Two of them do not\n * survive the move at all: `direction` and `inverseRelationName` were how the\n * old shape said which side owned the link, and the `kind` discriminant says it\n * now.\n */\nconst RELATION_PROPERTY_MIGRATIONS: Record<string, Migration> = {\n target: { fix: \"move `target` inside `relation` — `relation: { kind: …, target: … }`\" },\n cardinality: { fix: \"`cardinality` is implied by the relation's `kind` (`belongsTo`/`hasOne` are one, `hasMany`/`manyToMany` are many); it survives only on `relation: { kind: \\\"via\\\" }`\" },\n direction: { fix: \"`direction` was removed — the `kind` says which side owns the link. `owning` + one is `belongsTo`, `inverse` + one is `hasOne`, `inverse` + many is `hasMany`, `owning` + many is `manyToMany`\" },\n inverseRelationName: { fix: \"`inverseRelationName` was removed — name the far side with `relation: { kind: \\\"hasMany\\\", foreignKeyOnTarget: … }` instead of pointing at it\" },\n localKey: { fix: \"move `localKey` inside `relation` — `relation: { kind: \\\"belongsTo\\\", localKey: … }`\" },\n foreignKeyOnTarget: { fix: \"move `foreignKeyOnTarget` inside `relation` — `relation: { kind: \\\"hasOne\\\" | \\\"hasMany\\\", foreignKeyOnTarget: … }`\" },\n through: { fix: \"move `through` inside `relation` — `relation: { kind: \\\"manyToMany\\\", through: … }`\" },\n joinPath: { fix: \"move `joinPath` inside `relation` — `relation: { kind: \\\"via\\\", joinPath: … }`\" },\n onUpdate: { fix: \"move `onUpdate` inside `relation`\" },\n onDelete: { fix: \"move `onDelete` inside `relation`\" },\n overrides: { fix: \"move `overrides` inside `relation`\" },\n relationName: { fix: \"move `relationName` inside `relation` — `relation: { kind: …, relationName: … }`\" }\n};\n\nconst RELATION_UNION_CODEMOD = \"node scripts/codemod/relations-tagged-union.mjs\";\n\n/** Fields the old flat `Relation` carried that the tagged union does not. */\nconst RELATION_MIGRATIONS: Record<string, Migration> = {\n direction: { fix: RELATION_PROPERTY_MIGRATIONS.direction.fix, codemod: RELATION_UNION_CODEMOD },\n inverseRelationName: { fix: RELATION_PROPERTY_MIGRATIONS.inverseRelationName.fix, codemod: RELATION_UNION_CODEMOD }\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nclass ProblemCollector {\n readonly problems: ConfigProblem[] = [];\n\n constructor(private readonly unknownKeys: UnknownKeyPolicy) {\n }\n\n error(path: string, message: string): void {\n this.problems.push({ severity: \"error\", path, message });\n }\n\n /** A key we know moved or died. Always fatal — we know exactly what to do. */\n migrated(path: string, key: string, migration: Migration): void {\n this.error(\n path,\n `\\`${key}\\` is no longer read here. ${migration.fix}.` +\n (migration.codemod ? ` Run \\`${migration.codemod}\\` to migrate the whole project.` : \"\")\n );\n }\n\n /** A key nobody recognises. Might be metadata, might be newer than us. */\n unknown(path: string, key: string, context: string): void {\n if (this.unknownKeys === \"off\") return;\n this.problems.push({\n severity: this.unknownKeys === \"error\" ? \"error\" : \"warning\",\n path,\n message:\n `\\`${key}\\` is not a known ${context} key and is being ignored. ` +\n \"If it is deliberate metadata this is safe; if it is a typo or a key from an older \" +\n \"version, the feature it configures is silently absent.\"\n });\n }\n}\n\nfunction checkRelation(\n relation: unknown,\n path: string,\n collect: ProblemCollector\n): void {\n if (!isPlainObject(relation)) return;\n\n const kind = relation.kind;\n if (typeof kind !== \"string\") {\n collect.error(\n path,\n \"a relation has no `kind`. Relations became a tagged union in 0.11 — pick one of \" +\n `${RELATION_KINDS.join(\", \")}. Run \\`${RELATION_UNION_CODEMOD}\\` to migrate the whole project.`\n );\n } else if (!RELATION_KINDS.includes(kind)) {\n collect.error(path, `\\`kind: \"${kind}\"\\` is not a relation kind. Expected one of ${RELATION_KINDS.join(\", \")}.`);\n }\n\n for (const key of Object.keys(relation)) {\n const migration = RELATION_MIGRATIONS[key];\n if (migration) {\n collect.migrated(`${path}.${key}`, key, migration);\n continue;\n }\n if (!RELATION_KEYS.has(key)) {\n collect.unknown(`${path}.${key}`, key, \"relation\");\n }\n }\n\n // Each kind admits exactly one link field. A leftover from another shape\n // typechecks against nothing and is honoured by whichever consumer reads it\n // first — which is how a `many` relation carrying a `localKey` corrupted\n // writes before the union closed the door.\n if (typeof kind === \"string\" && RELATION_FIELDS_BY_KIND[kind]) {\n const allowed = RELATION_FIELDS_BY_KIND[kind];\n for (const field of RELATION_LINK_FIELDS) {\n if (relation[field] !== undefined && !allowed.includes(field)) {\n collect.error(\n `${path}.${field}`,\n `\\`${field}\\` is not valid on a \"${kind}\" relation. ` +\n `A \"${kind}\" takes ${allowed.length ? allowed.map(a => `\\`${a}\\``).join(\" and \") : \"no link field\"}.`\n );\n }\n }\n }\n}\n\nfunction checkProperty(\n property: unknown,\n path: string,\n collect: ProblemCollector\n): void {\n // A property may be a builder function in some authoring styles; there is\n // nothing to inspect statically, and guessing would be worse than silence.\n if (typeof property === \"function\") return;\n\n if (!isPlainObject(property)) {\n collect.error(path, \"a property must be an object.\");\n return;\n }\n\n const type = property.type;\n if (typeof type !== \"string\") {\n collect.error(path, \"a property has no `type`.\");\n } else if (!PROPERTY_TYPES.includes(type)) {\n collect.error(path, `\\`type: \"${type}\"\\` is not a property type. Expected one of ${PROPERTY_TYPES.join(\", \")}.`);\n }\n\n const allowed = new Set<string>([\n ...BASE_PROPERTY_KEYS,\n ...(typeof type === \"string\" ? PROPERTY_KEYS_BY_TYPE[type] ?? [] : [])\n ]);\n\n for (const key of Object.keys(property)) {\n if (allowed.has(key)) continue;\n\n // A relation's flat fields are checked first: `localKey` at the top of a\n // property is a 0.10 config, not an unknown key.\n if (type === \"relation\" && RELATION_PROPERTY_MIGRATIONS[key]) {\n collect.migrated(`${path}.${key}`, key, { ...RELATION_PROPERTY_MIGRATIONS[key], codemod: RELATION_UNION_CODEMOD });\n continue;\n }\n\n const migration = PROPERTY_MIGRATIONS[key];\n if (migration) {\n collect.migrated(`${path}.${key}`, key, migration);\n continue;\n }\n\n collect.unknown(`${path}.${key}`, key, `property (\\`${String(type)}\\`)`);\n }\n\n if (type === \"relation\" && property.relation !== undefined) {\n checkRelation(property.relation, `${path}.relation`, collect);\n }\n\n // Recurse into the two composites. `of` may be one property or an array of\n // them; `oneOf.properties` is a record like a map's.\n if (type === \"array\") {\n const of = property.of;\n if (Array.isArray(of)) {\n of.forEach((entry, index) => checkProperty(entry, `${path}.of[${index}]`, collect));\n } else if (of !== undefined) {\n checkProperty(of, `${path}.of`, collect);\n }\n const oneOf = property.oneOf;\n if (isPlainObject(oneOf) && isPlainObject(oneOf.properties)) {\n checkProperties(oneOf.properties, `${path}.oneOf.properties`, collect);\n }\n }\n\n if (type === \"map\" && isPlainObject(property.properties)) {\n checkProperties(property.properties, `${path}.properties`, collect);\n }\n}\n\nfunction checkProperties(\n properties: Record<string, unknown>,\n path: string,\n collect: ProblemCollector\n): void {\n for (const [key, property] of Object.entries(properties)) {\n checkProperty(property, `${path}.${key}`, collect);\n }\n}\n\nfunction checkCollection(\n collection: unknown,\n index: number,\n collect: ProblemCollector\n): void {\n if (!isPlainObject(collection)) {\n collect.error(`collection[${index}]`, \"a collection must be an object.\");\n return;\n }\n\n const slug = typeof collection.slug === \"string\" && collection.slug ? collection.slug : undefined;\n const at = slug ?? `collection[${index}]`;\n\n if (!slug) {\n collect.error(\n at,\n \"a collection has no `slug`. It is the collection's identity — the URL, the API path and \" +\n \"the key every relation targets.\"\n );\n }\n\n for (const key of Object.keys(collection)) {\n if (COLLECTION_KEYS.has(key)) continue;\n\n const migration = COLLECTION_MIGRATIONS[key];\n if (migration) {\n collect.migrated(`${at}.${key}`, key, migration);\n continue;\n }\n\n collect.unknown(`${at}.${key}`, key, \"collection\");\n }\n\n if (isPlainObject(collection.properties)) {\n checkProperties(collection.properties, `${at}.properties`, collect);\n } else if (collection.properties !== undefined) {\n collect.error(`${at}.properties`, \"`properties` must be an object keyed by property name.\");\n }\n\n if (Array.isArray(collection.relations)) {\n collection.relations.forEach((relation, i) => {\n const name = isPlainObject(relation) && typeof relation.relationName === \"string\"\n ? relation.relationName\n : String(i);\n checkRelation(relation, `${at}.relations[${name}]`, collect);\n });\n }\n}\n\n/**\n * Every problem across every collection, in one pass.\n *\n * Pure: it logs nothing and throws nothing, so callers that want to render the\n * list themselves (the doctor, a test) can.\n */\nexport function findCollectionConfigProblems(\n collections: readonly unknown[],\n options: ValidateCollectionConfigOptions = {}\n): ConfigProblem[] {\n const collect = new ProblemCollector(options.unknownKeys ?? unknownKeyPolicyFromEnv());\n collections.forEach((collection, index) => checkCollection(collection, index, collect));\n return collect.problems;\n}\n\nfunction render(problems: ConfigProblem[]): string {\n return problems.map(p => ` • ${p.path}\\n ${p.message}`).join(\"\\n\\n\");\n}\n\n/**\n * Warn about everything questionable, then refuse to boot if anything is wrong.\n *\n * Warnings are logged even when there are errors: someone migrating wants the\n * whole picture in one run, and the second-most annoying thing after a broken\n * boot is a boot that breaks again on something it could have told you the\n * first time.\n */\nexport function assertCollectionConfigs(\n collections: readonly unknown[],\n options: ValidateCollectionConfigOptions = {}\n): void {\n const problems = findCollectionConfigProblems(collections, options);\n if (problems.length === 0) return;\n\n const warnings = problems.filter(p => p.severity === \"warning\");\n const errors = problems.filter(p => p.severity === \"error\");\n\n if (warnings.length > 0) {\n logger.warn(\n `[collections] ${warnings.length} unrecognised key(s) in the collection config, ignored:\\n\\n` +\n render(warnings) +\n \"\\n\\nSet REBASE_STRICT_COLLECTION_CONFIG=error to make these fail the boot.\\n\"\n );\n }\n\n if (errors.length === 0) return;\n\n throw new Error(\n `${errors.length} problem(s) in the collection config.\\n\\n` +\n \"These keys are not read by this version. Nothing would have failed at runtime — \" +\n \"whatever they configure would simply be absent — so they are fatal at boot instead.\\n\\n\" +\n render(errors) + \"\\n\"\n );\n}\n","import { CollectionConfig, SecurityRule, isPostgresCollectionConfig } from \"@rebasepro/types\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport { logger } from \"../utils/logger\";\nimport { assertCollectionConfigs, type ValidateCollectionConfigOptions } from \"./validate-config\";\n\n/**\n * The one definition of \"the collections\".\n *\n * Four copies of this scan used to exist — the runtime, the drizzle-schema\n * generator, the policy generator and the doctor — each deciding for itself\n * which files counted. They agreed only by discipline, and any drift between\n * them would silently serve one set of collections while pushing policies for\n * another. Everything that needs to know what the collections are calls this.\n */\n\n/** Read from a directory's `index` module, or from a single-file source. */\nexport interface CollectionDefaults {\n /**\n * Applied to every collection that declares no `securityRules` of its own.\n *\n * This lives with the collections rather than in the server config because\n * `db push` generates the actual Postgres policies from these files and\n * never sees the running server — a default declared on the server could\n * never reach the database, and would look like an authorization setting\n * while enforcing nothing.\n */\n defaultSecurityRules?: SecurityRule[];\n}\n\nfunction isCollectionFile(file: string): boolean {\n return (file.endsWith(\".ts\") || file.endsWith(\".js\")) &&\n // Dotfiles are never collections. In particular macOS bsdtar puts\n // AppleDouble sidecars (`._foo.ts`) into build contexts — binary blobs\n // whose names end in .ts and whose first byte is \\x00, so importing\n // them kills the whole load.\n !file.startsWith(\".\") &&\n !file.includes(\".test.\") &&\n !file.endsWith(\".d.ts\") &&\n // index is the directory's own module: defaults live there, not a collection.\n file !== \"index.ts\" && file !== \"index.js\";\n}\n\nasync function importModule(filePath: string): Promise<Record<string, unknown>> {\n // Plain import() so tsx/loader hooks resolve .ts and workspace specifiers.\n return await import(pathToFileURL(filePath).href);\n}\n\n/** Read `defaultSecurityRules` from a collections directory's index module. */\nasync function readDefaults(directory: string): Promise<CollectionDefaults> {\n for (const name of [\"index.ts\", \"index.js\"]) {\n const indexPath = path.join(directory, name);\n if (!fs.existsSync(indexPath)) continue;\n try {\n const mod = await importModule(indexPath);\n return { defaultSecurityRules: mod.defaultSecurityRules as SecurityRule[] | undefined };\n } catch (err) {\n // The index usually just re-exports the collections for the frontend;\n // a failure to read it must not take the whole load down.\n logger.warn(`[collections] Could not read defaults from ${name}: ${err instanceof Error ? err.message : String(err)}`);\n return {};\n }\n }\n return {};\n}\n\n/**\n * Apply directory-level defaults. A collection declaring its own rules is left\n * alone; one declaring none inherits these. Declaring neither leaves\n * `securityRules` unset, which the policy generator treats as locked-by-default.\n */\nexport function applyCollectionDefaults(\n collections: CollectionConfig[],\n defaults: CollectionDefaults\n): CollectionConfig[] {\n if (!defaults.defaultSecurityRules?.length) return collections;\n for (const collection of collections) {\n if (isPostgresCollectionConfig(collection) && !collection.securityRules?.length) {\n collection.securityRules = defaults.defaultSecurityRules;\n }\n }\n return collections;\n}\n\n/**\n * Load collections from a directory of collection files, or from a single\n * module exporting `backendCollections` / `collections`.\n *\n * Throws if any file fails to import. A collection that cannot be loaded is a\n * configuration error, and continuing produces the worst outcome available: an\n * API missing a route, or a policy file missing a table, with a successful exit\n * code. Both read as \"no data\" rather than as a failure.\n *\n * Every collection is strict-parsed on the way out — see `validate-config` for\n * why a key that moved is fatal and a key nobody recognises only warns. It\n * happens here, at the one definition of \"the collections\", so the runtime, the\n * schema generator, the policy generator and the doctor all see the same\n * verdict rather than three of them silently accepting a config the fourth\n * rejects.\n */\nexport async function loadCollectionsFromDirectory(\n source: string,\n options: { validate?: false | ValidateCollectionConfigOptions } = {}\n): Promise<CollectionConfig[]> {\n const resolved = path.resolve(source);\n const validate = (collections: CollectionConfig[]): CollectionConfig[] => {\n if (options.validate !== false) assertCollectionConfigs(collections, options.validate ?? {});\n return collections;\n };\n\n if (!fs.existsSync(resolved)) {\n logger.warn(`[collections] Not found: ${resolved}`);\n return [];\n }\n\n // A single module exports the collections, and may export the defaults.\n if (!fs.statSync(resolved).isDirectory()) {\n const mod = await importModule(resolved);\n const collections = (mod.backendCollections || mod.collections || []) as CollectionConfig[];\n return validate(applyCollectionDefaults([...collections], {\n defaultSecurityRules: mod.defaultSecurityRules as SecurityRule[] | undefined\n }));\n }\n\n const collections: CollectionConfig[] = [];\n const failures: string[] = [];\n\n for (const file of fs.readdirSync(resolved).filter(isCollectionFile)) {\n try {\n const mod = await importModule(path.join(resolved, file));\n if (mod?.default) {\n collections.push(mod.default as CollectionConfig);\n } else {\n failures.push(`${file}: no default export`);\n }\n } catch (err) {\n failures.push(`${file}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `Could not load ${failures.length} collection file(s) from ${resolved}:\\n` +\n failures.map((f) => ` • ${f}`).join(\"\\n\") +\n \"\\n\\nEvery collection file must import cleanly and default-export a collection.\"\n );\n }\n\n return validate(applyCollectionDefaults(collections, await readDefaults(resolved)));\n}\n","/**\n * Driver Registry\n *\n * Manages multiple driver delegates for Rebase backend.\n * Allows different databases for different collections.\n *\n * Usage:\n * - Single DB: Pass a single DataDriver → maps to \"(default)\"\n * - Multiple DBs: Pass a map of { dbId: DataDriver }\n * - Collections use `databaseId` property to specify which driver to use\n * - Collections without `databaseId` fallback to \"(default)\"\n */\n\nimport { DataDriver } from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * The default driver identifier used when:\n * - A single driver is provided (not a map)\n * - A collection doesn't specify a databaseId\n */\nexport const DEFAULT_DRIVER_ID = \"(default)\";\n\n/**\n * Registry for managing multiple driver delegates\n */\nexport interface DriverRegistry {\n /**\n * Register a driver delegate with an ID\n * @param id - Unique identifier for this driver (e.g., \"analytics\", \"users\")\n * @param delegate - The DataDriver instance\n */\n register(id: string, delegate: DataDriver): void;\n\n /**\n * Get the default driver delegate (id = \"(default)\")\n * @throws Error if no default driver is registered\n */\n getDefault(): DataDriver;\n\n /**\n * Get a driver delegate by ID\n * @param id - Driver identifier, or undefined/null for default\n * @returns The DataDriver, or undefined if not found\n */\n get(id: string | undefined | null): DataDriver | undefined;\n\n /**\n * Get a driver delegate by ID, with fallback to default\n * @param id - Driver identifier, or undefined/null for default\n * @returns The DataDriver (falls back to default if id not found)\n * @throws Error if neither the specified nor default driver exists\n */\n getOrDefault(id: string | undefined | null): DataDriver;\n\n /**\n * Check if a driver with the given ID exists\n */\n has(id: string): boolean;\n\n /**\n * List all registered driver IDs\n */\n list(): string[];\n\n /**\n * Get the number of registered drivers\n */\n size(): number;\n}\n\n/**\n * Default implementation of DriverRegistry\n */\nexport class DefaultDriverRegistry implements DriverRegistry {\n private delegates = new Map<string, DataDriver>();\n\n /**\n * Create a DriverRegistry from either a single delegate or a map\n * @param input - Single DataDriver (maps to \"(default)\") or Record<string, DataDriver>\n */\n static create(\n input: DataDriver | Record<string, DataDriver>\n ): DefaultDriverRegistry {\n const registry = new DefaultDriverRegistry();\n\n if (isDataDriverDelegate(input)) {\n // Single delegate → register as \"(default)\"\n registry.register(DEFAULT_DRIVER_ID, input);\n } else {\n // Map of delegates → register each\n for (const [id, delegate] of Object.entries(input)) {\n registry.register(id, delegate);\n }\n // Ensure there's a default if not explicitly provided\n if (!registry.has(DEFAULT_DRIVER_ID) && registry.size() > 0) {\n // If no explicit \"(default)\", use the first one as default\n const firstId = Object.keys(input)[0];\n logger.warn(\n `[DriverRegistry] No \"${DEFAULT_DRIVER_ID}\" driver provided. ` +\n `Using \"${firstId}\" as the default.`\n );\n registry.register(DEFAULT_DRIVER_ID, input[firstId]);\n }\n }\n\n return registry;\n }\n\n register(id: string, delegate: DataDriver): void {\n if (this.delegates.has(id)) {\n logger.warn(`[DriverRegistry] Overwriting driver with id \"${id}\"`);\n }\n this.delegates.set(id, delegate);\n }\n\n getDefault(): DataDriver {\n const delegate = this.delegates.get(DEFAULT_DRIVER_ID);\n if (!delegate) {\n throw new Error(\n \"[DriverRegistry] No default driver registered. \" +\n `Register one with id \"${DEFAULT_DRIVER_ID}\" or pass a single DataDriver.`\n );\n }\n return delegate;\n }\n\n get(id: string | undefined | null): DataDriver | undefined {\n if (id === undefined || id === null) {\n return this.delegates.get(DEFAULT_DRIVER_ID);\n }\n return this.delegates.get(id);\n }\n\n getOrDefault(id: string | undefined | null): DataDriver {\n // If no ID specified, return default\n if (id === undefined || id === null) {\n return this.getDefault();\n }\n\n // Try to get by ID\n const delegate = this.delegates.get(id);\n if (delegate) {\n return delegate;\n }\n\n // Fallback to default with warning\n logger.warn(\n `[DriverRegistry] Driver \"${id}\" not found, falling back to \"${DEFAULT_DRIVER_ID}\"`\n );\n return this.getDefault();\n }\n\n has(id: string): boolean {\n return this.delegates.has(id);\n }\n\n list(): string[] {\n return Array.from(this.delegates.keys());\n }\n\n size(): number {\n return this.delegates.size;\n }\n}\n\n/**\n * Type guard to check if an object is a DataDriver\n */\nfunction isDataDriverDelegate(obj: unknown): obj is DataDriver {\n if (typeof obj !== \"object\" || obj === null) {\n return false;\n }\n const delegate = obj as DataDriver;\n // Check for required DataDriver properties\n return (\n typeof delegate.key === \"string\" &&\n typeof delegate.fetchCollection === \"function\" &&\n typeof delegate.fetchOne === \"function\" &&\n typeof delegate.save === \"function\" &&\n typeof delegate.delete === \"function\"\n );\n}\n","import { RealtimeProvider } from \"@rebasepro/types\";\n\n/**\n * A realtime client message as forwarded by the WebSocket server.\n */\ninterface ClientMessage {\n type: string;\n payload?: Record<string, unknown>;\n subscriptionId?: string;\n}\n\n/**\n * The concrete realtime service surface the WebSocket server drives — the\n * typed {@link RealtimeProvider} plus the client-connection methods that\n * every engine's realtime service implements.\n */\nexport interface WsRealtimeService extends RealtimeProvider {\n addClient(clientId: string, ws: unknown): void;\n handleClientMessage(clientId: string, message: ClientMessage, authContext?: unknown): Promise<void> | void;\n}\n\n/** Channel/presence/broadcast messages are engine-agnostic pub/sub. */\nconst CHANNEL_MESSAGE_TYPES = new Set([\n \"join_channel\", \"leave_channel\", \"broadcast\",\n \"presence_track\", \"presence_untrack\", \"presence_state\"\n]);\n\nexport interface RoutedRealtimeOptions {\n /** Per-engine realtime providers, keyed by data-source key. */\n providers: Record<string, RealtimeProvider>;\n /** Key of the default provider (handles channels/presence/broadcast). */\n defaultKey: string;\n /** Resolve a collection path to its data-source key. */\n resolveKey: (collectionPath: string) => string;\n}\n\n/**\n * Compose multiple per-engine {@link RealtimeProvider}s into one that routes\n * each subscription to the provider owning the subscribed collection — the\n * realtime counterpart of `buildRoutedRebaseData`.\n *\n * The WebSocket server stays single and engine-agnostic; this composite is\n * passed in its place. Routing rules:\n * - `subscribe_collection` / `subscribe_entity` → the provider for the\n * collection's data source (by `payload.path`).\n * - `unsubscribe` → forwarded to all providers (a no-op on non-owners).\n * - channel / presence / broadcast → the default provider (these are global\n * pub/sub, not bound to an engine).\n * - `addClient` and lifecycle (`onServerReady`/`destroy`/`stopListening`) →\n * all providers (each registers its own ws close handler for cleanup).\n */\nexport function createRoutedRealtimeService(opts: RoutedRealtimeOptions): WsRealtimeService {\n const { providers, defaultKey, resolveKey } = opts;\n\n const asWs = (p: RealtimeProvider): WsRealtimeService => p as unknown as WsRealtimeService;\n const all = (): WsRealtimeService[] => Object.values(providers).map(asWs);\n const fallback = (): WsRealtimeService => asWs(providers[defaultKey] ?? Object.values(providers)[0]);\n const forPath = (path?: string): WsRealtimeService => {\n if (!path) return fallback();\n const key = resolveKey(path);\n return asWs(providers[key] ?? providers[defaultKey] ?? Object.values(providers)[0]);\n };\n\n return {\n addClient(clientId, ws) {\n for (const p of all()) p.addClient?.(clientId, ws);\n },\n\n async handleClientMessage(clientId, message, authContext) {\n const { type } = message;\n if (type === \"subscribe_collection\" || type === \"subscribe_one\") {\n await forPath(message.payload?.path as string | undefined)\n .handleClientMessage(clientId, message, authContext);\n return;\n }\n if (type === \"unsubscribe\") {\n // The owning provider acts; others no-op on an unknown id.\n await Promise.all(all().map((p) => p.handleClientMessage(clientId, message, authContext)));\n return;\n }\n // Channels/presence/broadcast (and anything else) → default provider.\n await fallback().handleClientMessage(clientId, message, authContext);\n },\n\n subscribeToCollection(subscriptionId, config, callback) {\n forPath((config as { path?: string }).path).subscribeToCollection(subscriptionId, config, callback);\n },\n\n subscribeToOne(subscriptionId, config, callback) {\n forPath((config as { path?: string }).path).subscribeToOne(subscriptionId, config, callback);\n },\n\n unsubscribe(subscriptionId) {\n for (const p of all()) p.unsubscribe(subscriptionId);\n },\n\n async notifyUpdate(path: string, id: string, row: Record<string, unknown> | null, databaseId?: string) {\n await forPath(path).notifyUpdate(path, id, row, databaseId);\n },\n\n onServerReady(serverInfo) {\n for (const p of all()) p.onServerReady?.(serverInfo);\n },\n\n async destroy() {\n await Promise.all(all().map((p) => p.destroy?.()));\n },\n\n async stopListening() {\n await Promise.all(all().map((p) => p.stopListening?.()));\n }\n };\n}\n","import type { FilterValues, LogicalCondition, VectorSearchParams } from \"@rebasepro/types\";\nimport { toCanonicalOp, resolveClientListLimit, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from \"@rebasepro/types\";\nimport { deserializeOrderBy, deserializeFilter, deserializeLogicalCondition } from \"@rebasepro/common\";\nimport { QueryOptions } from \"../types\";\nimport { ApiError } from \"../errors\";\n\nexport const mapOperator = (op: string) => toCanonicalOp(op) ?? null;\n\nfunction getLastValue(val: unknown): unknown {\n if (Array.isArray(val)) {\n return val[val.length - 1];\n }\n return val;\n}\n\n/**\n * Parse an `or(...)` / `and(...)` logical group from its wire form.\n *\n * The wire carries the inner conditions wrapped in parens (e.g.\n * `(status.eq.active,age.gte.18)`); we re-attach the `or`/`and` prefix and\n * delegate to the canonical filter dialect (`@rebasepro/common`). Values are\n * preserved as strings — type coercion is the schema-aware driver's job, so\n * this path stays byte-for-byte consistent with the SDK/admin path (which\n * also parses via the shared dialect).\n */\nfunction parseLogicalGroup(type: \"or\" | \"and\", raw: unknown): LogicalCondition | undefined {\n let inner = String(raw).trim();\n if (inner.startsWith(\"(\") && inner.endsWith(\")\")) {\n inner = inner.slice(1, -1);\n }\n inner = inner.trim();\n if (!inner) return undefined;\n const parsed = deserializeLogicalCondition(`${type}(${inner})`);\n return \"type\" in parsed ? parsed : undefined;\n}\n\n/**\n * Parse the `?where=` JSON filter object.\n *\n * This is the dialect the OpenAPI document publishes on every\n * `GET /api/data/{slug}` — `{\"status\":[\"==\",\"active\"]}`: field → canonical\n * `[WhereFilterOp, value]` tuple. It is normalized through the same\n * `deserializeFilter` as the `?field=op.value` params below, so a value that\n * arrives as a PostgREST dot-string (`{\"status\":\"eq.active\"}`) or as a bare\n * scalar (`{\"status\":\"active\"}`) compiles to the same condition. Unlike the\n * querystring dialect, JSON carries types — a number stays a number.\n *\n * A malformed value is a 400 rather than a silent drop: dropping the filter\n * would run the read unfiltered and return everything RLS happens to allow.\n */\nfunction parseWhereParam(raw: unknown): FilterValues<string> | undefined {\n const str = String(raw).trim();\n if (!str) return undefined;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(str);\n } catch {\n throw ApiError.badRequest(\n \"Invalid `where` parameter: expected a JSON object, e.g. {\\\"status\\\":[\\\"==\\\",\\\"active\\\"]}\",\n \"INVALID_WHERE\"\n );\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw ApiError.badRequest(\n \"Invalid `where` parameter: expected a JSON object mapping fields to conditions, \"\n + \"e.g. {\\\"status\\\":[\\\"==\\\",\\\"active\\\"]}\",\n \"INVALID_WHERE\"\n );\n }\n\n const filter = deserializeFilter(parsed as Record<string, unknown>);\n return Object.keys(filter).length > 0 ? filter : undefined;\n}\n\n// Re-exported for callers/tests that reference the REST list bounds. The\n// numbers and clamp live in `@rebasepro/types` so the REST parser and the\n// WebSocket ingress enforce ONE shared guarantee. See `resolveClientListLimit`.\nexport { DEFAULT_LIST_LIMIT, DEFAULT_VECTOR_LIST_LIMIT, MAX_LIST_LIMIT } from \"@rebasepro/types\";\n\n/**\n * Overridable list-pagination bounds for {@link parseQueryOptions}. Without\n * these, `GET /<collection>` with no `?limit` would buffer the ENTIRE table\n * into a JS array + JSON response (a trivial OOM/DoS), and `?limit=100000000`\n * would be honoured verbatim.\n */\nexport interface ListLimitOptions {\n /**\n * Page size used when the client sends no `?limit`. Applied to plain and\n * text-search reads — a vector search falls back to its own default (10).\n */\n defaultLimit?: number;\n /** Upper bound clamped onto any client-supplied `?limit`. */\n maxLimit?: number;\n}\n\n/**\n * Parse query parameters into QueryOptions\n */\nexport function parseQueryOptions(\n query: Record<string, unknown>,\n limits: ListLimitOptions = {}\n): QueryOptions {\n const options: QueryOptions = {};\n const rawLimit = getLastValue(query.limit) as number | string | null | undefined;\n\n const offsetVal = getLastValue(query.offset);\n if (offsetVal) options.offset = parseInt(String(offsetVal));\n\n const pageVal = getLastValue(query.page);\n if (pageVal) {\n const page = parseInt(String(pageVal));\n // Page stride uses the same bounded page size the read will use, so\n // pages neither overlap nor gap. (Vector search never paginates by\n // page, so the plain/text default is correct here.)\n const limit = resolveClientListLimit(rawLimit, {\n defaultLimit: limits.defaultLimit,\n maxLimit: limits.maxLimit\n });\n options.offset = (page - 1) * limit;\n }\n\n // ── Logical conditions (or / and) ──────────────────────────────────\n const orVal = getLastValue(query.or);\n const andVal = getLastValue(query.and);\n if (orVal) {\n const logical = parseLogicalGroup(\"or\", orVal);\n if (logical) options.logical = logical;\n } else if (andVal) {\n const logical = parseLogicalGroup(\"and\", andVal);\n if (logical) options.logical = logical;\n }\n\n // ── PostgREST-style field filters: ?field=op.value ─────────────────\n // Delegate to the canonical filter dialect (the single source of truth\n // for the wire grammar: operator codes, list/escape handling, implicit\n // eq). Values stay strings; the schema-aware driver coerces them to\n // column types. This keeps the REST path byte-for-byte consistent with\n // the SDK/admin path, which parses through the same `deserializeFilter`.\n //\n // `where` is reserved: it is the JSON filter dialect (see\n // `parseWhereParam`), not a column named \"where\". Leaving it out of this\n // list made the documented `?where={...}` compile as a filter on a\n // nonexistent field — which used to be dropped, widening the read to the\n // whole table, and is now a 400 `UNKNOWN_FILTER_FIELD`.\n const reservedQueryKeys = [\"limit\", \"offset\", \"page\", \"orderBy\", \"include\", \"fields\", \"searchString\", \"vector_search\", \"vector\", \"vector_distance\", \"vector_threshold\", \"or\", \"and\", \"where\"];\n const filterDict: Record<string, unknown> = {};\n for (const [key, rawValue] of Object.entries(query)) {\n if (reservedQueryKeys.includes(key)) continue;\n filterDict[key] = rawValue;\n }\n // Both dialects may be sent together; an explicit `?field=op.value` wins\n // over the same field inside `where`, being the more specific request.\n const whereVal = getLastValue(query.where);\n const where = {\n ...(whereVal !== undefined && whereVal !== null ? parseWhereParam(whereVal) : undefined),\n ...deserializeFilter(filterDict)\n };\n if (Object.keys(where).length > 0) {\n options.where = where;\n }\n\n // Sorting\n const orderByVal = getLastValue(query.orderBy);\n if (orderByVal) {\n try {\n options.orderBy = typeof orderByVal === \"string\"\n ? JSON.parse(orderByVal)\n : orderByVal;\n } catch {\n // Try simple format: \"field:direction\"\n if (typeof orderByVal === \"string\") {\n const parsed = deserializeOrderBy(orderByVal);\n if (parsed) {\n options.orderBy = [\n {\n field: parsed[0],\n direction: parsed[1]\n }\n ];\n }\n }\n }\n }\n\n // Relation includes\n const includeVal = getLastValue(query.include);\n if (includeVal) {\n const includeStr = String(includeVal).trim();\n if (includeStr === \"*\") {\n options.include = [\"*\"];\n } else {\n options.include = includeStr.split(\",\").map(s => s.trim()).filter(Boolean);\n }\n }\n\n // Field selection\n const fieldsVal = getLastValue(query.fields);\n if (fieldsVal) {\n const fieldsStr = String(fieldsVal).trim();\n options.fields = fieldsStr.split(\",\").map(s => s.trim()).filter(Boolean);\n }\n\n // ── Vector similarity search ───────────────────────────────────────\n // Every rejection here is a malformed *request*, so it must carry a 400.\n // A bare `Error` reaches the handler with no `statusCode` and no known\n // `code`, which makes it a 500 — logged with a full stack as an incident,\n // and answered with \"An unexpected error occurred\", because the handler\n // only forwards a message to the client below 500. The caller was told\n // nothing about what it got wrong.\n const vectorSearchVal = getLastValue(query.vector_search);\n const vectorVal = getLastValue(query.vector);\n if (vectorSearchVal && vectorVal) {\n const vectorStr = String(vectorVal);\n let decoded: unknown;\n try {\n decoded = JSON.parse(vectorStr);\n } catch {\n decoded = undefined;\n }\n // Validated outside the `try` on purpose: inside it, the thrown\n // ApiError would be caught by its own `catch` and re-thrown as\n // something else.\n if (!Array.isArray(decoded) || !decoded.every(v => typeof v === \"number\")) {\n throw ApiError.badRequest(\n \"Invalid `vector` format. Expected a JSON array of numbers, e.g. [0.1,0.2,0.3]\",\n \"INVALID_VECTOR\"\n );\n }\n const queryVector = decoded as number[];\n\n const distanceParamVal = getLastValue(query.vector_distance);\n const distanceParam = distanceParamVal ? String(distanceParamVal) : \"cosine\";\n if (distanceParam !== \"cosine\" && distanceParam !== \"l2\" && distanceParam !== \"inner_product\") {\n throw ApiError.badRequest(\n `Invalid \\`vector_distance\\`: ${distanceParam}. Expected: cosine, l2, or inner_product`,\n \"INVALID_VECTOR_DISTANCE\"\n );\n }\n\n const vectorSearch: VectorSearchParams = {\n property: String(vectorSearchVal),\n vector: queryVector,\n distance: distanceParam\n };\n\n const thresholdVal = getLastValue(query.vector_threshold);\n if (thresholdVal) {\n const threshold = parseFloat(String(thresholdVal));\n if (isNaN(threshold)) {\n throw ApiError.badRequest(\n \"Invalid `vector_threshold`. Expected a number.\",\n \"INVALID_VECTOR_THRESHOLD\"\n );\n }\n vectorSearch.threshold = threshold;\n }\n\n options.vectorSearch = vectorSearch;\n }\n\n // Resolve the limit LAST — once we know whether this is a vector search —\n // so a client-supplied limit is clamped to the hard max and an absent one\n // falls back to the correct mode default (plain/text = defaultLimit, vector\n // = 10). Without this a bare `GET /<collection>` would return the whole\n // table. Shared with the WebSocket ingress via `resolveClientListLimit`.\n options.limit = resolveClientListLimit(rawLimit, {\n vectorSearch: !!options.vectorSearch,\n defaultLimit: limits.defaultLimit,\n maxLimit: limits.maxLimit\n });\n\n return options;\n}\n","import { CollectionConfig, type ResolvedBelongsTo } from \"@rebasepro/types\";\nimport { resolveCollectionRelations } from \"@rebasepro/common\";\nimport { ApiError } from \"../errors\";\n\n/**\n * Reject a write naming a field the collection does not have.\n *\n * Unknown keys used to travel all the way into the INSERT, where Postgres\n * rejected them — so a typo came back as `column \"titel\" does not exist`,\n * phrased by the database, from a stack the caller cannot see, and only if the\n * column really was absent. It is a request problem and belongs in a 400.\n *\n * What counts as known:\n * - a declared property (for an introspected BaaS collection these *are* the\n * columns, so the set is exact);\n * - the foreign-key column behind an owning relation, which callers may write\n * directly instead of through the relation property;\n * - anything named in `options.extraKnownFields` — for an auth collection the\n * credential keys the auth adapter consumes before a row is ever built;\n * - nothing else. `id` in particular is not automatically known — see below.\n */\nexport function assertKnownWriteFields(\n values: Record<string, unknown>,\n collection: CollectionConfig,\n options?: { rowIndex?: number; extraKnownFields?: readonly string[] }\n): void {\n if (collection.strictWrites === false) return;\n\n // A collection that declares no properties describes nothing, so there is\n // nothing to check against — \"no declared fields\" is not the same claim as\n // \"no fields are allowed\", and reading it as the latter would turn every\n // write to such a collection into a 400. Postgres still has the last word.\n if (!collection.properties || Object.keys(collection.properties).length === 0) return;\n\n const known = new Set<string>(Object.keys(collection.properties));\n\n // An owning relation stores its target in a local FK column that usually\n // has no property of its own; writing it directly is legitimate.\n for (const relation of Object.values(resolveCollectionRelations(collection))) {\n if (relation.kind === \"belongsTo\") known.add((relation as ResolvedBelongsTo).localKey);\n }\n\n for (const field of options?.extraKnownFields ?? []) known.add(field);\n\n const unknown = Object.keys(values).filter(key => !known.has(key));\n if (unknown.length === 0) return;\n\n const where = options?.rowIndex !== undefined ? `Row ${options.rowIndex}: ` : \"\";\n\n // The `id` case is worth its own sentence, because the caller almost\n // certainly did not choose to send it — `create(data, id)` puts it there,\n // which is right for a table keyed on `id` and meaningless for any other.\n if (unknown.includes(\"id\") && !known.has(\"id\")) {\n const keys = Object.entries(collection.properties ?? {})\n .filter(([, prop]) => \"isId\" in (prop as object) && Boolean((prop as { isId?: unknown }).isId))\n .map(([name]) => `'${name}'`);\n const keyDesc = keys.length > 0 ? keys.join(\" + \") : \"its own key column\";\n throw ApiError.badRequest(\n `${where}'${collection.slug}' has no 'id' column — it is keyed on ${keyDesc}. ` +\n `The \\`id\\` argument of \\`create(data, id)\\` is written as an \\`id\\` column, so for this ` +\n `collection put the key in \\`data\\` instead.`,\n \"VALIDATION_UNKNOWN_FIELDS\"\n );\n }\n\n throw ApiError.badRequest(\n `${where}'${collection.slug}' has no field${unknown.length > 1 ? \"s\" : \"\"} ` +\n `${unknown.map(f => `'${f}'`).join(\", \")}. ` +\n `Known fields: ${[...known].sort().map(f => `'${f}'`).join(\", \")}.`,\n \"VALIDATION_UNKNOWN_FIELDS\"\n );\n}\n\n/**\n * Narrow response rows to the fields the caller asked for.\n *\n * `?fields=id,title` is documented in the generated OpenAPI — \"Comma-separated\n * list of fields to return (field selection)\" — and it is the first thing shown\n * on every endpoint in the API Explorer. It was parsed into `options.fields`\n * and then read by nothing at all: no driver referenced it, and every request\n * came back with every column. A caller asking for two fields of a `posts` row\n * still received its whole `content`.\n *\n * This shapes the *response*, which is what the parameter says it does; it is\n * not a column pushdown, so it saves bandwidth rather than database work.\n *\n * `id` always survives. Rows are addressed by it everywhere above this layer —\n * the admin table, realtime reconciliation, the offline cache — and a row that\n * arrives without one is not a smaller row, it is an unusable one. Asking for\n * `fields=title` and being unable to open the record you clicked is a worse\n * answer than one extra key.\n */\nexport function projectResponseFields<T extends Record<string, unknown>>(\n rows: T[],\n fields: readonly string[] | undefined,\n collection: CollectionConfig,\n options?: { include?: readonly string[] }\n): T[] {\n if (!fields || fields.length === 0) return rows;\n\n const declared = new Set<string>(Object.keys(collection.properties ?? {}));\n // The record is keyed by the property name the relation is reached under,\n // which is the name a caller would put in `fields`.\n for (const [key, relation] of Object.entries(resolveCollectionRelations(collection))) {\n declared.add(key);\n if (relation.kind === \"belongsTo\") declared.add((relation as ResolvedBelongsTo).localKey);\n }\n // `include` decides what is *loaded*; `fields` decides what is *returned*.\n // So `include=author&fields=title,author` yields both, and naming the\n // relation in `fields` without including it yields nothing for it — there\n // was nothing fetched to return. Included names are accepted here so that\n // a relation reached only through `include` (one the collection does not\n // declare as a property) is not rejected as unknown.\n for (const included of options?.include ?? []) declared.add(included);\n declared.add(\"id\");\n\n // A collection that declares nothing describes nothing to check against —\n // the same reasoning `assertKnownWriteFields` applies one function up.\n if (declared.size > 1) {\n const unknown = fields.filter(field => !declared.has(field));\n if (unknown.length > 0) {\n throw ApiError.badRequest(\n `'${collection.slug}' has no field${unknown.length > 1 ? \"s\" : \"\"} ` +\n `${unknown.map(f => `'${f}'`).join(\", \")} to return. ` +\n `Known fields: ${[...declared].sort().map(f => `'${f}'`).join(\", \")}.`,\n \"UNKNOWN_RESPONSE_FIELD\",\n { fields: unknown, collection: collection.slug }\n );\n }\n }\n\n const keep = new Set<string>([...fields, \"id\"]);\n return rows.map(row => {\n const projected: Record<string, unknown> = {};\n for (const key of Object.keys(row)) {\n if (keep.has(key)) projected[key] = row[key];\n }\n return projected as T;\n });\n}\n","import { DataDriver, isSQLAdmin } from \"@rebasepro/types\";\nimport { logger } from \"../../utils/logger\";\n\n/**\n * Remembering what a write already answered, so replaying it does not do it twice.\n *\n * The offline queue replays a mutation whenever it did not see the response —\n * which includes every case where the write *committed* and the ACK was lost to\n * a dropped connection. For a collection whose id the client chooses, the replay\n * collides on that id and the client can recognise its own earlier attempt. For\n * a collection with a serial id it cannot: the server ignored the id the client\n * invented and assigned its own, so the replay is indistinguishable from a new\n * row and inserts a second one. The scaffold's own collections use\n * `isId: \"increment\"`, so that is the default case, not an exotic one.\n *\n * A key is honoured only for the principal that created it. Mutation ids are\n * generated on the client, so keying on the id alone would let anyone who\n * learned (or guessed) another user's id replay their key and be handed that\n * user's row back — a read of someone else's data through a write endpoint.\n */\nconst TABLE = \"\\\"rebase\\\".\\\"idempotency_keys\\\"\";\n\n/**\n * How long a replay is recognised. Long enough to cover an offline stretch and\n * a retry schedule; short enough that the table stays small and a key cannot be\n * replayed indefinitely. Rows past this are pruned opportunistically rather than\n * by a scheduled job — there is no cron guaranteed to be running.\n */\nconst TTL_HOURS = 24;\n\n/**\n * The principal a key belongs to; anonymous and service writes share a sentinel.\n *\n * The NUL is written as an escape, not as a raw byte in the source. The\n * sentinel itself is deliberate — a uid can never contain one — but written\n * literally it makes this file test as binary, and every repo-wide grep then\n * skips all 124 lines of it silently. Identical at runtime.\n */\nfunction principal(uid: string | undefined): string {\n return uid && uid.length > 0 ? uid : \"\\u0000anon\";\n}\n\nexport interface IdempotencyStore {\n /** What this key answered before, or `undefined` if it is new. */\n recall(key: string, uid: string | undefined): Promise<unknown | undefined>;\n /** Record what this key answered. Never throws — see {@link createIdempotencyStore}. */\n remember(key: string, uid: string | undefined, response: unknown): Promise<void>;\n}\n\n/**\n * Returns `undefined` when the driver cannot run SQL, which disables the whole\n * mechanism rather than failing writes: a document backend has no table to put\n * this in, and refusing to serve is far worse than the duplicate this prevents.\n *\n * Every method swallows its own errors for the same reason. A write must not\n * fail because the bookkeeping around it did — the worst case of a failed\n * `remember` is the duplicate we already have today, while a thrown error would\n * reject a write the database has already accepted.\n */\nexport function createIdempotencyStore(driver: DataDriver): IdempotencyStore | undefined {\n const admin = driver.admin;\n if (!isSQLAdmin(admin)) return undefined;\n const exec = (sql: string, params?: unknown[]) => admin.executeSql(sql, params ? { params } : undefined);\n\n let ready: Promise<boolean> | undefined;\n /** Created on first use: most deployments never send a key at all. */\n const ensure = (): Promise<boolean> => {\n ready ??= (async () => {\n try {\n await exec(\"CREATE SCHEMA IF NOT EXISTS rebase\");\n await exec(`\n CREATE TABLE IF NOT EXISTS ${TABLE} (\n key TEXT NOT NULL,\n uid TEXT NOT NULL,\n response JSONB,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n PRIMARY KEY (uid, key)\n )\n `);\n await exec(`CREATE INDEX IF NOT EXISTS idx_idempotency_created ON ${TABLE}(created_at)`);\n return true;\n } catch (error) {\n logger.warn(\n \"Idempotency keys unavailable — a replayed offline write may insert a duplicate row.\",\n { detail: error instanceof Error ? error.message : String(error) }\n );\n return false;\n }\n })();\n return ready;\n };\n\n return {\n async recall(key, uid) {\n if (!key || !(await ensure())) return undefined;\n try {\n const rows = await exec(\n `SELECT response FROM ${TABLE}\n WHERE uid = $1 AND key = $2 AND created_at > NOW() - INTERVAL '${TTL_HOURS} hours'`,\n [principal(uid), key]\n );\n return rows[0]?.response;\n } catch {\n return undefined;\n }\n },\n\n async remember(key, uid, response) {\n if (!key || !(await ensure())) return;\n try {\n // ON CONFLICT DO NOTHING: two tabs replaying the same key at\n // once must not turn a race into a 23505 that fails the write.\n await exec(\n `INSERT INTO ${TABLE} (key, uid, response) VALUES ($1, $2, $3::jsonb)\n ON CONFLICT (uid, key) DO NOTHING`,\n [key, principal(uid), JSON.stringify(response ?? null)]\n );\n // Cheap and unsynchronised on purpose: an occasional extra pass\n // costs less than a scheduler this package cannot assume exists.\n if (Math.random() < 0.01) {\n await exec(`DELETE FROM ${TABLE} WHERE created_at < NOW() - INTERVAL '${TTL_HOURS} hours'`);\n }\n } catch {\n /* Bookkeeping only — never fail the write it describes. */\n }\n }\n };\n}\n\n/** The header the client sends. Matches the widely used Stripe/IETF spelling. */\nexport const IDEMPOTENCY_HEADER = \"Idempotency-Key\";\n","import { Hono, type Context } from \"hono\";\nimport { AuthAdapter, DataDriver, CollectionConfig, getCollectionDataPath } from \"@rebasepro/types\";\nimport { QueryOptions, HonoEnv } from \"../types\";\nimport { ApiError, isRebaseApiError } from \"../errors\";\nimport { parseQueryOptions, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, type ListLimitOptions } from \"./query-parser\";\nimport { assertKnownWriteFields, projectResponseFields } from \"./write-validation\";\nimport { httpMethodToOperation, isOperationAllowed } from \"../../auth/api-keys/api-key-permission-guard\";\nimport type { ApiKeyMasked } from \"../../auth/api-keys/api-key-types\";\nimport { findRelation, resolveCollectionRelations } from \"@rebasepro/common\";\nimport { createIdempotencyStore, IDEMPOTENCY_HEADER, type IdempotencyStore } from \"./idempotency\";\n\n/**\n * Parse a JSON request body for a create/update. An empty body yields `{}`\n * (a valid \"no explicit fields\" write), but a **malformed** body throws a 400\n * rather than being silently swallowed to `{}` — which would turn bad input\n * into an unintended empty write.\n */\nasync function parseJsonBody(c: Context<HonoEnv>): Promise<Record<string, unknown>> {\n const raw = await c.req.text();\n if (!raw || raw.trim() === \"\") return {};\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw ApiError.badRequest(\"Invalid JSON body\");\n }\n}\n\n\n\n/**\n * Lightweight REST API generator that leverages existing Rebase DataDriver.\n * Supports `include` query parameter for eager-loading relations via Drizzle.\n */\n/** Rows accepted by a single POST /<collection>/bulk. See `maxBulkRows`. */\nexport const DEFAULT_MAX_BULK_ROWS = 1000;\n\nexport class RestApiGenerator {\n private collections: CollectionConfig[];\n private router: Hono<HonoEnv>;\n private driver: DataDriver;\n private maxBulkRows: number;\n private listLimits: ListLimitOptions;\n\n private authAdapter?: AuthAdapter;\n\n constructor(\n collections: CollectionConfig[],\n driver: DataDriver,\n authAdapter?: AuthAdapter,\n maxBulkRows: number = DEFAULT_MAX_BULK_ROWS,\n listLimits: ListLimitOptions = {}\n ) {\n this.collections = collections;\n this.driver = driver;\n this.authAdapter = authAdapter;\n this.maxBulkRows = maxBulkRows;\n this.listLimits = {\n defaultLimit: listLimits.defaultLimit ?? DEFAULT_LIST_LIMIT,\n maxLimit: listLimits.maxLimit ?? MAX_LIST_LIMIT\n };\n this.router = new Hono<HonoEnv>();\n }\n\n /**\n * Built on first use rather than in the constructor: it probes the driver\n * for SQL support and creates a table, and most requests never send a key.\n */\n private idempotencyStore?: IdempotencyStore | null;\n private idempotency(): IdempotencyStore | undefined {\n this.idempotencyStore ??= createIdempotencyStore(this.driver) ?? null;\n return this.idempotencyStore ?? undefined;\n }\n\n /**\n * Parse request query params into QueryOptions, applying this generator's\n * list-pagination bounds (default page size + hard max limit) so no read\n * path can be tricked into buffering an entire table into memory.\n */\n private parseQuery(queryDict: Record<string, unknown>): QueryOptions {\n return parseQueryOptions(queryDict, this.listLimits);\n }\n\n\n\n /**\n * Generate REST routes using existing DataDriver\n */\n generateRoutes(): Hono<HonoEnv> {\n this.collections.forEach(collection => {\n this.createCollectionRoutes(collection);\n });\n\n // Catch-all routes for subcollection paths like\n // /authors/111094/posts and /authors/111094/posts/43\n // The DataDriver already knows how to resolve nested relation paths.\n this.createSubcollectionRoutes();\n\n return this.router;\n }\n\n /**\n * Check API key permissions for a collection operation.\n * Throws 403 if the key doesn't have the required permission.\n * No-ops if the request is not authenticated via an API key.\n */\n private enforceApiKeyPermission(\n c: { get: (key: string) => unknown; req: { method: string } },\n collectionSlug: string\n ): void {\n const apiKey = c.get(\"apiKey\") as ApiKeyMasked | undefined;\n if (!apiKey) return; // Not an API key request — skip\n\n const operation = httpMethodToOperation(c.req.method);\n if (!isOperationAllowed(apiKey.permissions, collectionSlug, operation)) {\n throw ApiError.forbidden(\n `API key does not have \"${operation}\" permission for collection \"${collectionSlug}\"`,\n \"API_KEY_FORBIDDEN\"\n );\n }\n }\n\n /**\n * API key permission check for nested paths. The operation targets the\n * LAST collection in the path (e.g. \"posts\" for /authors/1/posts), so\n * that is the slug the key must hold permission for — checking the\n * parent instead would let a key scoped to \"authors\" write \"posts\".\n * `parseSubPath` always yields a collectionPath ending in a collection\n * slug, never an id.\n */\n private enforceSubcollectionApiKeyPermission(\n c: { get: (key: string) => unknown; req: { method: string } },\n collectionPath: string\n ): void {\n this.enforceApiKeyPermission(c, collectionPath.split(\"/\").pop()!);\n }\n\n /**\n * The collection a nested path writes into — the target of the relation its\n * last segment names.\n *\n * Needed so a nested write can be checked against a schema at all. Without\n * it these routes skipped `assertKnownWriteFields` entirely, which is why a\n * typo `POST /posts` rejected with a 400 while the same typo on\n * `POST /authors/1/posts` reached the database.\n *\n * Returns `undefined` rather than throwing when the path cannot be walked:\n * the driver raises the authoritative error a moment later, and duplicating\n * it here would report a resolution failure as a validation failure.\n */\n private resolveNestedWriteCollection(collectionPath: string): CollectionConfig | undefined {\n const segments = collectionPath.split(\"/\").filter(s => s && s !== \"undefined\");\n let current = this.collections.find(c => c.slug === segments[0]);\n\n for (let i = 2; i < segments.length && current; i += 2) {\n const relation = findRelation(resolveCollectionRelations(current), segments[i]);\n if (!relation) return undefined;\n try {\n const target = relation.target();\n current = this.collections.find(c => c.slug === target?.slug) ?? target;\n } catch {\n return undefined;\n }\n }\n\n return current;\n }\n\n /**\n * Get the request-scoped driver. Throws if none is set — never falls\n * back to the unscoped `this.driver` to avoid bypassing RLS/auth.\n */\n private getScopedDriver(c: { get: (key: string) => unknown }): DataDriver {\n const driver = c.get(\"driver\") as DataDriver | undefined;\n if (!driver) throw ApiError.internal(\"Scoped driver not available\");\n return driver;\n }\n\n\n\n /**\n * Create REST routes for a collection using existing Rebase patterns\n */\n private createCollectionRoutes(collection: CollectionConfig): void {\n const basePath = `/${collection.slug}`;\n const resolvedCollection = collection;\n\n // GET /collection/count - Count entities (with optional filters)\n this.router.get(`${basePath}/count`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n const driver = this.getScopedDriver(c);\n\n const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);\n return c.json({ count: total });\n });\n\n // GET /collection - List entities\n this.router.get(basePath, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n\n const driver = this.getScopedDriver(c);\n const fetchService = driver.restFetchService;\n\n // Use include-aware path when available\n const entities = fetchService\n ? await fetchService.fetchCollectionForRest(\n collection.slug,\n {\n filter: queryOptions.where,\n // `?or=`/`?and=` were parsed and then dropped right here,\n // so a filtered read returned every row RLS allowed.\n logical: queryOptions.logical,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n orderBy: queryOptions.orderBy?.[0]?.field,\n order: queryOptions.orderBy?.[0]?.direction === \"desc\" ? \"desc\" : \"asc\",\n searchString,\n vectorSearch: queryOptions.vectorSearch\n },\n queryOptions.include\n )\n : await this.fetchRawCollection(driver, resolvedCollection, queryOptions, searchString);\n\n const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);\n\n return c.json({\n data: projectResponseFields(\n entities as Record<string, unknown>[],\n queryOptions.fields,\n resolvedCollection,\n { include: queryOptions.include }\n ),\n meta: {\n total,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n hasMore: (queryOptions.offset || 0) + entities.length < total\n }\n });\n });\n\n // GET /collection/:id - Get single entity\n this.router.get(`${basePath}/:id`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const id = c.req.param(\"id\");\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const driver = this.getScopedDriver(c);\n const fetchService = driver.restFetchService;\n\n // Use include-aware path when available\n const entity = fetchService\n ? await fetchService.fetchOneForRest(collection.slug, String(id), queryOptions.include)\n : await this.fetchRawEntity(driver, resolvedCollection, String(id));\n\n if (!entity) {\n throw ApiError.notFound(\"Entity not found\");\n }\n\n return c.json(projectResponseFields(\n [entity as Record<string, unknown>],\n queryOptions.fields,\n resolvedCollection,\n { include: queryOptions.include }\n )[0]);\n });\n\n // POST /collection/bulk - Write many rows as one transaction.\n //\n // Registered before POST /collection/:id-shaped routes so \"bulk\" is never\n // read as an id.\n this.router.post(`${basePath}/bulk`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const driver = this.getScopedDriver(c);\n const path = collection.slug;\n\n const body = await parseJsonBody(c) as { rows?: unknown; upsert?: unknown };\n\n if (!Array.isArray(body?.rows)) {\n throw ApiError.badRequest(\n \"Expected a JSON body of { rows: [...] }.\",\n \"INVALID_BULK_BODY\"\n );\n }\n if (body.rows.length === 0) {\n return c.json({ data: [], meta: { written: 0 } });\n }\n if (body.rows.some((row) => typeof row !== \"object\" || row === null || Array.isArray(row))) {\n throw ApiError.badRequest(\n \"Every entry in `rows` must be an object.\",\n \"INVALID_BULK_BODY\"\n );\n }\n if (body.upsert !== undefined && typeof body.upsert !== \"boolean\") {\n throw ApiError.badRequest(\"`upsert` must be a boolean.\", \"INVALID_BULK_BODY\");\n }\n\n const maxRows = this.maxBulkRows;\n if (body.rows.length > maxRows) {\n // A batch is one transaction, which holds locks for its whole\n // duration; an unbounded one is a self-inflicted outage. Say the\n // limit and the actual count so the caller can chunk to it.\n throw ApiError.badRequest(\n `Too many rows: ${body.rows.length} exceeds the ${maxRows}-row limit for a single bulk write. ` +\n `Send it in chunks of ${maxRows} or fewer.`,\n \"BULK_TOO_LARGE\"\n );\n }\n\n if (!driver.saveMany) {\n throw ApiError.badRequest(\n \"This collection's data source does not support bulk writes.\",\n \"BULK_UNSUPPORTED\"\n );\n }\n\n // Checked before the transaction opens, and named by row index: a\n // batch is all-or-nothing, so one bad field in ten thousand rows\n // should not be found by rolling the other 9,999 back.\n (body.rows as Record<string, unknown>[]).forEach((row, rowIndex) =>\n assertKnownWriteFields(row, resolvedCollection, { rowIndex }));\n\n const rows = await driver.saveMany({\n path,\n rows: body.rows as Record<string, unknown>[],\n collection: resolvedCollection,\n upsert: body.upsert === true\n });\n\n return c.json({\n data: rows.map((row) => this.formatResponse(row)),\n meta: { written: rows.length }\n });\n });\n\n // POST /collection - Create entity\n this.router.post(basePath, async (c) => {\n try {\n this.enforceApiKeyPermission(c, collection.slug);\n const driver = this.getScopedDriver(c);\n const path = collection.slug;\n\n\n const body = await parseJsonBody(c);\n\n const isAuth = collection.auth;\n const isAuthCollection = isAuth === true || (isAuth && typeof isAuth === \"object\" && isAuth.enabled === true);\n\n const collectionAuthConfig = typeof isAuth === \"object\" ? isAuth : undefined;\n\n // Auth signups carry credential fields (`password`, provider\n // bits) that the users collection does not declare as columns —\n // `prepareUserCreation` turns them into what the table has. The\n // adapter says which those are, so the body can still be checked\n // for everything else. Skipping the check outright (as this used\n // to) meant a typo on the users table was silently dropped and\n // answered 201, while the same typo on `posts` was a 400.\n if (!isAuthCollection) {\n assertKnownWriteFields(body, resolvedCollection);\n } else {\n const contract = this.authAdapter?.describeUserCreationContract?.(collectionAuthConfig);\n if (contract?.validate) {\n assertKnownWriteFields(body, resolvedCollection, {\n extraKnownFields: contract.extraFields\n });\n }\n }\n\n if (isAuthCollection && this.authAdapter?.prepareUserCreation) {\n const prepared = await this.authAdapter.prepareUserCreation(body, collectionAuthConfig);\n\n const entity = await driver.save({\n path,\n values: prepared.values,\n collection: resolvedCollection,\n status: \"new\"\n });\n\n const result = prepared.hookHandledEmail\n ? { temporaryPassword: prepared.clearPassword,\ninvitationSent: prepared.invitationSent }\n : this.authAdapter.finalizeUserCreation\n ? await this.authAdapter.finalizeUserCreation(\n // `driver.save` returns the flat row — the row IS the\n // values. Reading `entity.values` here (an Entity-era\n // leftover) handed the adapter `undefined`, whose\n // `.email` threw inside the invite-email try block —\n // reported as \"email delivery failed\", so no\n // invitation was ever sent.\n { id: entity.id as string,\nvalues: entity as Record<string, unknown> },\n prepared.clearPassword\n )\n : { invitationSent: false };\n\n const response = this.formatResponse(entity) as Record<string, unknown>;\n\n\n\n return c.json({\n ...response,\n invitationSent: result.invitationSent,\n ...(result.temporaryPassword ? { temporaryPassword: result.temporaryPassword } : {}),\n ...(\"emailDeliveryFailed\" in result && result.emailDeliveryFailed ? { emailDeliveryFailed: true } : {})\n }, 201);\n }\n\n // Deliberately not applied to the auth-signup branch above: that\n // response can carry a temporary password, and handing it out\n // again on a replayed key is a credential disclosure the plain\n // data path has no equivalent of.\n const idempotencyKey = c.req.header(IDEMPOTENCY_HEADER);\n const uid = (c.get(\"user\") as { uid?: string } | undefined)?.uid;\n const store = this.idempotency();\n if (idempotencyKey && store) {\n const already = await store.recall(idempotencyKey, uid);\n // `null` is a legitimate stored body, so presence is the\n // test — not truthiness.\n if (already !== undefined) return c.json(already as never, 201);\n }\n\n const entity = await driver.save({\n path,\n values: body,\n collection: resolvedCollection,\n status: \"new\"\n });\n\n const response = this.formatResponse(entity);\n\n if (idempotencyKey && store) {\n await store.remember(idempotencyKey, uid, response);\n }\n\n return c.json(response, 201);\n } catch (error) {\n if (isRebaseApiError(error) && !error.code) {\n // Only classify as BAD_REQUEST if it's an operational error\n // (e.g. validation, DB constraints). Runtime bugs like TypeError,\n // RangeError etc. should remain as 500 INTERNAL_ERROR.\n const isRuntimeBug = error instanceof TypeError\n || error instanceof RangeError\n || error instanceof SyntaxError\n || error instanceof ReferenceError;\n if (!isRuntimeBug) {\n error.code = \"BAD_REQUEST\";\n }\n }\n throw error;\n }\n });\n\n // PUT /collection/:id - Update entity\n this.router.put(`${basePath}/:id`, async (c) => {\n try {\n this.enforceApiKeyPermission(c, collection.slug);\n const id = c.req.param(\"id\");\n const driver = this.getScopedDriver(c);\n\n\n const existingEntity = await driver.fetchOne({\n path: getCollectionDataPath(collection),\n id: String(id),\n collection: resolvedCollection\n });\n\n if (!existingEntity) {\n throw ApiError.notFound(\"Entity not found\");\n }\n\n const body = await parseJsonBody(c);\n assertKnownWriteFields(body, resolvedCollection);\n\n const entity = await driver.save({\n path: getCollectionDataPath(collection),\n id: String(id),\n values: body,\n collection: resolvedCollection,\n status: \"existing\"\n });\n\n const response = this.formatResponse(entity);\n\n\n\n return c.json(response);\n } catch (error) {\n if (isRebaseApiError(error) && !error.code) {\n // Only classify as BAD_REQUEST if it's an operational error.\n // Runtime bugs (TypeError, RangeError, etc.) stay as 500.\n const isRuntimeBug = error instanceof TypeError\n || error instanceof RangeError\n || error instanceof SyntaxError\n || error instanceof ReferenceError;\n if (!isRuntimeBug) {\n error.code = \"BAD_REQUEST\";\n }\n }\n throw error;\n }\n });\n\n // DELETE /collection/:id - Delete entity\n this.router.delete(`${basePath}/:id`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const id = c.req.param(\"id\");\n const driver = this.getScopedDriver(c);\n\n\n const existingEntity = await driver.fetchOne({\n path: getCollectionDataPath(collection),\n id: String(id),\n collection: resolvedCollection\n });\n\n if (!existingEntity) {\n throw ApiError.notFound(\"Entity not found\");\n }\n\n await driver.delete({\n row: {\n // The address is the one in the URL, not something read back\n // off the row: a row is only its columns, so `existingEntity.id`\n // is undefined for any table not keyed on `id` — and the delete\n // went looking for a row called \"undefined\".\n id: String(id),\n path: getCollectionDataPath(collection),\n values: existingEntity\n },\n collection: resolvedCollection\n });\n\n\n\n return new Response(null, { status: 204 });\n });\n }\n\n /**\n * Catch-all routes for subcollection paths.\n *\n * Matches URL patterns like:\n * GET /authors/111094/posts → list child collection\n * GET /authors/111094/posts/43 → get child entity\n * POST /authors/111094/posts → create child entity\n * PUT /authors/111094/posts/43 → update child entity\n * DELETE /authors/111094/posts/43 → delete child entity\n *\n * The `:rest{.+}` regex param captures the full remainder of the URL\n * path (Hono v4 `*` wildcard does not populate `c.req.param(\"*\")`).\n * We split it into segments and reconstruct the `collectionPath`\n * (e.g. \"authors/111094/posts\") and optional `id` (e.g. \"43\").\n *\n * The DataDriver.save / fetchCollection / etc. already know how to\n * resolve multi-segment relation paths, so we just forward to them.\n */\n private createSubcollectionRoutes(): void {\n // Reserved path segments that should NOT be treated as relation names.\n // These are handled by dedicated route handlers (e.g., history routes)\n // mounted on the same data router.\n const RESERVED_SEGMENTS = new Set([\"history\"]);\n\n // Helper: parse a path like \"authors/111094/posts/43\" into\n // { collectionPath: \"authors/111094/posts\", id: \"43\" }\n // or \"authors/111094/posts\" into\n // { collectionPath: \"authors/111094/posts\", id: undefined }\n const parseSubPath = (rawPath: string): { collectionPath: string; id?: string } | null => {\n const segments = rawPath.split(\"/\").filter(Boolean);\n // A literal \"undefined\" segment is a client that interpolated a\n // variable it did not have. The whole-`rest` case is already refused\n // by the route guards above; this used to *drop* the segment, so\n // `/authors/123/undefined/posts` was quietly answered with the\n // contents of `/authors/123/posts`. Serving a path nobody asked for\n // is worse than refusing the one they did: the caller gets rows,\n // concludes the address it built was right, and the bug ships.\n if (segments.some(s => s === \"undefined\")) return null;\n // Need at least 3 segments for a subcollection path (parent/id/child)\n if (segments.length < 3) return null;\n\n // If any segment is a reserved path (e.g. \"history\"), this is not a\n // subcollection route — let it fall through to other handlers.\n if (segments.some(s => RESERVED_SEGMENTS.has(s))) return null;\n\n // Odd segment count → collection path (parent/id/child or parent/id/child/id2/grandchild)\n // Even segment count → entity path (parent/id/child/id)\n if (segments.length % 2 === 1) {\n return { collectionPath: segments.join(\"/\") };\n } else {\n const id = segments.pop()!;\n return { collectionPath: segments.join(\"/\"),\nid };\n }\n };\n\n // GET /<subcollection-path> — list or get single entity\n // Use :rest{.+} instead of * because Hono v4's wildcard doesn't\n // capture into c.req.param(\"*\") — it always returns undefined.\n this.router.get(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed) return next();\n\n const driver = this.getScopedDriver(c);\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n\n\n\n if (parsed.id === \"count\") {\n // GET /parent/:parentId/child/count — count child entities\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n\n const total = driver.count ? await driver.count({\n path: parsed.collectionPath,\n filter: queryOptions.where,\n searchString\n }) : 0;\n\n return c.json({ count: total });\n } else if (parsed.id) {\n // GET /parent/:parentId/child/:id — single entity\n const queryOptions = this.parseQuery(c.req.queries());\n const fetchService = driver.restFetchService;\n const entity = fetchService\n ? await fetchService.fetchOneForRest(parsed.collectionPath, parsed.id, queryOptions.include)\n : await driver.fetchOne({ path: parsed.collectionPath,\nid: parsed.id });\n if (!entity) throw ApiError.notFound(\"Entity not found\");\n\n return c.json(entity);\n } else {\n // GET /parent/:parentId/child — list entities.\n //\n // Same call the root list route makes. A child listing used to\n // be served by a second, thinner pipeline that accepted these\n // options and applied only `limit` — so `offset`, `orderBy` and\n // `include` were dropped without a word, and `total` counted\n // rows the filter would have excluded.\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n const fetchService = driver.restFetchService;\n const listOptions = {\n filter: queryOptions.where,\n // Same omission the comment above describes, one parameter\n // later: parsed, then dropped, so `?or=` widened the read.\n logical: queryOptions.logical,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n orderBy: queryOptions.orderBy?.[0]?.field,\n order: queryOptions.orderBy?.[0]?.direction === \"desc\" ? \"desc\" as const : \"asc\" as const,\n searchString\n };\n const entities = fetchService\n ? await fetchService.fetchCollectionForRest(parsed.collectionPath, listOptions, queryOptions.include)\n : await driver.fetchCollection({ path: parsed.collectionPath,\n...listOptions });\n\n const total = driver.count ? await driver.count({\n path: parsed.collectionPath,\n filter: queryOptions.where,\n logical: queryOptions.logical,\n searchString\n }) : entities.length;\n\n return c.json({\n data: entities,\n meta: {\n total,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n hasMore: (queryOptions.offset || 0) + entities.length < total\n }\n });\n }\n });\n\n // POST /<subcollection-path> — create entity\n this.router.post(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed || parsed.id) return next();\n\n const driver = this.getScopedDriver(c);\n\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n const body = await parseJsonBody(c);\n\n const targetCollection = this.resolveNestedWriteCollection(parsed.collectionPath);\n if (targetCollection) assertKnownWriteFields(body, targetCollection);\n\n const entity = await driver.save({\n path: parsed.collectionPath,\n values: body,\n status: \"new\"\n });\n\n const response = this.formatResponse(entity);\n\n\n\n return c.json(response, 201);\n });\n\n // PUT /<subcollection-path>/:id — update entity\n this.router.put(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed || !parsed.id) return next();\n\n const driver = this.getScopedDriver(c);\n\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n\n const body = await parseJsonBody(c);\n\n const targetCollection = this.resolveNestedWriteCollection(parsed.collectionPath);\n if (targetCollection) assertKnownWriteFields(body, targetCollection);\n\n const entity = await driver.save({\n path: parsed.collectionPath,\n id: parsed.id,\n values: body,\n status: \"existing\"\n });\n\n const response = this.formatResponse(entity);\n\n\n\n return c.json(response);\n });\n\n // DELETE /<subcollection-path>/:id — delete entity\n this.router.delete(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed || !parsed.id) return next();\n\n const driver = this.getScopedDriver(c);\n\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n\n const existingEntity = await driver.fetchOne({\n path: parsed.collectionPath,\n id: parsed.id\n });\n\n if (!existingEntity) throw ApiError.notFound(\"Entity not found\");\n\n await driver.delete({\n row: {\n // The address from the path, for the same reason as the\n // collection-level delete above: a row carries no id.\n id: parsed.id,\n path: parsed.collectionPath,\n values: existingEntity\n }\n });\n\n\n\n return new Response(null, { status: 204 });\n });\n }\n\n /**\n * Format successful API response\n */\n private formatResponse<T>(data: T, meta?: Record<string, unknown>): unknown {\n if (meta) {\n return {\n data,\n meta\n };\n }\n return data;\n }\n\n\n\n /**\n * Fetch raw collection data without Entity wrapper (fallback for non-Postgres)\n */\n private async fetchRawCollection(driver: DataDriver, collection: CollectionConfig, queryOptions: QueryOptions, searchString?: string) {\n const entities = await driver.fetchCollection({\n path: getCollectionDataPath(collection),\n collection,\n filter: queryOptions.where,\n // The fallback every driver without a `restFetchService` uses —\n // mongo, firebase, anything a developer registers. It dropped the\n // group exactly as the Postgres path did.\n logical: queryOptions.logical,\n limit: queryOptions.limit,\n orderBy: queryOptions.orderBy?.[0]?.field,\n order: queryOptions.orderBy?.[0]?.direction === \"desc\" ? \"desc\" : \"asc\",\n startAfter: queryOptions.offset ? String(queryOptions.offset) : undefined,\n searchString,\n vectorSearch: queryOptions.vectorSearch\n });\n\n return entities;\n }\n\n /**\n * Count raw entities for a collection\n */\n private async countRawEntities(driver: DataDriver, collection: CollectionConfig, queryOptions: QueryOptions, searchString?: string): Promise<number> {\n return driver.count ? await driver.count({\n path: getCollectionDataPath(collection),\n collection,\n filter: queryOptions.where,\n // Counted as well as fetched, or `total` describes a different set\n // of rows from the one that was served.\n logical: queryOptions.logical,\n searchString\n }) : 0;\n }\n\n /**\n * Fetch single entity raw data without Entity wrapper (fallback)\n */\n private async fetchRawEntity(driver: DataDriver, collection: CollectionConfig, id: string) {\n const entity = await driver.fetchOne({\n path: getCollectionDataPath(collection),\n id,\n collection\n });\n\n return entity ?? null;\n }\n\n\n}\n","// Zod 3 compat layer\nimport * as core from \"../core/index.js\";\n/** @deprecated Use the raw string literal codes instead, e.g. \"invalid_type\". */\nexport const ZodIssueCode = {\n invalid_type: \"invalid_type\",\n too_big: \"too_big\",\n too_small: \"too_small\",\n invalid_format: \"invalid_format\",\n not_multiple_of: \"not_multiple_of\",\n unrecognized_keys: \"unrecognized_keys\",\n invalid_union: \"invalid_union\",\n invalid_key: \"invalid_key\",\n invalid_element: \"invalid_element\",\n invalid_value: \"invalid_value\",\n custom: \"custom\",\n};\nexport { $brand, config } from \"../core/index.js\";\n/** @deprecated Use `z.config(params)` instead. */\nexport function setErrorMap(map) {\n core.config({\n customError: map,\n });\n}\n/** @deprecated Use `z.config()` instead. */\nexport function getErrorMap() {\n return core.config().customError;\n}\n/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */\nexport var ZodFirstPartyTypeKind;\n(function (ZodFirstPartyTypeKind) {\n})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));\n","import * as core from \"../core/index.js\";\nimport * as schemas from \"./schemas.js\";\nexport function string(params) {\n return core._coercedString(schemas.ZodString, params);\n}\nexport function number(params) {\n return core._coercedNumber(schemas.ZodNumber, params);\n}\nexport function boolean(params) {\n return core._coercedBoolean(schemas.ZodBoolean, params);\n}\nexport function bigint(params) {\n return core._coercedBigint(schemas.ZodBigInt, params);\n}\nexport function date(params) {\n return core._coercedDate(schemas.ZodDate, params);\n}\n","/**\n * Configure console log levels based on environment variable\n * Call this early in your application to set up proper logging levels\n */\nexport function configureLogLevel(logLevel?: string) {\n const LOG_LEVEL = logLevel || process.env.LOG_LEVEL || \"info\";\n const logLevels = { error: 0,\nwarn: 1,\ninfo: 2,\ndebug: 3 };\n const currentLevel = logLevels[LOG_LEVEL as keyof typeof logLevels] ?? 2;\n\n if (currentLevel < 3) console.debug = () => { };\n if (currentLevel < 2) console.log = () => { };\n if (currentLevel < 1) console.warn = () => { };\n if (currentLevel < 0) console.error = () => { };\n}\n\n/** Module-scoped backup of the original console methods. */\nlet originalConsole: Pick<Console, \"log\" | \"warn\" | \"error\" | \"debug\"> | undefined;\n\n/**\n * Reset console methods to their original state\n */\nexport function resetConsole() {\n // Store original methods if not already stored\n if (!originalConsole) {\n originalConsole = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n debug: console.debug\n };\n }\n\n console.log = originalConsole.log;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.debug = originalConsole.debug;\n}\n","import type { MiddlewareHandler } from \"hono\";\nimport { compress } from \"hono/compress\";\n\n/**\n * Response compression (gzip/deflate), negotiated from `Accept-Encoding`.\n *\n * Wraps Hono's `compress` with two corrections it does not make itself:\n *\n * - **`Vary: Accept-Encoding`** on every response it guards. Without it a shared\n * cache may hand a gzipped body to a client that asked for identity.\n * - **Range responses are left alone.** `Content-Range` describes offsets into\n * the identity body, so compressing a 206 desyncs the framing from the bytes\n * actually sent.\n *\n * No brotli: `CompressionStream` has no \"br\", so a br-only client would fall\n * back to identity — every real client sends gzip too.\n */\nexport function responseCompression(): MiddlewareHandler {\n const gzip = compress();\n\n return async (c, next) => {\n await next();\n\n const vary = c.res.headers.get(\"Vary\");\n if (!vary) {\n c.res.headers.set(\"Vary\", \"Accept-Encoding\");\n } else if (!/\\baccept-encoding\\b/i.test(vary)) {\n c.res.headers.append(\"Vary\", \"Accept-Encoding\");\n }\n\n if (c.res.status === 206 || c.res.headers.has(\"Content-Range\")) {\n return;\n }\n\n // The response is already built, so `compress` only needs to inspect and\n // re-wrap it — hence the no-op continuation.\n await gzip(c, async () => { /* already resolved */ });\n };\n}\n","/**\n * X-Request-ID Middleware for Hono.\n *\n * Generates a unique request identifier (UUID v4) for every inbound\n * request, or propagates an existing `X-Request-ID` header from the\n * caller. The ID is:\n *\n * 1. Stored in the Hono context (`c.get(\"requestId\")`)\n * 2. Echoed back on the response as `X-Request-ID`\n *\n * Downstream middleware and handlers (request logger, error handler,\n * etc.) read the ID from context to include it in log entries and\n * error responses, enabling end-to-end request tracing across services.\n *\n * @example\n * ```ts\n * import { requestId } from \"@rebasepro/server\";\n * app.use(\"/*\", requestId());\n * ```\n */\nimport { randomUUID } from \"node:crypto\";\nimport type { MiddlewareHandler } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\n\nexport const REQUEST_ID_HEADER = \"X-Request-ID\";\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function requestId(): MiddlewareHandler<HonoEnv> {\n return async (c, next) => {\n const incoming = c.req.header(REQUEST_ID_HEADER);\n const id = incoming && UUID_RE.test(incoming) ? incoming : randomUUID();\n\n c.set(\"requestId\", id);\n\n await next();\n\n c.header(REQUEST_ID_HEADER, id);\n };\n}\n","/**\n * Structured HTTP request logging middleware for Hono.\n *\n * Logs every request with method, path, status code, latency, and\n * content-length. In production, outputs JSON for Cloud Logging; in\n * development, emits a coloured one-liner.\n *\n * @example\n * ```ts\n * import { requestLogger } from \"@rebasepro/server\";\n * app.use(\"/*\", requestLogger());\n * ```\n */\nimport type { MiddlewareHandler } from \"hono\";\nimport { logger as log } from \"./logger\";\n\nexport interface RequestLoggerOptions {\n /** Paths to skip logging (e.g. \"/health\"). Supports exact match. */\n skip?: string[];\n}\n\nexport function requestLogger(options?: RequestLoggerOptions): MiddlewareHandler {\n const skipPaths = new Set(options?.skip ?? [\"/health\", \"/favicon.ico\"]);\n\n return async (c, next) => {\n const start = performance.now();\n const method = c.req.method;\n const path = c.req.path;\n\n // Skip noisy endpoints\n if (skipPaths.has(path)) {\n return next();\n }\n\n await next();\n\n const latencyMs = Math.round(performance.now() - start);\n const status = c.res.status;\n const contentLength = c.res.headers.get(\"content-length\");\n\n const data: Record<string, unknown> = {\n method,\n path,\n status,\n latencyMs\n };\n\n // Include request correlation ID if available\n const reqId = c.get(\"requestId\");\n if (reqId) {\n data.requestId = reqId;\n }\n\n if (contentLength) {\n data.contentLength = parseInt(contentLength, 10);\n }\n\n // Extract the user id from context if auth middleware ran.\n //\n // This read `c.get(\"uid\")` — a context key nothing has ever set, so\n // no request log has ever carried a user. The auth middlewares all set\n // `user`; the id lives on it.\n const uid = (c.get(\"user\") as { uid?: string } | undefined)?.uid;\n if (uid) {\n data.uid = uid;\n }\n\n if (status >= 500) {\n log.error(\"request\", data);\n } else if (status >= 400) {\n log.warn(\"request\", data);\n } else {\n log.info(\"request\", data);\n }\n };\n}\n","import { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { csrf } from \"hono/csrf\";\nimport { HonoEnv } from \"../api/types\";\nimport { responseCompression } from \"../utils/compression\";\nimport { requestId } from \"../utils/request-id\";\nimport { requestLogger } from \"../utils/request-logger\";\nimport { logger } from \"../utils/logger\";\nimport { logMiddleware } from \"../api/logs-routes\";\n\ninterface MiddlewareConfig {\n maxBodySize?: number;\n compression?: boolean;\n /**\n * The caller already installed a CORS middleware.\n *\n * The framework does not install one itself, so it warns when it sees no\n * sign of an origin policy. The bundle runtime always installs one, and a\n * warning that is wrong in the common case is worse than no warning — it\n * teaches people to skim past the ones that matter.\n */\n corsHandled?: boolean;\n csrf?: {\n origin: string | string[] | ((origin: string) => boolean);\n };\n}\n\nexport function configureMiddlewares(\n app: Hono<HonoEnv>,\n basePath: string,\n isProduction: boolean,\n config: MiddlewareConfig\n): void {\n // Request ID (correlation)\n app.use(`${basePath}/*`, requestId());\n\n // Response Compression — registered early so it wraps the final response of\n // every downstream handler, including error responses.\n //\n // Hono's `threshold` is deliberately not plumbed through: it only applies to\n // responses declaring a Content-Length, and `c.json()` sets none, so it\n // would silently do nothing on the very responses this exists to shrink.\n if (config.compression !== false) {\n app.use(`${basePath}/*`, responseCompression());\n logger.info(\"Response compression enabled\");\n }\n\n // Request Body Size Limit\n const maxBodySize = config.maxBodySize ?? 10 * 1024 * 1024; // 10MB default\n if (maxBodySize > 0) {\n app.use(`${basePath}/*`, bodyLimit({\n maxSize: maxBodySize,\n onError: (c) => {\n return c.json({\n error: {\n message: `Request body too large. Maximum size is ${Math.round(maxBodySize / 1024 / 1024)}MB.`,\n code: \"PAYLOAD_TOO_LARGE\"\n }\n }, 413);\n }\n }));\n logger.info(\"Request body limit configured\", { maxSizeMB: Math.round(maxBodySize / 1024 / 1024) });\n }\n\n // CSRF Protection (opt-in)\n if (config.csrf?.origin) {\n app.use(`${basePath}/*`, csrf({\n origin: config.csrf.origin\n }));\n logger.info(\"CSRF protection enabled\");\n }\n\n // CORS Warning. The framework does not install a CORS middleware itself —\n // that belongs to the app (the scaffolded template adds `hono/cors`). A\n // backend wired up by hand can therefore end up with no origin restriction\n // at all, which is most dangerous in production, so warn there too rather\n // than only in development.\n if (!config.corsHandled && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) {\n logger.warn(\n (isProduction ? \"[PRODUCTION] \" : \"\") +\n \"No CORS configuration detected (CORS_ORIGINS / FRONTEND_URL not set). \" +\n \"If your app does not install its own CORS middleware, the API may accept \" +\n \"requests from any origin. Set CORS_ORIGINS to restrict access.\"\n );\n }\n\n // Request Logging\n app.use(`${basePath}/*`, requestLogger());\n\n // Record requests into the in-memory ring buffer that backs the Studio's\n // Logs Explorer. This is a separate sink from `requestLogger` above, which\n // writes to stdout — both observe every request, neither duplicates the other.\n app.use(`${basePath}/*`, logMiddleware());\n}\n","/**\n * Local filesystem storage controller\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { promisify } from \"util\";\nimport {\n StorageController,\n LocalStorageConfig,\n DEFAULT_MAX_FILE_SIZE\n} from \"./types\";\nimport {\n UploadFileProps,\n UploadFileResult,\n DownloadConfig,\n DownloadMetadata,\n StorageListResult,\n StorageReference\n} from \"@rebasepro/types\";\n\nconst mkdir = promisify(fs.mkdir);\nconst writeFile = promisify(fs.writeFile);\nconst readFile = promisify(fs.readFile);\nconst unlink = promisify(fs.unlink);\nconst readdir = promisify(fs.readdir);\nconst stat = promisify(fs.stat);\nconst access = promisify(fs.access);\n\n/**\n * Bucket used when a call names none.\n *\n * Every method resolves through this, so put/get/delete/list agree on where a\n * bare key lives.\n */\nexport const DEFAULT_BUCKET = \"default\";\n\n/**\n * Remove initial and trailing slashes from a path.\n * Handles paths like \"/images/\", \"images/\", \"/images\" → \"images\"\n */\nfunction normalizeStoragePath(s: string): string {\n let result = s;\n while (result.startsWith(\"/\")) {\n result = result.slice(1);\n }\n while (result.endsWith(\"/\")) {\n result = result.slice(0, -1);\n }\n return result;\n}\n\n/**\n * Local filesystem storage implementation\n * Stores files in a directory structure: {basePath}/{bucket}/{path}\n */\nexport class LocalStorageController implements StorageController {\n private config: LocalStorageConfig;\n private basePath: string;\n\n constructor(config: LocalStorageConfig) {\n this.config = config;\n this.basePath = path.resolve(config.basePath);\n }\n\n getType(): \"local\" {\n return \"local\";\n }\n\n /**\n * Ensure directory exists, creating it if necessary\n */\n private async ensureDir(dirPath: string): Promise<void> {\n try {\n await mkdir(dirPath, { recursive: true });\n } catch (error: unknown) {\n if (error instanceof Error && (error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n }\n\n /**\n * Get the full filesystem path for a storage path, with a traversal guard\n * that keeps the result inside the bucket directory.\n *\n * Defaults the bucket the way `putObject` does.\n *\n * `putObject` has always written into `default` when given no bucket, while\n * the read side resolved a bare key against the storage root — where\n * nothing is. The two disagreed silently: `getObject` returned null (reads\n * as \"file missing\"), `deleteObject` deleted nothing (404s are swallowed by\n * design), and `listObjects` returned an empty page. So the obvious\n * `putObject({ key })` → `getObject(key)` did not round-trip and nothing\n * said why. One default, applied everywhere, removes the whole class.\n */\n private getFullPath(storagePath: string, bucket?: string): string {\n const bucketPath = path.join(this.basePath, bucket ?? DEFAULT_BUCKET);\n const resolved = path.resolve(path.join(bucketPath, storagePath));\n if (!resolved.startsWith(bucketPath + path.sep) && resolved !== bucketPath) {\n throw new Error(\"Path traversal detected: resolved storage path is outside the bucket directory.\");\n }\n return resolved;\n }\n\n /**\n * Validate file before upload\n */\n private validateFile(file: File): void {\n const maxSize = this.config.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > maxSize) {\n throw new Error(`File size ${file.size} exceeds maximum allowed size ${maxSize}`);\n }\n\n if (this.config.allowedMimeTypes && this.config.allowedMimeTypes.length > 0) {\n if (!this.config.allowedMimeTypes.includes(file.type)) {\n throw new Error(`File type ${file.type} is not allowed. Allowed types: ${this.config.allowedMimeTypes.join(\", \")}`);\n }\n }\n }\n\n async putObject({\n file,\n key,\n metadata,\n bucket\n }: UploadFileProps): Promise<UploadFileResult> {\n this.validateFile(file);\n\n // Always use a bucket (default to 'default')\n const usedBucket = bucket ?? DEFAULT_BUCKET;\n const fullStoragePath = key;\n const fullPath = this.getFullPath(fullStoragePath, usedBucket);\n\n // Ensure parent directory exists\n await this.ensureDir(path.dirname(fullPath));\n\n // Convert File to Buffer and write\n const arrayBuffer = await file.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n await writeFile(fullPath, buffer);\n\n // Always save metadata file with at least contentType (required for preview)\n const metadataPath = `${fullPath}.metadata.json`;\n await writeFile(metadataPath, JSON.stringify({\n ...(metadata || {}),\n contentType: file.type,\n size: file.size,\n uploadedAt: new Date().toISOString()\n }, null, 2));\n\n return {\n key: fullStoragePath,\n bucket: usedBucket,\n storageUrl: `local://${usedBucket}/${fullStoragePath}`\n };\n }\n\n async getSignedUrl(key: string, bucket?: string): Promise<DownloadConfig> {\n // Handle local:// URLs\n let resolvedPath = key;\n let resolvedBucket = bucket;\n\n if (key.startsWith(\"local://\")) {\n const withoutProtocol = key.substring(\"local://\".length);\n const firstSlash = withoutProtocol.indexOf(\"/\");\n if (firstSlash > 0) {\n resolvedBucket = withoutProtocol.substring(0, firstSlash);\n resolvedPath = withoutProtocol.substring(firstSlash + 1);\n }\n }\n\n // Normalize path to handle leading/trailing slashes\n resolvedPath = normalizeStoragePath(resolvedPath);\n const fullPath = this.getFullPath(resolvedPath, resolvedBucket);\n\n try {\n await access(fullPath, fs.constants.R_OK);\n } catch {\n return {\n url: null,\n fileNotFound: true\n };\n }\n\n // Read metadata if available\n let metadata: DownloadMetadata | undefined;\n const metadataPath = `${fullPath}.metadata.json`;\n try {\n const metadataContent = await readFile(metadataPath, \"utf-8\");\n const savedMetadata = JSON.parse(metadataContent);\n const fileStat = await stat(fullPath);\n\n metadata = {\n bucket: resolvedBucket ?? DEFAULT_BUCKET,\n fullPath: resolvedPath,\n name: path.basename(resolvedPath),\n size: fileStat.size,\n contentType: savedMetadata.contentType || \"application/octet-stream\",\n customMetadata: savedMetadata\n };\n } catch {\n // No metadata file, create basic metadata from stat\n try {\n const fileStat = await stat(fullPath);\n metadata = {\n bucket: resolvedBucket ?? DEFAULT_BUCKET,\n fullPath: resolvedPath,\n name: path.basename(resolvedPath),\n size: fileStat.size,\n contentType: \"application/octet-stream\",\n customMetadata: {}\n };\n } catch {\n // Stat failed\n }\n }\n\n // Return a relative URL that will be served by the storage routes\n const bucketPath = resolvedBucket ? `${resolvedBucket}/` : \"\";\n const url = `/api/storage/file/${bucketPath}${resolvedPath}`;\n\n return {\n url,\n metadata\n };\n }\n\n async getObject(key: string, bucket?: string): Promise<File | null> {\n // Handle local:// URLs\n let resolvedPath = key;\n let resolvedBucket = bucket;\n\n if (key.startsWith(\"local://\")) {\n const withoutProtocol = key.substring(\"local://\".length);\n const firstSlash = withoutProtocol.indexOf(\"/\");\n if (firstSlash > 0) {\n resolvedBucket = withoutProtocol.substring(0, firstSlash);\n resolvedPath = withoutProtocol.substring(firstSlash + 1);\n }\n }\n\n // Normalize path to handle leading/trailing slashes\n resolvedPath = normalizeStoragePath(resolvedPath);\n const fullPath = this.getFullPath(resolvedPath, resolvedBucket);\n\n try {\n await access(fullPath, fs.constants.R_OK);\n const buffer = await readFile(fullPath);\n\n // Try to get content type from metadata\n let contentType = \"application/octet-stream\";\n try {\n const metadataPath = `${fullPath}.metadata.json`;\n const metadataContent = await readFile(metadataPath, \"utf-8\");\n const metadata = JSON.parse(metadataContent);\n contentType = metadata.contentType || contentType;\n } catch {\n // No metadata, use default content type\n }\n\n const blob = new Blob([buffer], { type: contentType });\n return new File([blob], path.basename(resolvedPath), { type: contentType });\n } catch {\n return null;\n }\n }\n\n async deleteObject(key: string, bucket?: string): Promise<void> {\n // Handle local:// URLs\n let resolvedPath = key;\n let resolvedBucket = bucket;\n\n if (key.startsWith(\"local://\")) {\n const withoutProtocol = key.substring(\"local://\".length);\n const firstSlash = withoutProtocol.indexOf(\"/\");\n if (firstSlash > 0) {\n resolvedBucket = withoutProtocol.substring(0, firstSlash);\n resolvedPath = withoutProtocol.substring(firstSlash + 1);\n }\n }\n\n // Normalize path to handle leading/trailing slashes\n resolvedPath = normalizeStoragePath(resolvedPath);\n\n if (!resolvedPath) {\n // Safety: never delete the bucket root\n return;\n }\n\n const fullPath = this.getFullPath(resolvedPath, resolvedBucket);\n\n // Check if path exists before attempting to delete\n try {\n await access(fullPath, fs.constants.F_OK);\n } catch {\n // File doesn't exist — nothing to delete\n return;\n }\n\n try {\n const stats = await stat(fullPath);\n if (stats.isDirectory()) {\n // Only remove if empty — client must delete contents first\n await fs.promises.rmdir(fullPath);\n } else {\n await unlink(fullPath);\n // Also delete metadata file if exists\n try {\n await unlink(`${fullPath}.metadata.json`);\n } catch {\n // Metadata file might not exist\n }\n }\n } catch (error: unknown) {\n if (error instanceof Error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"ENOTEMPTY\") {\n // File doesn't exist or directory not empty — ignore\n return;\n }\n }\n throw error;\n }\n }\n\n async listObjects(prefix: string, options?: {\n bucket?: string;\n maxResults?: number;\n pageToken?: string;\n }): Promise<StorageListResult> {\n // Normalize path to handle leading/trailing slashes\n const normalizedPath = normalizeStoragePath(prefix);\n const fullPath = this.getFullPath(normalizedPath, options?.bucket);\n const items: StorageReference[] = [];\n const prefixes: StorageReference[] = [];\n\n try {\n await access(fullPath, fs.constants.R_OK);\n const entries = await readdir(fullPath, { withFileTypes: true });\n\n let count = 0;\n const maxResults = options?.maxResults ?? 1000;\n const startIndex = options?.pageToken ? parseInt(options.pageToken, 10) : 0;\n // Cursor over `entries`, not over emitted results. Every stored\n // object has a `.metadata.json` sidecar that is skipped without\n // emitting anything, so a token derived from `count` could fail to\n // advance — a page of nothing but sidecars handed back the token it\n // was called with, and `while (pageToken)` never terminated.\n let scanned = startIndex;\n\n for (let i = startIndex; i < entries.length && count < maxResults; i++) {\n const entry = entries[i];\n scanned = i + 1;\n\n // Skip metadata files\n if (entry.name.endsWith(\".metadata.json\")) {\n continue;\n }\n\n const entryPath = prefix ? `${prefix}/${entry.name}` : entry.name;\n const bucket = options?.bucket ?? DEFAULT_BUCKET;\n\n const ref: StorageReference = {\n bucket,\n fullPath: entryPath,\n name: entry.name,\n parent: null as never, // Simplified - not fully implementing parent chain\n root: null as never,\n toString: () => `local://${bucket}/${entryPath}`\n };\n\n if (entry.isDirectory()) {\n prefixes.push(ref);\n } else {\n items.push(ref);\n }\n count++;\n }\n\n const nextPageToken = scanned < entries.length ? String(scanned) : undefined;\n\n return {\n items,\n prefixes,\n nextPageToken\n };\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { items: [],\nprefixes: [] };\n }\n throw error;\n }\n }\n\n /**\n * Get the absolute filesystem path for serving files\n * Used by the storage routes to serve files directly\n */\n getAbsolutePath(key: string, bucket?: string): string {\n return this.getFullPath(key, bucket);\n }\n\n /**\n * Get the base path for the storage\n */\n getBasePath(): string {\n return this.basePath;\n }\n}\n","/**\n * Image Transformation Service\n *\n * Provides on-the-fly image resize, crop, format conversion, and quality\n * adjustment using the `sharp` library. Results are cached in an LRU\n * in-memory cache to avoid redundant processing.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet sharpFactory: ((input: Buffer | Uint8Array) => any) | undefined;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function getSharp(): Promise<(input: Buffer | Uint8Array) => any> {\n if (!sharpFactory) {\n try {\n const mod = await import(\"sharp\");\n sharpFactory = mod.default;\n } catch (err) {\n throw new Error(\"Failed to load optional 'sharp' dependency for image transformation.\");\n }\n }\n if (!sharpFactory) {\n throw new Error(\"Failed to load optional 'sharp' dependency for image transformation.\");\n }\n return sharpFactory;\n}\n\n/** Options that can be specified via query parameters. */\nexport interface ImageTransformOptions {\n width?: number;\n height?: number;\n quality?: number;\n format?: \"webp\" | \"avif\" | \"jpeg\" | \"png\";\n fit?: \"cover\" | \"contain\" | \"fill\" | \"inside\" | \"outside\";\n}\n\n/** Maximum dimension allowed (prevents abuse). */\nconst MAX_DIMENSION = 4096;\n/** Maximum quality value. */\nconst MAX_QUALITY = 100;\n/** Minimum quality value. */\nconst MIN_QUALITY = 1;\n\nconst VALID_FORMATS = new Set([\"webp\", \"avif\", \"jpeg\", \"png\"]);\nconst VALID_FITS = new Set([\"cover\", \"contain\", \"fill\", \"inside\", \"outside\"]);\n\n/**\n * Parse transform options from URL query parameters.\n * Returns `null` when no transformation is requested.\n */\nexport function parseTransformOptions(query: Record<string, string>): ImageTransformOptions | null {\n const opts: ImageTransformOptions = {};\n let hasTransform = false;\n\n if (query.width) {\n const w = parseInt(query.width, 10);\n if (!Number.isNaN(w) && w > 0) {\n opts.width = Math.min(w, MAX_DIMENSION);\n hasTransform = true;\n }\n }\n\n if (query.height) {\n const h = parseInt(query.height, 10);\n if (!Number.isNaN(h) && h > 0) {\n opts.height = Math.min(h, MAX_DIMENSION);\n hasTransform = true;\n }\n }\n\n if (query.quality) {\n const q = parseInt(query.quality, 10);\n if (!Number.isNaN(q)) {\n opts.quality = Math.min(Math.max(q, MIN_QUALITY), MAX_QUALITY);\n hasTransform = true;\n }\n }\n\n if (query.format && VALID_FORMATS.has(query.format)) {\n opts.format = query.format as ImageTransformOptions[\"format\"];\n hasTransform = true;\n }\n\n if (query.fit && VALID_FITS.has(query.fit)) {\n opts.fit = query.fit as ImageTransformOptions[\"fit\"];\n hasTransform = true;\n }\n\n return hasTransform ? opts : null;\n}\n\n/** MIME types that can be used as a Content-Type header. */\nconst FORMAT_CONTENT_TYPES: Record<string, string> = {\n webp: \"image/webp\",\n avif: \"image/avif\",\n jpeg: \"image/jpeg\",\n png: \"image/png\"\n};\n\n/** Check whether a content type is a transformable image. */\nexport function isTransformableImage(contentType: string): boolean {\n return (\n contentType.startsWith(\"image/\") &&\n !contentType.includes(\"svg\") &&\n !contentType.includes(\"gif\")\n );\n}\n\n/**\n * Apply image transformations and return the result buffer + content type.\n */\nexport async function transformImage(\n buffer: Buffer | Uint8Array,\n options: ImageTransformOptions\n): Promise<{ data: Buffer; contentType: string }> {\n const sharp = await getSharp();\n let pipeline = sharp(buffer);\n\n if (options.width || options.height) {\n pipeline = pipeline.resize({\n width: options.width,\n height: options.height,\n fit: options.fit || \"cover\",\n withoutEnlargement: true\n });\n }\n\n const format = options.format || \"webp\";\n const quality = options.quality || 80;\n\n switch (format) {\n case \"webp\":\n pipeline = pipeline.webp({ quality });\n break;\n case \"avif\":\n pipeline = pipeline.avif({ quality });\n break;\n case \"jpeg\":\n pipeline = pipeline.jpeg({ quality });\n break;\n case \"png\":\n pipeline = pipeline.png({ quality });\n break;\n }\n\n const data = await pipeline.toBuffer();\n return { data,\ncontentType: FORMAT_CONTENT_TYPES[format] };\n}\n\n// ---------------------------------------------------------------------------\n// LRU Transform Cache\n// ---------------------------------------------------------------------------\n\ninterface CacheEntry {\n data: Buffer;\n contentType: string;\n timestamp: number;\n}\n\n/**\n * Simple LRU cache for transformed images.\n *\n * Entries expire after `maxAgeMs` (default: 1 hour) and the cache\n * evicts the oldest entry when `maxEntries` is exceeded.\n */\nexport class TransformCache {\n private cache = new Map<string, CacheEntry>();\n private readonly maxEntries: number;\n private readonly maxAgeMs: number;\n private readonly maxTotalBytes: number;\n private totalBytes = 0;\n\n constructor(maxEntries = 500, maxAgeMs = 3_600_000, maxTotalBytes = 256 * 1024 * 1024) {\n this.maxEntries = maxEntries;\n this.maxAgeMs = maxAgeMs;\n this.maxTotalBytes = maxTotalBytes;\n }\n\n /** Build a deterministic cache key from file key + transform options. */\n buildKey(fileKey: string, options: ImageTransformOptions): string {\n return `${fileKey}::${JSON.stringify(options)}`;\n }\n\n get(cacheKey: string): { data: Buffer; contentType: string } | null {\n const entry = this.cache.get(cacheKey);\n if (!entry) return null;\n if (Date.now() - entry.timestamp > this.maxAgeMs) {\n this.totalBytes -= entry.data.length;\n this.cache.delete(cacheKey);\n return null;\n }\n // Move to end (most recently used)\n this.cache.delete(cacheKey);\n this.cache.set(cacheKey, entry);\n return { data: entry.data,\ncontentType: entry.contentType };\n }\n\n set(cacheKey: string, data: Buffer, contentType: string): void {\n // Evict oldest entries while over capacity (entry count or total bytes)\n while (\n (this.cache.size >= this.maxEntries || this.totalBytes + data.length > this.maxTotalBytes)\n && this.cache.size > 0\n ) {\n const oldest = this.cache.keys().next().value;\n if (oldest !== undefined) {\n const evicted = this.cache.get(oldest);\n if (evicted) this.totalBytes -= evicted.data.length;\n this.cache.delete(oldest);\n }\n }\n this.totalBytes += data.length;\n this.cache.set(cacheKey, { data,\ncontentType,\ntimestamp: Date.now() });\n }\n}\n","/**\n * TUS Protocol Handler\n *\n * Implements the TUS v1.0.0 resumable upload protocol with the\n * Creation and Termination extensions. Uploads are stored in a\n * temporary directory and moved to final storage on completion.\n *\n * @see https://tus.io/protocols/resumable-upload\n */\n\nimport { randomUUID } from \"crypto\";\nimport { writeFile, unlink, stat, mkdir, open } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport type { Context } from \"hono\";\nimport type { StorageController } from \"./types\";\nimport type { StorageRegistry } from \"./storage-registry\";\nimport { logger } from \"../utils/logger.js\";\nimport { ApiError } from \"../api/errors\";\n\n/** Metadata for an in-progress resumable upload. */\ninterface TusUpload {\n id: string;\n /** Total declared size in bytes. */\n size: number;\n /** Bytes received so far. */\n offset: number;\n /** TUS metadata parsed from the creation request. */\n metadata: Record<string, string>;\n /** Timestamp of creation (epoch ms). */\n createdAt: number;\n /** Absolute path to the temp file on disk. */\n filePath: string;\n /** Target bucket (from metadata). */\n bucket?: string;\n /** Target key / filename (from metadata). */\n key?: string;\n /** Whether the upload has been fully received and finalized. */\n completed: boolean;\n}\n\n/** Maximum upload size: 5 GB. */\nconst MAX_UPLOAD_SIZE = 5 * 1024 * 1024 * 1024;\n\n/** Stale upload expiry: 24 hours. */\nconst UPLOAD_EXPIRY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * TUS resumable upload handler.\n *\n * Each instance manages uploads for a single storage root. The\n * `storageController` is used to finalize completed uploads by\n * calling `putObject`.\n */\nexport class TusHandler {\n private uploads = new Map<string, TusUpload>();\n private tusDir: string;\n private cleanupTimer?: ReturnType<typeof setInterval>;\n\n constructor(\n storageBaseDir: string,\n private storageController?: StorageController,\n private storageRegistry?: StorageRegistry,\n /**\n * Per-object authorization, applied to the resumable path too.\n *\n * TUS is a second way to write an object, so a hook enforced only on\n * `POST /upload` would leave the door it was added to close standing\n * open. The target key lives in the `Upload-Metadata` header, which\n * only this class parses — hence the injection rather than a check in\n * the route. Rejects by throwing.\n */\n private authorizeUpload?: (c: Context, key: string, bucket: string) => Promise<void>\n ) {\n this.tusDir = join(storageBaseDir, \".tus-uploads\");\n }\n\n /** Ensure the temp directory exists. */\n private async ensureDir(): Promise<void> {\n if (!existsSync(this.tusDir)) {\n await mkdir(this.tusDir, { recursive: true });\n }\n }\n\n /** Start periodic cleanup of stale uploads. */\n startCleanup(): void {\n if (this.cleanupTimer) return;\n this.cleanupTimer = setInterval(() => {\n void this.cleanupStale();\n }, 60_000); // every minute\n }\n\n /** Remove uploads that have been idle for longer than UPLOAD_EXPIRY_MS. */\n private async cleanupStale(): Promise<void> {\n const now = Date.now();\n for (const [id, upload] of this.uploads) {\n if (now - upload.createdAt > UPLOAD_EXPIRY_MS && !upload.completed) {\n try { await unlink(upload.filePath); } catch { /* ok */ }\n this.uploads.delete(id);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // TUS Metadata Parsing\n // -----------------------------------------------------------------------\n\n /**\n * Parse the `Upload-Metadata` header.\n *\n * Format: `key base64value,key2 base64value2`\n */\n private parseMetadata(header: string): Record<string, string> {\n const metadata: Record<string, string> = {};\n if (!header) return metadata;\n for (const pair of header.split(\",\")) {\n const trimmed = pair.trim();\n const spaceIdx = trimmed.indexOf(\" \");\n if (spaceIdx === -1) {\n metadata[trimmed] = \"\";\n } else {\n const key = trimmed.substring(0, spaceIdx);\n const value = Buffer.from(trimmed.substring(spaceIdx + 1), \"base64\").toString(\"utf-8\");\n metadata[key] = value;\n }\n }\n return metadata;\n }\n\n // -----------------------------------------------------------------------\n // Protocol Endpoints\n // -----------------------------------------------------------------------\n\n /** `OPTIONS /tus` — TUS capability discovery. */\n options(): Response {\n return new Response(null, {\n status: 204,\n headers: {\n \"Tus-Resumable\": \"1.0.0\",\n \"Tus-Version\": \"1.0.0\",\n \"Tus-Extension\": \"creation,termination\",\n \"Tus-Max-Size\": String(MAX_UPLOAD_SIZE)\n }\n });\n }\n\n /** `POST /tus` — Create a new upload. */\n async create(c: Context): Promise<Response> {\n await this.ensureDir();\n\n const uploadLengthHeader = c.req.header(\"Upload-Length\");\n if (!uploadLengthHeader) {\n throw ApiError.badRequest(\"Upload-Length header is required\");\n }\n\n const uploadLength = parseInt(uploadLengthHeader, 10);\n if (Number.isNaN(uploadLength) || uploadLength <= 0) {\n throw ApiError.badRequest(\"Invalid Upload-Length\");\n }\n if (uploadLength > MAX_UPLOAD_SIZE) {\n throw new ApiError(413, \"PAYLOAD_TOO_LARGE\", `Upload-Length exceeds maximum of ${MAX_UPLOAD_SIZE} bytes`);\n }\n\n const metadata = this.parseMetadata(c.req.header(\"Upload-Metadata\") || \"\");\n\n // Gate before any temp file exists, so a denied upload leaves nothing\n // behind to resume.\n if (this.authorizeUpload) {\n const key = metadata.key || metadata.filename || \"\";\n await this.authorizeUpload(c, key, metadata.bucket || \"default\");\n }\n\n const id = randomUUID();\n const filePath = join(this.tusDir, id);\n\n // Create empty temp file\n await writeFile(filePath, Buffer.alloc(0));\n\n const upload: TusUpload = {\n id,\n size: uploadLength,\n offset: 0,\n metadata,\n createdAt: Date.now(),\n filePath,\n bucket: metadata.bucket || undefined,\n key: metadata.key || metadata.filename || undefined,\n completed: false\n };\n this.uploads.set(id, upload);\n\n // Build absolute Location\n const reqUrl = new URL(c.req.url);\n const location = `${reqUrl.origin}${reqUrl.pathname}/${id}`;\n\n return new Response(null, {\n status: 201,\n headers: {\n Location: location,\n \"Tus-Resumable\": \"1.0.0\",\n \"Upload-Offset\": \"0\"\n }\n });\n }\n\n /** `HEAD /tus/:id` — Query upload progress. */\n head(c: Context, id: string): Response {\n const upload = this.uploads.get(id);\n if (!upload) {\n throw ApiError.notFound(\"Upload not found\");\n }\n\n return new Response(null, {\n status: 200,\n headers: {\n \"Tus-Resumable\": \"1.0.0\",\n \"Upload-Offset\": String(upload.offset),\n \"Upload-Length\": String(upload.size),\n \"Cache-Control\": \"no-store\"\n }\n });\n }\n\n /** `PATCH /tus/:id` — Append data to an upload. */\n async patch(c: Context, id: string): Promise<Response> {\n const upload = this.uploads.get(id);\n if (!upload) {\n throw ApiError.notFound(\"Upload not found\");\n }\n if (upload.completed) {\n throw ApiError.badRequest(\"Upload already completed\");\n }\n\n // Validate offset\n const offsetHeader = c.req.header(\"Upload-Offset\");\n if (!offsetHeader) {\n throw ApiError.badRequest(\"Upload-Offset header is required\");\n }\n const offset = parseInt(offsetHeader, 10);\n if (offset !== upload.offset) {\n throw ApiError.conflict(\"Offset mismatch\");\n }\n\n // Validate content type\n const contentType = c.req.header(\"Content-Type\");\n if (contentType !== \"application/offset+octet-stream\") {\n throw new ApiError(415, \"UNSUPPORTED_MEDIA_TYPE\", \"Content-Type must be application/offset+octet-stream\");\n }\n\n // Read chunk and append to temp file\n const body = await c.req.arrayBuffer();\n const chunk = Buffer.from(body);\n\n // Prevent overrun\n if (upload.offset + chunk.length > upload.size) {\n throw new ApiError(413, \"PAYLOAD_TOO_LARGE\", \"Chunk exceeds declared Upload-Length\");\n }\n\n const fh = await open(upload.filePath, \"a\");\n try {\n await fh.write(chunk);\n } finally {\n await fh.close();\n }\n upload.offset += chunk.length;\n\n // Finalize if complete\n if (upload.offset >= upload.size) {\n await this.finalize(upload);\n }\n\n return new Response(null, {\n status: 204,\n headers: {\n \"Tus-Resumable\": \"1.0.0\",\n \"Upload-Offset\": String(upload.offset)\n }\n });\n }\n\n /** `DELETE /tus/:id` — Cancel and remove an upload. */\n async delete(c: Context, id: string): Promise<Response> {\n const upload = this.uploads.get(id);\n if (!upload) {\n throw ApiError.notFound(\"Upload not found\");\n }\n\n try { await unlink(upload.filePath); } catch { /* ok */ }\n this.uploads.delete(id);\n\n return new Response(null, {\n status: 204,\n headers: { \"Tus-Resumable\": \"1.0.0\" }\n });\n }\n\n // -----------------------------------------------------------------------\n // Finalization\n // -----------------------------------------------------------------------\n\n /**\n * Move a completed upload into the storage controller.\n */\n private async finalize(upload: TusUpload): Promise<void> {\n upload.completed = true;\n\n // Resolve the target controller: prefer storageId from TUS metadata,\n // then fall back to the registry default, then the single controller.\n const storageId = upload.metadata.storageId;\n let targetController = this.storageController;\n if (this.storageRegistry) {\n targetController = storageId\n ? this.storageRegistry.getOrDefault(storageId)\n : this.storageRegistry.getDefault();\n }\n\n if (!targetController) {\n // No controller — leave temp file in place\n logger.warn(\"[TUS] Upload completed but no StorageController configured. Temp file remains:\", { filePath: upload.filePath });\n return;\n }\n\n try {\n const { readFile } = await import(\"fs/promises\");\n const data = await readFile(upload.filePath);\n const fileName = upload.key || upload.metadata.filename || upload.id;\n const mimeType = upload.metadata.contentType || upload.metadata.filetype || \"application/octet-stream\";\n\n // `new Uint8Array(buffer)` rather than the Buffer directly: a Node\n // `Buffer` is typed `Buffer<ArrayBufferLike>`, and `ArrayBufferLike`\n // admits `SharedArrayBuffer`, which is not a `BlobPart`. This copies\n // into a plain ArrayBuffer, which is.\n const file = new File([new Uint8Array(data)], fileName, { type: mimeType });\n\n await targetController.putObject({\n file,\n key: fileName,\n bucket: upload.bucket\n });\n\n // Clean up temp file\n try { await unlink(upload.filePath); } catch { /* ok */ }\n this.uploads.delete(upload.id);\n\n logger.info(`[TUS] Upload ${upload.id} finalized → ${fileName}`, storageId ? { storageId } : {});\n } catch (err) {\n logger.error(`[TUS] Failed to finalize upload ${upload.id}`, { error: err });\n }\n }\n}\n","/**\n * Storage REST API routes using Hono\n *\n * Supports multi-backend routing via `StorageRegistry`. Each endpoint\n * accepts an optional `storageId` parameter (query string or form field)\n * to target a named storage backend. When omitted, the default backend\n * is used.\n */\n\nimport { Hono, type MiddlewareHandler } from \"hono\";\nimport fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport { StorageController, type StorageAuthorize, type StorageAuthorizeData, type StorageOperation } from \"./types\";\nimport { LocalStorageController } from \"./LocalStorageController\";\nimport type { StorageRegistry } from \"./storage-registry\";\nimport { DEFAULT_STORAGE_SOURCE_KEY, isPublicStoragePath, type StorageSourceDefinition, type AuthAdapter } from \"@rebasepro/types\";\nimport { requireAuth as jwtRequireAuth, optionalAuth as jwtOptionalAuth, queryTokenAuth, fileTokenAuth, publicObjectAuth } from \"../auth/middleware\";\nimport { generateDownloadToken } from \"../auth\";\nimport { ApiError, errorHandler } from \"../api/errors\";\nimport { HonoEnv } from \"../api/types\";\nimport { parseTransformOptions, transformImage, isTransformableImage, TransformCache } from \"./image-transform\";\nimport { TusHandler } from \"./tus-handler\";\n\n/** Shared image transform cache (LRU, 500 entries, 1 hour TTL). */\nconst transformCache = new TransformCache();\n\nexport interface StorageRoutesConfig {\n /**\n * Single storage controller (backward-compatible).\n * Used as fallback when no `registry` is provided.\n */\n controller?: StorageController;\n /**\n * Full storage registry for multi-backend routing.\n * When provided, endpoints resolve the controller from `storageId`\n * parameter. Takes precedence over `controller`.\n */\n registry?: StorageRegistry;\n /**\n * Declared storage sources, surfaced by `GET /sources` so the client can\n * bootstrap its registry. Carries the frontend `transport` (server vs\n * direct) and human-readable labels. Server-transport sources are also\n * derived from the registry; `direct` sources (e.g. Firebase Storage) only\n * exist here since the backend does not proxy them.\n */\n sources?: StorageSourceDefinition[];\n /** Base path for storage routes (default: '/api/storage') */\n basePath?: string;\n /** Require authentication for write operations (default: true) */\n requireAuth?: boolean;\n /** Allow unauthenticated read access to stored files (default: false).\n * When false and requireAuth is true, reads also require authentication. */\n publicRead?: boolean;\n /**\n * When provided, storage routes delegate auth to this adapter instead\n * of the built-in JWT module. This mirrors how data routes use\n * `createAdapterAuthMiddleware()` and avoids the \"JWT secret not\n * configured\" crash when `configureJwt()` was never called.\n */\n authAdapter?: AuthAdapter;\n /**\n * Per-object access control, consulted after authentication on every\n * storage route. See `StorageAuthorize`.\n *\n * Omitted, storage behaves as before: authenticated means allowed.\n */\n authorize?: StorageAuthorize;\n /**\n * Trusted data access handed to {@link authorize} on every call.\n *\n * A function rather than a value because the admin data plane is built after\n * the storage routes are mounted; by the time a request runs it is always\n * resolved.\n */\n authorizeData?: () => StorageAuthorizeData | undefined;\n}\n\n/**\n * Extract the wildcard portion of a route path from the full request path.\n *\n * Hono's `c.req.param('*')` does not work reliably in sub-routers mounted\n * via `app.route(prefix, subRouter)`. Instead we derive the wildcard value\n * from the fully-resolved `c.req.path` and `c.req.routePath`.\n *\n * For a route `/metadata/*` mounted at `/api/storage`, a request to\n * `/api/storage/metadata/default/file.jpg` yields routePath\n * `/api/storage/metadata/*`. We strip the prefix (everything before `/*`)\n * plus one character for the trailing `/` to obtain `default/file.jpg`.\n */\nexport function extractWildcardPath(c: { req: { path: string; routePath: string } }): string {\n const routePath = c.req.routePath; // e.g. \"/api/storage/metadata/*\"\n const prefix = routePath.replace(\"/*\", \"\"); // e.g. \"/api/storage/metadata\"\n const fullPath = c.req.path; // e.g. \"/api/storage/metadata/default/file.jpg\"\n const idx = fullPath.indexOf(prefix);\n if (idx < 0) return \"\";\n // +1 to skip the '/' after the prefix\n return fullPath.substring(idx + prefix.length + 1);\n}\n\n/**\n * Sanitize a user-supplied storage key to prevent path traversal and other attacks.\n * Removes null bytes, ../ sequences, leading slashes, and limits length.\n */\nfunction sanitizeStorageKey(key: string): string {\n let sanitized = key;\n // Remove null bytes\n sanitized = sanitized.replace(/\\0/g, \"\");\n // Remove ../ sequences (and ..\\ on Windows)\n sanitized = sanitized.replace(/\\.\\.\\/|\\.\\.\\\\/g, \"\");\n // Remove leading slashes\n sanitized = sanitized.replace(/^\\/+/, \"\");\n // Limit length\n sanitized = sanitized.slice(0, 1024);\n return sanitized;\n}\n\n/**\n * Build adapter-aware auth middleware for storage routes.\n *\n * When an `AuthAdapter` is provided, token verification is delegated to the\n * adapter instead of the built-in JWT module. This mirrors how data routes\n * use `createAdapterAuthMiddleware()`, but without RLS driver scoping (storage\n * routes don't interact with the DataDriver).\n *\n * Returns both a \"write\" middleware (enforces auth when `requireAuth` is true)\n * and a \"read\" middleware (enforces auth unless `publicRead` is set).\n */\nfunction buildAdapterAuthMiddleware(\n adapter: AuthAdapter,\n requireAuth: boolean,\n publicRead: boolean\n): { writeAuthMiddleware: MiddlewareHandler<HonoEnv>; readAuthMiddleware: MiddlewareHandler<HonoEnv> } {\n /**\n * Core middleware: verifies the request via the adapter. When `enforce`\n * is true, returns 401 if no authenticated user is resolved.\n */\n const createMiddleware = (enforce: boolean): MiddlewareHandler<HonoEnv> => {\n return async (c, next) => {\n let authenticatedUser = null;\n try {\n authenticatedUser = await adapter.verifyRequest(c.req.raw);\n } catch {\n return c.json({ error: { message: \"Unauthorized\", code: \"UNAUTHORIZED\" } }, 401);\n }\n\n if (authenticatedUser) {\n c.set(\"user\", {\n uid: authenticatedUser.uid,\n email: authenticatedUser.email,\n roles: authenticatedUser.roles\n });\n }\n\n // Respect a user already resolved by an upstream middleware\n // (e.g. `fileTokenAuth` for scoped `?token=` download tokens, or\n // `publicObjectAuth` for public paths). The adapter does not\n // understand these file-read tokens, so enforcing purely on\n // `authenticatedUser` would 401 an otherwise-valid file request.\n if (enforce && !authenticatedUser && !c.get(\"user\")) {\n return c.json({ error: { message: \"Unauthorized: Authentication required\", code: \"UNAUTHORIZED\" } }, 401);\n }\n\n return next();\n };\n };\n\n return {\n writeAuthMiddleware: createMiddleware(requireAuth),\n readAuthMiddleware: createMiddleware(!publicRead && requireAuth)\n };\n}\n\n/**\n * Create storage REST API routes\n */\nexport function createStorageRoutes(config: StorageRoutesConfig): Hono<HonoEnv> {\n const router = new Hono<HonoEnv>();\n router.onError(errorHandler);\n const { controller, registry, sources: declaredSources, requireAuth = true, publicRead = false, authAdapter, authorize, authorizeData } = config;\n\n /**\n * Run the per-object authorization hook, if one is configured.\n *\n * Denials are 403 rather than 404: the route already established that the\n * caller is authenticated, so hiding existence buys nothing, and a\n * distinguishable status is what makes a misconfigured policy debuggable.\n * A hook that throws denies too — an ownership lookup that fails must not\n * fall open.\n */\n const checkAuthorized = async (\n c: { get: (k: \"user\") => { uid: string; email?: string; roles?: string[] } | undefined },\n operation: StorageOperation,\n key: string,\n bucket: string,\n storageId?: string | null\n ): Promise<void> => {\n if (!authorize) return;\n\n const user = c.get(\"user\") ?? null;\n\n // A scoped download token *is* the authorization: it was minted by\n // `/metadata`, which ran this same hook, and it is valid only for the\n // path it was minted for. Re-running the hook here would ask the\n // synthetic token principal a question about ownership it cannot\n // answer, and would break every <img> the client already renders.\n // Public paths are declared public, so they are equally not the hook's\n // business.\n if (user?.uid === \"download-token\" || user?.uid === \"public\") return;\n\n let allowed: boolean;\n try {\n allowed = await authorize({\n key,\n bucket,\n operation,\n user,\n storageId: storageId ?? undefined,\n data: authorizeData?.()\n });\n } catch {\n allowed = false;\n }\n if (!allowed) {\n throw ApiError.forbidden(\"Not authorized for this object\");\n }\n };\n\n /**\n * Resolve the storage controller for a request.\n * Looks up by `storageId` in the registry, falls back to the single\n * controller, and finally to the registry default.\n */\n const resolveController = (storageId?: string | null): StorageController => {\n if (registry) {\n return registry.getOrDefault(storageId);\n }\n if (controller) {\n return controller;\n }\n throw new Error(\"No storage controller or registry available\");\n };\n\n /** Get the default controller (used for TUS and base-path derivation). */\n const getDefaultController = (): StorageController => {\n if (registry) return registry.getDefault();\n if (controller) return controller;\n throw new Error(\"No storage controller or registry available\");\n };\n\n // ── Auth middleware selection ────────────────────────────────────────\n // When an AuthAdapter is available, delegate token verification to it\n // (mirroring the data-routes pattern). This avoids calling the JWT\n // module which may not have been configured (e.g. custom auth).\n // When no adapter is present, fall back to the built-in JWT middleware.\n const { writeAuthMiddleware, readAuthMiddleware } = authAdapter\n ? buildAdapterAuthMiddleware(authAdapter, requireAuth, publicRead)\n : {\n writeAuthMiddleware: requireAuth ? jwtRequireAuth : jwtOptionalAuth,\n readAuthMiddleware: (publicRead || !requireAuth) ? jwtOptionalAuth : jwtRequireAuth\n };\n\n /**\n * Parse bucket and path from a combined file path.\n *\n * The resolved path is run through `sanitizeStorageKey` here — the same\n * function the upload route applies to incoming keys — so that read,\n * delete, metadata and folder routes strip `../`, null bytes and leading\n * slashes before the path reaches the controller, the authorize hook, or\n * the download-token it mints. The `LocalStorageController` traversal guard\n * (`getFullPath`) remains the load-bearing defence; this is the same\n * normalization on the write and read sides so a `..%2f` read/delete cannot\n * even reach it as a raw traversal string (it 404s as a normal miss instead\n * of throwing, and never leaks whether an escape was attempted).\n */\n const parseBucketAndPath = (filePath: string): { bucket: string; resolvedPath: string } => {\n const parts = filePath.split(\"/\");\n\n // Only recognize 'default' as an explicit bucket prefix\n if (parts.length > 1 && parts[0].toLowerCase() === \"default\") {\n return {\n bucket: \"default\",\n resolvedPath: sanitizeStorageKey(parts.slice(1).join(\"/\"))\n };\n }\n\n // All other paths use 'default' bucket with the full path\n return {\n bucket: \"default\",\n resolvedPath: sanitizeStorageKey(filePath)\n };\n };\n\n /**\n * POST /upload - Upload a file\n * Body: multipart/form-data with 'file' field\n * Request body can also contain metadata keys 'metadata_*'\n */\n router.post(\"/upload\", writeAuthMiddleware, async (c) => {\n const body = await c.req.parseBody();\n const uploadedFile = body[\"file\"];\n\n if (!uploadedFile || typeof uploadedFile === \"string\") {\n throw ApiError.badRequest(\"No file provided\");\n }\n\n const key = typeof body[\"key\"] === \"string\" ? body[\"key\"] : \"\";\n const bucket = typeof body[\"bucket\"] === \"string\" ? body[\"bucket\"] : undefined;\n const storageId = typeof body[\"storageId\"] === \"string\" ? body[\"storageId\"] : c.req.query(\"storageId\");\n\n const finalKey = sanitizeStorageKey(key || uploadedFile.name || \"unnamed\");\n\n // Extract custom metadata from request body\n const metadata: Record<string, unknown> = {};\n for (const [k, value] of Object.entries(body)) {\n if (k.startsWith(\"metadata_\")) {\n metadata[k.replace(\"metadata_\", \"\")] = value;\n }\n }\n\n await checkAuthorized(c, \"write\", finalKey, bucket ?? \"default\", storageId);\n\n const resolved = resolveController(storageId);\n const result = await resolved.putObject({\n file: uploadedFile,\n key: finalKey,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n bucket\n });\n\n return c.json({\n success: true,\n data: result\n }, 201);\n });\n\n /**\n * GET /file/* - Download/serve a file\n * Path: /file/{bucket}/{path} or /file/{path}\n */\n router.get(\"/file/*\", fileTokenAuth, publicObjectAuth, readAuthMiddleware, async (c) => {\n // Allow cross-origin loading so admin frontends on different\n // ports (dev) or domains (CDN) can render images via <img>.\n c.header(\"Cross-Origin-Resource-Policy\", \"cross-origin\");\n\n const rawPath = extractWildcardPath(c);\n if (!rawPath) {\n throw ApiError.notFound(\"File not found\");\n }\n\n const filePath = decodeURIComponent(rawPath);\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n\n {\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n await checkAuthorized(c, \"read\", resolvedPath, bucket, storageId);\n }\n\n // Parse image transform query params (e.g. ?width=300&format=webp)\n const transformOpts = parseTransformOptions(c.req.query() as Record<string, string>);\n\n // For local storage, serve the file directly from disk\n if (resolved.getType() === \"local\") {\n const localController = resolved as LocalStorageController;\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n\n const absolutePath = localController.getAbsolutePath(resolvedPath, bucket);\n\n // Check if file exists\n try {\n await fsp.access(absolutePath);\n } catch {\n throw ApiError.notFound(\"File not found\");\n }\n\n // Get content type from metadata or infer from extension\n let contentType = \"application/octet-stream\";\n const metadataPath = `${absolutePath}.metadata.json`;\n try {\n const metadataRaw = await fsp.readFile(metadataPath, \"utf-8\");\n const metadata = JSON.parse(metadataRaw);\n contentType = metadata.contentType || contentType;\n } catch {\n // Ignore metadata errors (file may not exist)\n }\n\n const fileContent = await fsp.readFile(absolutePath);\n\n // Apply image transforms if requested and the file is a transformable image\n if (transformOpts && isTransformableImage(contentType)) {\n const cacheKey = transformCache.buildKey(filePath, transformOpts);\n let cached = transformCache.get(cacheKey);\n if (!cached) {\n cached = await transformImage(Buffer.from(fileContent), transformOpts);\n transformCache.set(cacheKey, cached.data, cached.contentType);\n }\n c.header(\"Content-Type\", cached.contentType);\n c.header(\"Cache-Control\", \"public, max-age=31536000, immutable\");\n return c.body(new Uint8Array(cached.data));\n }\n\n c.header(\"Content-Type\", contentType);\n return c.body(new Uint8Array(fileContent));\n }\n\n // For remote storage (S3, GCS, etc.), proxy the file through the backend.\n // We avoid redirecting to signed URLs because:\n // 1. Mixed-content (HTTPS page → HTTP MinIO) is blocked by browsers\n // 2. Internal IPs / VPC endpoints are unreachable from the browser\n const { bucket: parsedBucket, resolvedPath: parsedPath } = parseBucketAndPath(filePath);\n const fileObject = await resolved.getObject(parsedPath, parsedBucket);\n if (!fileObject) {\n throw ApiError.notFound(\"File not found\");\n }\n\n const remoteContentType = fileObject.type || \"application/octet-stream\";\n\n // Apply image transforms for remote storage too\n if (transformOpts && isTransformableImage(remoteContentType)) {\n const cacheKey = transformCache.buildKey(filePath, transformOpts);\n let cached = transformCache.get(cacheKey);\n if (!cached) {\n const buf = Buffer.from(await fileObject.arrayBuffer());\n cached = await transformImage(buf, transformOpts);\n transformCache.set(cacheKey, cached.data, cached.contentType);\n }\n c.header(\"Content-Type\", cached.contentType);\n c.header(\"Cache-Control\", \"public, max-age=31536000, immutable\");\n return c.body(new Uint8Array(cached.data));\n }\n\n c.header(\"Content-Type\", remoteContentType);\n c.header(\"Cache-Control\", \"public, max-age=3600, immutable\");\n const buf = await fileObject.arrayBuffer();\n return c.body(new Uint8Array(buf));\n });\n\n /**\n * GET /metadata/* - Get file metadata\n */\n router.get(\"/metadata/*\", fileTokenAuth, publicObjectAuth, readAuthMiddleware, async (c) => {\n const rawPath = extractWildcardPath(c);\n if (!rawPath) {\n return c.json({\n success: true,\n data: null,\n fileNotFound: true\n }, 404);\n }\n\n const filePath = decodeURIComponent(rawPath);\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n\n // The load-bearing check. This route mints the short-lived path-scoped\n // download token that `/file/*` then trusts, and it used to mint one\n // for any authenticated caller for any path — which is exactly why\n // \"reject full-access JWTs on file routes\" did not close the gap.\n await checkAuthorized(c, \"read\", resolvedPath, bucket, storageId);\n\n const downloadConfig = await resolved.getSignedUrl(resolvedPath, bucket);\n\n if (downloadConfig.fileNotFound) {\n throw ApiError.notFound(\"File not found\");\n }\n\n if (downloadConfig.metadata) {\n const scopedPath = `${bucket}/${resolvedPath}`;\n if (isPublicStoragePath(scopedPath)) {\n // Public object: served token-less via a permanent URL.\n downloadConfig.metadata.public = true;\n } else {\n // Private object: mint a short-lived, path-scoped download token.\n downloadConfig.metadata.token = generateDownloadToken(scopedPath, 300);\n downloadConfig.metadata.tokenExpiresIn = 300;\n }\n }\n\n return c.json({\n success: true,\n data: downloadConfig.metadata\n });\n });\n\n /**\n * DELETE /file/* - Delete a file\n */\n router.delete(\"/file/*\", writeAuthMiddleware, async (c) => {\n const rawPath = extractWildcardPath(c);\n if (!rawPath) {\n return c.json({ success: true,\nmessage: \"No file to delete\" });\n }\n\n const filePath = decodeURIComponent(rawPath);\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n\n await checkAuthorized(c, \"delete\", resolvedPath, bucket, storageId);\n\n await resolved.deleteObject(resolvedPath, bucket);\n\n return c.json({\n success: true,\n message: \"File deleted\"\n });\n });\n\n /**\n * GET /list - List files in a path\n */\n router.get(\"/list\", writeAuthMiddleware, async (c) => {\n // Fallback to path for backward compatibility. Sanitize the prefix the\n // same way object keys are sanitized elsewhere, so a listing cannot be\n // steered out of the bucket with `../` before it hits the controller.\n const storagePrefix = sanitizeStorageKey(c.req.query(\"prefix\") || c.req.query(\"path\") || \"\");\n const bucket = c.req.query(\"bucket\");\n const maxResults = c.req.query(\"maxResults\");\n const pageToken = c.req.query(\"pageToken\");\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n\n // The prefix is the \"object\" being asked about — a listing is how you\n // discover keys you were never told, so leaving it ungated would hand\n // back exactly what per-object read control is meant to withhold.\n await checkAuthorized(c, \"list\", storagePrefix, bucket ?? \"default\", storageId);\n\n const result = await resolved.listObjects(\n storagePrefix,\n {\n bucket: bucket ?? (resolved.getType() === \"local\" ? \"default\" : undefined),\n maxResults: maxResults ? parseInt(maxResults, 10) : undefined,\n pageToken\n }\n );\n\n return c.json({\n success: true,\n data: result\n });\n });\n\n /**\n * POST /folder - Create a new folder\n * Body: { path: string, bucket?: string }\n */\n router.post(\"/folder\", writeAuthMiddleware, async (c) => {\n const body = await c.req.json();\n const folderPath = body.path;\n const storageId = typeof body.storageId === \"string\" ? body.storageId : c.req.query(\"storageId\");\n\n if (!folderPath || typeof folderPath !== \"string\") {\n throw ApiError.badRequest(\"Folder path is required\");\n }\n\n const resolved = resolveController(storageId);\n const { bucket, resolvedPath } = parseBucketAndPath(folderPath);\n\n if (!resolvedPath || resolvedPath.trim() === \"\") {\n throw ApiError.badRequest(\"Invalid folder path\");\n }\n\n await checkAuthorized(c, \"write\", resolvedPath, bucket, storageId);\n\n if (resolved.getType() === \"local\") {\n // For local storage, create the directory\n const localController = resolved as LocalStorageController;\n const absolutePath = localController.getAbsolutePath(resolvedPath, bucket);\n fs.mkdirSync(absolutePath, { recursive: true });\n } else {\n // For S3/GCS-compatible storage, create a zero-byte marker object with trailing slash\n const key = resolvedPath.endsWith(\"/\") ? resolvedPath : resolvedPath + \"/\";\n const emptyFile = new File([], key, { type: \"application/x-directory\" });\n await resolved.putObject({\n file: emptyFile,\n key\n });\n }\n\n return c.json({\n success: true,\n message: \"Folder created\"\n }, 201);\n });\n\n // -----------------------------------------------------------------------\n // TUS Resumable Uploads\n // -----------------------------------------------------------------------\n\n const defaultCtrl = getDefaultController();\n const tusBaseDir = defaultCtrl.getType() === \"local\"\n ? (defaultCtrl as LocalStorageController).getBasePath()\n : (process.env.STORAGE_PATH || \"./uploads\");\n const tusHandler = new TusHandler(\n tusBaseDir,\n defaultCtrl,\n registry,\n authorize\n ? async (c, key, bucket) => {\n await checkAuthorized(c as never, \"write\", sanitizeStorageKey(key), bucket, c.req.query(\"storageId\"));\n }\n : undefined\n );\n tusHandler.startCleanup();\n\n router.options(\"/tus\", (_c) => tusHandler.options());\n router.post(\"/tus\", writeAuthMiddleware, async (c) => tusHandler.create(c));\n router.get(\"/tus/:id\", readAuthMiddleware, (c) => tusHandler.head(c, c.req.param(\"id\")));\n router.patch(\"/tus/:id\", writeAuthMiddleware, async (c) => tusHandler.patch(c, c.req.param(\"id\")));\n router.delete(\"/tus/:id\", writeAuthMiddleware, async (c) => tusHandler.delete(c, c.req.param(\"id\")));\n\n // -----------------------------------------------------------------------\n // Storage Sources Discovery\n // -----------------------------------------------------------------------\n\n /**\n * GET /sources — list all registered storage backends.\n * The client can bootstrap its StorageSourceRegistry from this endpoint.\n */\n router.get(\"/sources\", (c) => {\n const byKey = new Map<string, { key: string; engine: string; transport: \"server\" | \"direct\"; label?: string }>();\n\n // 1. Server-backed sources derived from the registry (source of truth\n // for the actual engine type), or the single controller.\n if (registry) {\n for (const key of registry.list()) {\n byKey.set(key, {\n key,\n engine: registry.get(key)?.getType() ?? \"unknown\",\n transport: \"server\",\n });\n }\n } else {\n byKey.set(DEFAULT_STORAGE_SOURCE_KEY, {\n key: DEFAULT_STORAGE_SOURCE_KEY,\n engine: defaultCtrl.getType(),\n transport: \"server\",\n });\n }\n\n // 2. Overlay declared definitions: adds `direct` sources the backend\n // does not proxy, plus labels and explicit transport/engine.\n for (const def of declaredSources ?? []) {\n const existing = byKey.get(def.key);\n byKey.set(def.key, {\n key: def.key,\n engine: def.engine ?? existing?.engine ?? \"unknown\",\n transport: def.transport ?? existing?.transport ?? \"server\",\n label: def.label ?? existing?.label,\n });\n }\n\n return c.json({ success: true, data: Array.from(byKey.values()) });\n });\n\n return router;\n}\n","/**\n * Storage Registry\n *\n * Manages multiple storage controllers for Rebase backend.\n * Allows different storage backends for different use cases.\n *\n * Usage:\n * - Single storage: Pass a single StorageController → maps to \"(default)\"\n * - Multiple storages: Pass a map of { storageId: StorageController }\n * - String properties use `storageId` in their config to specify which storage to use\n * - Properties without `storageId` fallback to \"(default)\"\n */\n\nimport { StorageController } from \"./types\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * The default storage identifier used when:\n * - A single storage controller is provided (not a map)\n * - A property doesn't specify a storageId\n */\nexport const DEFAULT_STORAGE_ID = \"(default)\";\n\n/**\n * Registry for managing multiple storage controllers\n */\nexport interface StorageRegistry {\n /**\n * Register a storage controller with an ID\n * @param id - Unique identifier for this storage (e.g., \"media\", \"backups\")\n * @param controller - The StorageController instance\n */\n register(id: string, controller: StorageController): void;\n\n /**\n * Get the default storage controller (id = \"(default)\")\n * @throws Error if no default storage is registered\n */\n getDefault(): StorageController;\n\n /**\n * Get a storage controller by ID\n * @param id - Storage identifier, or undefined/null for default\n * @returns The StorageController, or undefined if not found\n */\n get(id: string | undefined | null): StorageController | undefined;\n\n /**\n * Get a storage controller by ID, with fallback to default\n * @param id - Storage identifier, or undefined/null for default\n * @returns The StorageController (falls back to default if id not found)\n * @throws Error if neither the specified nor default storage exists\n */\n getOrDefault(id: string | undefined | null): StorageController;\n\n /**\n * Check if a storage with the given ID exists\n */\n has(id: string): boolean;\n\n /**\n * List all registered storage IDs\n */\n list(): string[];\n\n /**\n * Get the number of registered storage controllers\n */\n size(): number;\n}\n\n/**\n * Default implementation of StorageRegistry\n */\nexport class DefaultStorageRegistry implements StorageRegistry {\n private controllers = new Map<string, StorageController>();\n\n /**\n * Create a StorageRegistry from either a single controller or a map\n * @param input - Single StorageController (maps to \"(default)\") or Record<string, StorageController>\n */\n static create(\n input: StorageController | Record<string, StorageController>\n ): DefaultStorageRegistry {\n const registry = new DefaultStorageRegistry();\n\n if (isStorageController(input)) {\n // Single controller → register as \"(default)\"\n registry.register(DEFAULT_STORAGE_ID, input);\n } else {\n // Map of controllers → register each\n for (const [id, controller] of Object.entries(input)) {\n if (isStorageController(controller)) {\n registry.register(id, controller);\n }\n }\n // Ensure there's a default if not explicitly provided\n if (!registry.has(DEFAULT_STORAGE_ID) && registry.size() > 0) {\n // If no explicit \"(default)\", use the first one as default\n const firstId = Object.keys(input).find(k => isStorageController(input[k]));\n if (firstId) {\n logger.warn(\n `[StorageRegistry] No \"${DEFAULT_STORAGE_ID}\" storage provided. ` +\n `Using \"${firstId}\" as the default.`\n );\n registry.register(DEFAULT_STORAGE_ID, input[firstId]);\n }\n }\n }\n\n return registry;\n }\n\n register(id: string, controller: StorageController): void {\n if (this.controllers.has(id)) {\n logger.warn(`[StorageRegistry] Overwriting storage with id \"${id}\"`);\n }\n this.controllers.set(id, controller);\n }\n\n getDefault(): StorageController {\n const controller = this.controllers.get(DEFAULT_STORAGE_ID);\n if (!controller) {\n throw new Error(\n \"[StorageRegistry] No default storage registered. \" +\n `Register one with id \"${DEFAULT_STORAGE_ID}\" or pass a single StorageController.`\n );\n }\n return controller;\n }\n\n get(id: string | undefined | null): StorageController | undefined {\n if (id === undefined || id === null) {\n return this.controllers.get(DEFAULT_STORAGE_ID);\n }\n return this.controllers.get(id);\n }\n\n getOrDefault(id: string | undefined | null): StorageController {\n // If no ID specified, return default\n if (id === undefined || id === null) {\n return this.getDefault();\n }\n\n // Try to get by ID\n const controller = this.controllers.get(id);\n if (controller) {\n return controller;\n }\n\n // Fallback to default with warning\n logger.warn(\n `[StorageRegistry] Storage \"${id}\" not found, falling back to \"${DEFAULT_STORAGE_ID}\"`\n );\n return this.getDefault();\n }\n\n has(id: string): boolean {\n return this.controllers.has(id);\n }\n\n list(): string[] {\n return Array.from(this.controllers.keys());\n }\n\n size(): number {\n return this.controllers.size;\n }\n}\n\n/**\n * Type guard to check if an object is a StorageController\n * vs a Record<string, StorageController> (multiple storages)\n */\nfunction isStorageController(obj: unknown): obj is StorageController {\n if (typeof obj !== \"object\" || obj === null) {\n return false;\n }\n const controller = obj as StorageController;\n // Check for required StorageController properties\n return (\n typeof controller.putObject === \"function\" &&\n typeof controller.getSignedUrl === \"function\" &&\n typeof controller.deleteObject === \"function\" &&\n typeof controller.listObjects === \"function\" &&\n typeof controller.getType === \"function\"\n );\n}\n","/**\n * Storage module for Rebase backend\n *\n * Provides pluggable file storage with three built-in providers:\n * - **Local filesystem** — zero config, great for dev and single-server deployments.\n * - **S3-compatible** — works with AWS S3, Cloudflare R2, MinIO, Hetzner Object Storage,\n * Backblaze B2, DigitalOcean Spaces, and GCS (via S3 interop).\n * - **Google Cloud Storage / Firebase Storage** — native GCS support via `@google-cloud/storage`\n * (optional peer dependency, lazily loaded).\n *\n * For other providers (Azure Blob, etc.), implement the\n * `StorageController` interface and pass the instance directly to the `storage` config.\n */\n\nexport * from \"./types\";\nexport { LocalStorageController } from \"./LocalStorageController\";\nexport { S3StorageController } from \"./S3StorageController\";\nexport { GCSStorageController } from \"./GCSStorageController\";\nexport { createStorageRoutes } from \"./routes\";\nexport type { StorageRoutesConfig } from \"./routes\";\nexport * from \"./storage-registry\";\nexport { parseTransformOptions, transformImage, isTransformableImage, TransformCache } from \"./image-transform\";\nexport type { ImageTransformOptions } from \"./image-transform\";\nexport { TusHandler } from \"./tus-handler\";\n\nimport { BackendStorageConfig, StorageController } from \"./types\";\nimport { LocalStorageController } from \"./LocalStorageController\";\n\n/**\n * Create a storage controller from a config object.\n *\n * For custom providers, implement `StorageController` directly instead\n * of going through this factory.\n */\nexport async function createStorageController(config: BackendStorageConfig): Promise<StorageController> {\n switch (config.type) {\n case \"local\":\n return new LocalStorageController(config);\n case \"s3\": {\n const { S3StorageController } = await import(\"./S3StorageController\");\n return new S3StorageController(config);\n }\n case \"gcs\": {\n const { GCSStorageController } = await import(\"./GCSStorageController\");\n return new GCSStorageController(config);\n }\n default:\n throw new Error(\n `Unknown storage type: ${(config as Record<string, unknown>).type}. ` +\n \"Built-in types: local, s3, gcs. \" +\n \"For other providers, implement the StorageController interface directly.\"\n );\n }\n}\n","import {\n BackendStorageConfig,\n createStorageController,\n DEFAULT_STORAGE_ID,\n DefaultStorageRegistry,\n StorageController,\n StorageRegistry\n} from \"../storage\";\nimport { logger } from \"../utils/logger\";\n\nexport async function initializeStorage(\n storageConfig: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController> | undefined,\n isProduction: boolean\n): Promise<{ storageRegistry?: StorageRegistry; storageController?: StorageController }> {\n if (!storageConfig) return {};\n\n logger.info(\"Configuring storage\");\n const controllers: Record<string, StorageController> = {};\n\n const toController = async (entry: BackendStorageConfig | StorageController, label: string): Promise<StorageController | undefined> => {\n if (typeof (entry as StorageController).putObject === \"function\") {\n return entry as StorageController;\n }\n const conf = entry as BackendStorageConfig;\n // On a managed platform the local backend is a pod's ephemeral\n // filesystem, so every uploaded file disappears at the next restart —\n // with no error at write time, no error at read time, and a log line\n // nobody reads until the data is already gone.\n //\n // So in production this backend is not registered at all. Storage is\n // off until a bucket is configured: uploads are refused with\n // STORAGE_NOT_CONFIGURED (see the stub router in `init.ts`) instead of\n // succeeding into a filesystem that is about to be wiped. Dropping the\n // backend rather than throwing keeps the rest of the app — data, auth,\n // realtime — serving, which a crash-looping rollout would not.\n if (isProduction && conf.type === \"local\" && !process.env.FORCE_LOCAL_STORAGE) {\n logger.error(\n `Storage backend \"${label}\" is set to \"local\" in production — DISABLED. Local ` +\n \"storage is the container filesystem, so uploaded files would be destroyed on the \" +\n \"next restart or redeploy. File uploads will be refused until storage is \" +\n \"configured: set S3-compatible storage (STORAGE_TYPE=s3) or GCS \" +\n \"(STORAGE_TYPE=gcs), or pass a custom StorageController. If this deployment \" +\n \"really does have a durable volume mounted at the storage path, set \" +\n \"FORCE_LOCAL_STORAGE=true.\"\n );\n return undefined;\n }\n return await createStorageController(conf);\n };\n\n if (\n typeof storageConfig === \"object\" &&\n (\"type\" in storageConfig || typeof (storageConfig as StorageController).putObject === \"function\")\n ) {\n const controller = await toController(\n storageConfig as BackendStorageConfig | StorageController,\n DEFAULT_STORAGE_ID\n );\n if (controller) controllers[DEFAULT_STORAGE_ID] = controller;\n } else {\n for (const [storageId, entry] of Object.entries(\n storageConfig as Record<string, BackendStorageConfig | StorageController>\n )) {\n const controller = await toController(entry, storageId);\n if (controller) controllers[storageId] = controller;\n }\n }\n\n if (Object.keys(controllers).length > 0) {\n const storageRegistry = DefaultStorageRegistry.create(controllers);\n const storageController = storageRegistry.getDefault();\n logger.info(\"Initialized storage backends\", { count: Object.keys(controllers).length });\n return { storageRegistry, storageController };\n }\n\n return {};\n}\n\n/** Inputs that decide whether storage has an access-control model at all. */\nexport interface StorageAccessControlState {\n /** A `storageAuthorize` hook was configured (per-object access control). */\n hasAuthorize: boolean;\n /** Reads are deliberately public (`storagePublicRead: true`). */\n publicRead: boolean;\n /** The legacy \"any authenticated user may touch any key\" behaviour was\n * explicitly acknowledged (`storageInsecureAllowAnyAuthenticated: true`). */\n allowAnyAuthenticated: boolean;\n}\n\n/**\n * The one message the boot guard emits, factored out so the production throw\n * and the development warning say exactly the same thing.\n */\nconst STORAGE_NO_ACCESS_CONTROL_MESSAGE =\n \"Storage is configured WITHOUT any access-control model. Keys share one flat \" +\n \"namespace and no `storageAuthorize` hook is set, so any authenticated user can \" +\n \"list every key (GET /storage/list?prefix=) and then read, overwrite or delete \" +\n \"any other user's files. Fix one of:\\n\" +\n \" • add a `storageAuthorize` hook that scopes access per user/tenant (recommended), or\\n\" +\n \" • set `storagePublicRead: true` if this bucket is genuinely a public read-only CDN, or\\n\" +\n \" • set `storageInsecureAllowAnyAuthenticated: true` to keep the legacy shared-namespace\\n\" +\n \" behaviour on purpose (single-tenant apps where every signed-in user is trusted).\";\n\n/**\n * Refuse to boot storage in production with no access-control model.\n *\n * Storage is not under RLS and its keys share one flat namespace, so with no\n * `storageAuthorize` hook the only thing separating two users' files is key\n * unguessability — which a `GET /list` defeats. This is the storage analogue of\n * the locked-by-default RLS on collections: rather than ship an allow-all\n * default silently, make the deployment state its intent.\n *\n * In production a bare allow-all config is refused (throws, so the rollout\n * fails loudly instead of serving everyone's files to everyone). Outside\n * production it is a loud warning, so local development is not blocked.\n *\n * Any one of the three explicit choices — a hook, public-read, or the insecure\n * opt-out — satisfies the guard.\n */\nexport function assertStorageAccessControlConfigured(\n state: StorageAccessControlState,\n isProduction: boolean\n): void {\n if (state.hasAuthorize || state.publicRead || state.allowAnyAuthenticated) {\n return;\n }\n if (isProduction) {\n throw new Error(STORAGE_NO_ACCESS_CONTROL_MESSAGE);\n }\n logger.warn(STORAGE_NO_ACCESS_CONTROL_MESSAGE);\n}\n","import { Hono } from \"hono\";\nimport { CollectionConfig } from \"@rebasepro/types\";\nimport { HonoEnv } from \"../api/types\";\nimport { logger } from \"../utils/logger\";\n\nexport async function mountOpenApiDocs(\n app: Hono<HonoEnv>,\n basePath: string,\n enableSwagger: boolean | undefined,\n activeCollections: CollectionConfig[],\n requireAuth: boolean\n): Promise<void> {\n if (enableSwagger === false || activeCollections.length === 0) {\n return;\n }\n\n const { generateOpenApiSpec } = await import(\"../api/openapi-generator\");\n\n app.get(`${basePath}/docs`, (c) => {\n const spec = generateOpenApiSpec(activeCollections, {\n basePath,\n requireAuth\n });\n return c.json(spec);\n });\n\n if (process.env.NODE_ENV !== \"production\") {\n app.get(`${basePath}/swagger`, (c) => {\n return c.html(`<!DOCTYPE html>\n<html>\n<head>\n <title>Rebase API Documentation</title>\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <link rel=\"stylesheet\" type=\"text/css\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\"/>\n <style>body{margin:0;padding:0;}</style>\n</head>\n<body>\n <div id=\"swagger-ui\"></div>\n <script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>\n <script>SwaggerUIBundle({ url: '${basePath}/docs', dom_id: '#swagger-ui' });</script>\n</body>\n</html>`);\n });\n logger.info(\"Swagger UI available\", { path: `${basePath}/swagger` });\n }\n}\n","import { AuthSchemaHealth, DataDriver, HealthCheckResult, isSQLAdmin } from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * @param defaultDriver — probed for basic database reachability.\n * @param authSchemaCheck — optional; asserts the auth schema is one this\n * runtime can serve. Reachability alone is not health: a database can answer\n * `SELECT 1` in a millisecond while the auth tables have been migrated out\n * from under the running code, so every login returns 500 behind a green\n * check. Reporting that as healthy is what lets an orchestrator keep routing\n * traffic to a server that cannot authenticate anyone.\n */\nexport function createHealthCheck(\n defaultDriver: DataDriver,\n authSchemaCheck?: () => Promise<AuthSchemaHealth>\n): () => Promise<HealthCheckResult> {\n return async (): Promise<HealthCheckResult> => {\n const start = performance.now();\n try {\n const admin = defaultDriver.admin;\n if (isSQLAdmin(admin)) {\n await admin.executeSql(\"SELECT 1\");\n } else {\n await defaultDriver.fetchCollection({\n path: \"__health_check_nonexistent__\",\n limit: 1\n });\n }\n\n const auth = await authSchemaCheck?.();\n const latencyMs = Math.round(performance.now() - start);\n if (auth && !auth.healthy) {\n logger.error(\"Health check failed: auth schema mismatch\", {\n problems: auth.problems,\n databaseVersion: auth.databaseVersion,\n runtimeVersion: auth.runtimeVersion\n });\n return {\n healthy: false,\n latencyMs,\n details: { authSchema: auth }\n };\n }\n\n return {\n healthy: true,\n latencyMs\n };\n } catch (error: unknown) {\n const latencyMs = Math.round(performance.now() - start);\n logger.error(\"Health check failed\", {\n error: error instanceof Error ? error : new Error(String(error)),\n latencyMs\n });\n return {\n healthy: false,\n latencyMs,\n details: {\n error: error instanceof Error ? error.message : String(error)\n }\n };\n }\n };\n}\n","import { Server } from \"http\";\nimport { RealtimeProvider } from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\n\ninterface ShutdownConfig {\n server: Server;\n cronScheduler?: { stop(): void };\n realtimeServices: Record<string, RealtimeProvider>;\n}\n\n/**\n * Minimal structural view of the backend instance needed by\n * {@link installShutdownHandlers}. Structural (rather than importing\n * `RebaseBackendInstance`) to avoid a circular import with `../init`.\n */\ninterface ShutdownCapableBackend {\n shutdown(timeoutMs?: number): Promise<void>;\n}\n\nexport interface ShutdownHandlerOptions {\n /**\n * Cleanup to run after the backend has drained — e.g. closing your\n * database pool: `onCleanup: () => pool.end()`.\n */\n onCleanup?: () => Promise<void> | void;\n\n /**\n * Hard force-exit timeout in milliseconds. If the shutdown sequence\n * (drain + cleanup) has not completed by then, the process exits with\n * code 1. Also passed to `backend.shutdown()` as its drain timeout.\n *\n * @default 15000\n */\n timeoutMs?: number;\n\n /**\n * Process signals to handle.\n * @default [\"SIGTERM\", \"SIGINT\"]\n */\n signals?: NodeJS.Signals[];\n\n /** @internal Injectable exit function for tests. */\n exit?: (code: number) => void;\n}\n\n/**\n * Install graceful-shutdown signal handlers for a Rebase backend.\n *\n * On the first signal received, this drains the backend via\n * `backend.shutdown()` — which stops the cron scheduler, tears down\n * realtime services, and closes the HTTP server. Do **not** call\n * `server.close()` yourself in addition: closing an already-closing\n * server deadlocks, because the second close's callback never fires.\n *\n * After the drain, `onCleanup` runs (close your database pool here),\n * and the process exits 0. A force-exit timer guards the whole\n * sequence: if it has not completed within `timeoutMs`, the process\n * exits 1. Repeated signals while a shutdown is in flight are ignored.\n *\n * @returns An uninstall function that removes the signal listeners\n * (useful in tests).\n *\n * @example\n * ```ts\n * const backend = await initializeRebaseBackend({ ... });\n * installShutdownHandlers(backend, { onCleanup: () => pool.end() });\n * ```\n */\nexport function installShutdownHandlers(\n backend: ShutdownCapableBackend,\n options: ShutdownHandlerOptions = {}\n): () => void {\n const {\n onCleanup,\n timeoutMs = 15_000,\n signals = [\"SIGTERM\", \"SIGINT\"],\n exit = process.exit\n } = options;\n\n let shuttingDown = false;\n\n const shutdownSequence = async (signal: NodeJS.Signals): Promise<void> => {\n if (shuttingDown) return;\n shuttingDown = true;\n\n logger.info(`Received ${signal}, shutting down gracefully...`);\n\n // Hard backstop — must be armed before any awaits.\n const forceTimer = setTimeout(() => {\n logger.error(`Shutdown timed out after ${Math.round(timeoutMs / 1000)}s. Forcefully exiting.`);\n exit(1);\n }, timeoutMs);\n forceTimer.unref();\n\n try {\n await backend.shutdown(timeoutMs);\n if (onCleanup) {\n await onCleanup();\n }\n clearTimeout(forceTimer);\n logger.info(\"Graceful shutdown complete.\");\n exit(0);\n } catch (err) {\n logger.error(\"Error during shutdown cleanup:\", { error: err instanceof Error ? err : new Error(String(err)) });\n exit(1);\n }\n };\n\n const listeners = signals.map((signal) => {\n const listener = () => { void shutdownSequence(signal); };\n process.on(signal, listener);\n return { signal, listener } as const;\n });\n\n return () => {\n for (const { signal, listener } of listeners) {\n process.removeListener(signal, listener);\n }\n };\n}\n\nexport function createShutdown(config: ShutdownConfig): (timeoutMs?: number) => Promise<void> {\n return (timeoutMs = 15_000): Promise<void> => {\n return new Promise<void>((resolve) => {\n (async () => {\n logger.info(\"Shutting down Rebase Backend...\");\n\n // 1. Stop cron scheduler\n if (config.cronScheduler) {\n config.cronScheduler.stop();\n logger.info(\"Cron scheduler stopped\");\n }\n\n // 2. Tear down realtime services (LISTEN clients, debounce timers,\n // subscriptions). Must happen BEFORE pool.end() so that pending\n // timer callbacks don't fire against a closed pool.\n for (const [key, rt] of Object.entries(config.realtimeServices)) {\n try {\n if (typeof rt.destroy === \"function\") {\n await rt.destroy();\n logger.info(`Realtime service \"${key}\" destroyed`);\n } else if (typeof rt.stopListening === \"function\") {\n await rt.stopListening();\n logger.info(`Realtime service \"${key}\" LISTEN client stopped`);\n }\n } catch (err) {\n logger.warn(`Error destroying realtime service \"${key}\":`, { error: err });\n }\n }\n\n // 3. Close the HTTP server (stop accepting, drain in-flight)\n config.server.close(() => {\n logger.info(\"HTTP server closed\");\n resolve();\n });\n\n // 4. Force-resolve after timeout (unless disabled with 0)\n if (timeoutMs > 0) {\n setTimeout(() => {\n logger.warn(`Forced shutdown after ${timeoutMs / 1000}s timeout`);\n resolve();\n }, timeoutMs).unref();\n }\n })();\n });\n };\n}\n","import { logger } from \"../utils/logger\";\n\n/** The data callbacks the auth write path does not run. */\nconst DATA_CALLBACKS = [\"beforeSave\", \"afterSave\", \"beforeDelete\", \"afterDelete\"] as const;\n\n/**\n * Warn when the auth collection hangs data callbacks that auth will not fire.\n *\n * Creating a user through the auth subsystem — registration, OAuth, the admin\n * user routes — writes to the user store directly, because that path owns\n * password hashing, identity rows and its own transaction. It deliberately does\n * not go through the collection save pipeline: a `beforeSave` able to rewrite\n * `password_hash` on its way to the database is a footgun, not a feature, and\n * the auth hooks (`afterUserCreate`, `beforeUserCreate`, …) exist to hang\n * behaviour off those events with the right contract.\n *\n * The cost is a reasonable expectation quietly not being met: someone puts\n * \"send the welcome email\" in `afterSave` on their users collection, tests it\n * by creating a user in the admin, and it works — because *that* is a\n * collection write. Then a real signup does nothing at all. Which is why this\n * is said at boot, naming the callbacks that will not run.\n */\nexport function warnOnAuthCollectionDataCallbacks(collection?: {\n slug?: string;\n callbacks?: Record<string, unknown>;\n}): void {\n if (!collection?.callbacks) return;\n\n const declared = DATA_CALLBACKS.filter(name => typeof collection.callbacks?.[name] === \"function\");\n if (declared.length === 0) return;\n\n logger.warn(\n `[Auth] The auth collection \"${collection.slug}\" defines ` +\n `${declared.join(\"/\")} callback(s), but these do NOT fire when users are ` +\n `created or updated through the auth system (registration, admin, OAuth) — ` +\n `that path bypasses the collection save pipeline. Use auth hooks ` +\n `(afterUserCreate, beforeUserCreate, afterUserDelete, …) for those side effects.`\n );\n}\n","import { DEFAULT_STORAGE_SOURCE_KEY, EntityReference, EntityRelation, GeoPoint, PUBLIC_STORAGE_PREFIX, RebaseApiError, RebaseApiError as RebaseApiError$1, RebaseClientError, RebaseClientError as RebaseClientError$1, Vector, isPublicStoragePath, toCanonicalOp } from \"@rebasepro/types\";\nimport { COMPOSITE_ID_SEPARATOR, QueryBuilder, RebasePaginationError, and, buildCompositeId, collectAllPages, cond, or, paginateFind, serializeFilter, serializeLogicalCondition, serializeOrderBy } from \"@rebasepro/common\";\nimport { toSnakeCase } from \"@rebasepro/utils\";\n//#region src/reviver.ts\nfunction rebaseReviver(_key, value) {\n\tif (value && typeof value === \"object\" && \"__type\" in value) {\n\t\tconst record = value;\n\t\tswitch (record.__type) {\n\t\t\tcase \"date\":\n\t\t\tcase \"Date\": {\n\t\t\t\tif (typeof record.value !== \"string\") return value;\n\t\t\t\tconst date = new Date(record.value);\n\t\t\t\treturn isNaN(date.getTime()) ? null : date;\n\t\t\t}\n\t\t\tcase \"reference\":\n\t\t\tcase \"EntityReference\": return new EntityReference({\n\t\t\t\tid: String(record.id),\n\t\t\t\tpath: record.path,\n\t\t\t\tdriver: record.driver,\n\t\t\t\tdatabaseId: record.databaseId\n\t\t\t});\n\t\t\tcase \"relation\":\n\t\t\tcase \"EntityRelation\": return new EntityRelation(record.id, record.path, record.data);\n\t\t\tcase \"GeoPoint\": return new GeoPoint(record.latitude, record.longitude);\n\t\t\tcase \"Vector\": return new Vector(record.value);\n\t\t\tdefault: return value;\n\t\t}\n\t}\n\treturn value;\n}\n//#endregion\n//#region src/transport.ts\n/**\n* True when there is no browser to have signed a user in — a Node script, a\n* cron job, an edge worker.\n*\n* Anonymous is an ordinary, correct state in a browser: before sign-in, on a\n* marketing page, for public reads. Warning there would be noise that teaches\n* people to ignore warnings, so the guard is off entirely. This uses the same\n* `typeof window` test as {@link resolveBaseUrl}, and additionally treats a\n* defined `document` as a browser so an SSR shim or test harness that installs\n* only one of the two is still excluded.\n*/\nfunction isServerLikeEnvironment() {\n\treturn typeof window === \"undefined\" && typeof document === \"undefined\";\n}\n/**\n* Emitted once per client. Kept as a constant so the wording is testable and\n* greppable — this is the string a user will paste into a search.\n*/\nvar ANONYMOUS_SERVER_CLIENT_WARNING = \"[rebase] This client was created outside a browser with no credential — no `token`, no auth token getter, and no cookie auth flow — so every request runs as an anonymous caller. Row-level security will return only publicly readable rows, which is usually nothing and occasionally the wrong thing. Inside a cron or function handler, use the `client` you were handed instead of building a new one: its data plane is already admin-scoped. In a standalone script or job, pass the service key as `token`. If you really do want anonymous access, pass `anonymous: true` to silence this.\";\n/**\n* Refuse a filter whose *value* is missing.\n*\n* `where: { status: [\"==\", undefined] }` used to serialize to the literal\n* string, so `status=eq.undefined` went out on the wire and the server dutifully\n* looked for rows whose status is the four-letter word \"undefined\". The caller\n* saw an empty page, not an error — the classic shape of a variable that was\n* never set.\n*\n* Dropping the condition instead would be worse than sending it: the query\n* would come back *unfiltered*, which for an ownership or tenant filter means\n* returning rows the caller never asked to see. So this is a hard error, and\n* both correct spellings are named in the message: omit the key to skip the\n* filter, or use `[\"is-null\", null]` to match SQL NULL (which still\n* serializes — `null` is a value, `undefined` is the absence of one).\n*/\nfunction assertNoUndefinedFilterValues(where) {\n\tconst reject = (field, op) => {\n\t\tthrow new RebaseClientError$1(`Filter on \"${field}\" has an undefined value ([\"${String(op)}\", undefined]). Omit \"${field}\" from \\`where\\` to skip the filter, or use [\"is-null\", null] to match SQL NULL.`);\n\t};\n\tfor (const [field, condition] of Object.entries(where)) {\n\t\tif (condition === void 0) continue;\n\t\tif (!Array.isArray(condition)) continue;\n\t\tconst tuples = Array.isArray(condition[0]) ? condition : [condition];\n\t\tfor (const tuple of tuples) {\n\t\t\tif (!Array.isArray(tuple) || tuple.length !== 2) continue;\n\t\t\tconst [op, value] = tuple;\n\t\t\tif (value === void 0) reject(field, op);\n\t\t\tif (Array.isArray(value) && value.some((v) => v === void 0)) reject(field, op);\n\t\t}\n\t}\n}\nfunction buildQueryString(params) {\n\tif (!params) return \"\";\n\tconst parts = [];\n\tif (params.limit != null) parts.push(`limit=${params.limit}`);\n\tif (params.offset != null) parts.push(`offset=${params.offset}`);\n\tif (params.page != null) parts.push(`page=${params.page}`);\n\tif (params.orderBy) {\n\t\tconst wire = serializeOrderBy(params.orderBy);\n\t\tif (wire) parts.push(`orderBy=${encodeURIComponent(wire)}`);\n\t}\n\tif (params.searchString) parts.push(`searchString=${encodeURIComponent(params.searchString)}`);\n\tif (params.include && params.include.length > 0) parts.push(`include=${encodeURIComponent(params.include.join(\",\"))}`);\n\tif (params.logical) {\n\t\tconst root = params.logical;\n\t\tconst serialized = (root.conditions ?? []).map(serializeLogicalCondition).join(\",\");\n\t\tparts.push(`${root.type}=${encodeURIComponent(`(${serialized})`)}`);\n\t}\n\tif (params.where) {\n\t\tassertNoUndefinedFilterValues(params.where);\n\t\tconst serialized = serializeFilter(params.where);\n\t\tfor (const [field, value] of Object.entries(serialized)) if (Array.isArray(value)) for (const v of value) parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(v)}`);\n\t\telse parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(value)}`);\n\t}\n\treturn parts.length > 0 ? \"?\" + parts.join(\"&\") : \"\";\n}\n/**\n* The base every request and every caller-built URL resolves against.\n*\n* `baseUrl` is optional because the common production shape is a Rebase\n* backend serving its own SPA, where the API is simply the page's origin.\n* Leaving it unset is therefore the *correct* configuration there — and the\n* one that keeps working when a second hostname (a custom domain) points at\n* the same app.\n*\n* When unset in a browser this resolves to the page origin rather than \"\".\n* Requests behave identically either way, but the empty string is a trap for\n* anything that builds a URL from `client.baseUrl`: `new URL(\"\" + path)`\n* throws, so apps \"fixed\" it by baking an absolute host into their bundle —\n* which is exactly what breaks the day a custom domain is added, and which no\n* amount of CORS configuration repairs, because a SameSite=Lax auth cookie is\n* not sent cross-site either.\n*/\nfunction resolveBaseUrl(configured) {\n\tif (configured) return configured.replace(/\\/$/, \"\");\n\tif (typeof window !== \"undefined\" && window.location?.origin) return window.location.origin;\n\treturn \"\";\n}\nfunction createTransport(config, environment) {\n\tconst fetchFn = config.fetch || globalThis.fetch;\n\tconst apiPath = config.apiPath || \"/api\";\n\tlet token = config.token;\n\tlet tokenGetter;\n\tlet onUnauthorizedHandler = config.onUnauthorized;\n\t/** Once per client, never per request — log spam is its own bug. */\n\tlet anonymousWarningIssued = false;\n\t/**\n\t* Warn a server-side caller that it built a client that can only ever be\n\t* anonymous. Deliberately checked at the *first request* rather than at\n\t* construction: `setToken()` / `setAuthTokenGetter()` and a server-side\n\t* `auth.signIn…()` (which calls `transport.setToken`) all land after the\n\t* constructor, and warning at construction would fire on every one of them.\n\t*/\n\tfunction warnIfAnonymousServerClient(activeToken) {\n\t\tif (anonymousWarningIssued) return;\n\t\tif (activeToken) return;\n\t\tif (tokenGetter) return;\n\t\tif (config.anonymous) return;\n\t\tif (environment?.credentialOutOfBand) return;\n\t\tif (!isServerLikeEnvironment()) return;\n\t\tanonymousWarningIssued = true;\n\t\tconsole.warn(ANONYMOUS_SERVER_CLIENT_WARNING);\n\t}\n\tfunction getHeaders(activeToken, init) {\n\t\treturn {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...activeToken ? { Authorization: `Bearer ${activeToken}` } : {},\n\t\t\t...init?.headers || {}\n\t\t};\n\t}\n\tasync function request(path, init) {\n\t\tconst url = resolveBaseUrl(config.baseUrl) + apiPath + path;\n\t\tlet activeToken = token;\n\t\tif (tokenGetter) try {\n\t\t\tconst fetched = await tokenGetter();\n\t\t\tif (fetched !== null && fetched !== void 0) activeToken = fetched;\n\t\t} catch (e) {}\n\t\twarnIfAnonymousServerClient(activeToken);\n\t\tconst headers = getHeaders(activeToken, init);\n\t\tif (init?.body instanceof FormData) delete headers[\"Content-Type\"];\n\t\tconst res = await fetchFn(url, {\n\t\t\t...init,\n\t\t\theaders\n\t\t});\n\t\tif (res.status === 204) return void 0;\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tlet body = {};\n\t\tif (text) try {\n\t\t\tbody = JSON.parse(text, rebaseReviver);\n\t\t} catch (e) {}\n\t\tconst getErrorField = (obj, field) => {\n\t\t\tconst err = obj?.error;\n\t\t\tif (err && typeof err === \"object\" && err !== null) return err[field];\n\t\t};\n\t\tif (res.status === 401 && onUnauthorizedHandler) {\n\t\t\tif (await onUnauthorizedHandler()) {\n\t\t\t\tlet retryToken = token;\n\t\t\t\tif (tokenGetter) try {\n\t\t\t\t\tconst fetched = await tokenGetter();\n\t\t\t\t\tif (fetched !== null && fetched !== void 0) retryToken = fetched;\n\t\t\t\t} catch (e) {}\n\t\t\t\tconst retryHeaders = getHeaders(retryToken, init);\n\t\t\t\tconst retryRes = await fetchFn(url, {\n\t\t\t\t\t...init,\n\t\t\t\t\theaders: retryHeaders\n\t\t\t\t});\n\t\t\t\tif (retryRes.status === 204) return void 0;\n\t\t\t\tconst retryText = await retryRes.text().catch(() => \"\");\n\t\t\t\tlet retryBody = {};\n\t\t\t\tif (retryText) try {\n\t\t\t\t\tretryBody = JSON.parse(retryText, rebaseReviver);\n\t\t\t\t} catch (e) {}\n\t\t\t\tif (!retryRes.ok) {\n\t\t\t\t\tlet fallbackMessage = retryRes.statusText;\n\t\t\t\t\tif (retryRes.status === 404 && !fallbackMessage) fallbackMessage = `Endpoint not found (${init?.method || \"GET\"} ${path}). This usually means the collection is not registered on the backend, or the frontend API URL configuration (e.g. VITE_API_URL) is missing or pointing to the wrong host.`;\n\t\t\t\t\tthrow new RebaseApiError$1(String(getErrorField(retryBody, \"message\") || fallbackMessage || `Request failed with status ${retryRes.status}`), {\n\t\t\t\t\t\tstatus: retryRes.status,\n\t\t\t\t\t\tcode: getErrorField(retryBody, \"code\"),\n\t\t\t\t\t\tdetails: getErrorField(retryBody, \"details\")\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn retryBody;\n\t\t\t}\n\t\t}\n\t\tif (!res.ok) {\n\t\t\tlet fallbackMessage = res.statusText;\n\t\t\tif (res.status === 404 && !fallbackMessage) fallbackMessage = `Endpoint not found (${init?.method || \"GET\"} ${path}). This usually means the collection is not registered on the backend, or the frontend API URL configuration (e.g. VITE_API_URL) is missing or pointing to the wrong host.`;\n\t\t\tthrow new RebaseApiError$1(String(getErrorField(body, \"message\") || fallbackMessage || `Request failed with status ${res.status}`), {\n\t\t\t\tstatus: res.status,\n\t\t\t\tcode: getErrorField(body, \"code\"),\n\t\t\t\tdetails: getErrorField(body, \"details\")\n\t\t\t});\n\t\t}\n\t\treturn body;\n\t}\n\treturn {\n\t\trequest,\n\t\tsetToken(newToken) {\n\t\t\ttoken = newToken || void 0;\n\t\t},\n\t\tsetAuthTokenGetter(getter) {\n\t\t\ttokenGetter = getter;\n\t\t},\n\t\tsetOnUnauthorized(handler) {\n\t\t\tonUnauthorizedHandler = handler;\n\t\t},\n\t\tget baseUrl() {\n\t\t\treturn resolveBaseUrl(config.baseUrl);\n\t\t},\n\t\tget apiPath() {\n\t\t\treturn apiPath;\n\t\t},\n\t\tget storageUrlOrigin() {\n\t\t\treturn config.storageUrlOrigin?.replace(/\\/$/, \"\") || void 0;\n\t\t},\n\t\tget fetchFn() {\n\t\t\treturn fetchFn;\n\t\t},\n\t\tgetHeaders: (init) => getHeaders(token, init),\n\t\tresolveToken: async () => {\n\t\t\tif (tokenGetter) try {\n\t\t\t\tconst fetched = await tokenGetter();\n\t\t\t\tif (fetched !== null && fetched !== void 0) return fetched;\n\t\t\t} catch (e) {}\n\t\t\treturn token || null;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/auth.ts\n/** Map a raw user object from an auth response (`/login`, `/refresh`, `/me`) to a `User`. */\nfunction mapRawUser(raw) {\n\treturn {\n\t\tuid: raw.uid,\n\t\temail: raw.email ?? null,\n\t\tdisplayName: raw.displayName ?? null,\n\t\tphotoURL: raw.photoURL ?? null,\n\t\tproviderId: raw.providerId ?? \"password\",\n\t\tisAnonymous: raw.isAnonymous ?? false,\n\t\temailVerified: raw.emailVerified,\n\t\troles: raw.roles,\n\t\tmetadata: raw.metadata\n\t};\n}\n/** Placeholder user, used only as a last resort when none can be resolved. */\nvar EMPTY_USER = {\n\tuid: \"\",\n\temail: null,\n\tdisplayName: null,\n\tphotoURL: null,\n\tproviderId: \"password\",\n\tisAnonymous: false\n};\nfunction createMemoryStorage() {\n\tconst store = {};\n\treturn {\n\t\tgetItem(key) {\n\t\t\treturn store[key] ?? null;\n\t\t},\n\t\tsetItem(key, value) {\n\t\t\tstore[key] = value;\n\t\t},\n\t\tremoveItem(key) {\n\t\t\tdelete store[key];\n\t\t}\n\t};\n}\nfunction detectStorage() {\n\ttry {\n\t\tif (typeof localStorage !== \"undefined\") {\n\t\t\tlocalStorage.setItem(\"__rebase_test__\", \"1\");\n\t\t\tlocalStorage.removeItem(\"__rebase_test__\");\n\t\t\treturn localStorage;\n\t\t}\n\t} catch (e) {}\n\treturn createMemoryStorage();\n}\nfunction createAuth(transport, options) {\n\tconst opts = options || {};\n\tconst storage = opts.storage || detectStorage();\n\tconst authPath = opts.authPath || \"/auth\";\n\tconst autoRefresh = opts.autoRefresh !== false;\n\tconst persistSession = opts.persistSession !== false;\n\tconst authFlowMode = opts.authFlowMode || \"json\";\n\tconst STORAGE_KEY = \"rebase_auth\";\n\tconst REFRESH_BUFFER_MS = 12e4;\n\tconst MAX_REFRESH_RETRIES = 5;\n\tconst REFRESH_RETRY_BASE_MS = 1e3;\n\tconst REFRESH_RETRY_MAX_MS = 3e4;\n\tlet currentSession = null;\n\tconst listeners = /* @__PURE__ */ new Set();\n\tlet refreshTimeout = null;\n\tlet inFlightRefresh = null;\n\tlet resolveInitialized;\n\tconst isInitialized = new Promise((resolve) => {\n\t\tresolveInitialized = resolve;\n\t});\n\tfunction authUrl(endpoint) {\n\t\treturn transport.baseUrl + transport.apiPath + authPath + endpoint;\n\t}\n\tfunction getFetch() {\n\t\treturn transport.fetchFn || globalThis.fetch;\n\t}\n\tfunction throwApiError(status, body, statusText) {\n\t\tthrow new RebaseApiError(body?.error?.message || body?.message || statusText, {\n\t\t\tstatus,\n\t\t\tcode: body?.error?.code || body?.code,\n\t\t\tdetails: body?.error?.details || body?.details\n\t\t});\n\t}\n\tfunction emit(event, session) {\n\t\tfor (const fn of listeners) try {\n\t\t\tfn(event, session);\n\t\t} catch (e) {}\n\t}\n\tfunction saveSession(session) {\n\t\tif (!persistSession || authFlowMode === \"cookie\") return;\n\t\ttry {\n\t\t\tstorage.setItem(STORAGE_KEY, JSON.stringify(session));\n\t\t} catch (e) {}\n\t}\n\tfunction clearStoredSession() {\n\t\ttry {\n\t\t\tstorage.removeItem(STORAGE_KEY);\n\t\t} catch (e) {}\n\t}\n\tfunction loadStoredSession() {\n\t\ttry {\n\t\t\tconst raw = storage.getItem(STORAGE_KEY);\n\t\t\tif (raw) return JSON.parse(raw);\n\t\t} catch (e) {}\n\t\treturn null;\n\t}\n\t/**\n\t* A refresh failure is only fatal if the refresh token itself is rejected\n\t* (expired / invalid / forbidden). Network blips, timeouts, and 5xx (e.g. a\n\t* backend restart mid-session) are transient and must NOT log the user out.\n\t*/\n\tfunction isFatalRefreshError(err) {\n\t\tif (!(err instanceof RebaseApiError)) return false;\n\t\tif (err.code === \"TOKEN_ALREADY_USED\") return false;\n\t\tif (err.code === \"INVALID_TOKEN\" || err.code === \"TOKEN_EXPIRED\") return true;\n\t\treturn err.status === 401 || err.status === 403;\n\t}\n\t/**\n\t* Drop this client's session without telling the server.\n\t*\n\t* `signOut()` is a user action: it POSTs /logout, which revokes the whole\n\t* sign-in. That is the wrong hammer for a refresh that failed. Our token\n\t* may be stale precisely because a sibling tab holds a live one, and\n\t* logging out on its behalf would turn one tab's bad luck into everybody\n\t* being signed out — the exact failure this work exists to remove.\n\t*/\n\tfunction abandonSessionLocally() {\n\t\tcurrentSession = null;\n\t\tclearStoredSession();\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t\ttransport.setToken(null);\n\t\temit(\"SIGNED_OUT\", null);\n\t}\n\t/**\n\t* Recover from a 401 on an ordinary API request.\n\t*\n\t* Returns `true` when the caller should retry — we minted a fresh access\n\t* token. When the refresh is rejected *fatally* (the refresh token itself\n\t* is invalid, expired or revoked) this client can no longer act as the\n\t* user at all, so we drop the session and emit `SIGNED_OUT`. UIs gate on\n\t* that event, so they show their login screen instead of leaving the user\n\t* staring at \"Invalid or expired token\" on every view.\n\t*\n\t* Transient failures (offline, 5xx, backend restarting) keep the session:\n\t* the scheduled refresh backs off and retries, and the token is very\n\t* likely still good once the backend answers again.\n\t*/\n\tasync function handleUnauthorized() {\n\t\tif (!currentSession) return false;\n\t\tif (authFlowMode !== \"cookie\" && !currentSession.refreshToken) {\n\t\t\tabandonSessionLocally();\n\t\t\treturn false;\n\t\t}\n\t\ttry {\n\t\t\tawait refreshSession();\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tif (isFatalRefreshError(err)) abandonSessionLocally();\n\t\t\treturn false;\n\t\t}\n\t}\n\tasync function attemptScheduledRefresh(attempt) {\n\t\ttry {\n\t\t\tawait refreshSession();\n\t\t} catch (err) {\n\t\t\tif (isFatalRefreshError(err)) {\n\t\t\t\tabandonSessionLocally();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (attempt >= MAX_REFRESH_RETRIES) {\n\t\t\t\tabandonSessionLocally();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst backoff = Math.min(REFRESH_RETRY_BASE_MS * 2 ** attempt, REFRESH_RETRY_MAX_MS);\n\t\t\trefreshTimeout = setTimeout(() => {\n\t\t\t\tattemptScheduledRefresh(attempt + 1);\n\t\t\t}, backoff);\n\t\t}\n\t}\n\tfunction scheduleRefresh(expiresAt) {\n\t\tif (refreshTimeout) clearTimeout(refreshTimeout);\n\t\tif (!autoRefresh) return;\n\t\tconst delay = expiresAt - REFRESH_BUFFER_MS - Date.now();\n\t\tif (delay <= 0) {\n\t\t\tattemptScheduledRefresh(0);\n\t\t\treturn;\n\t\t}\n\t\trefreshTimeout = setTimeout(() => {\n\t\t\tattemptScheduledRefresh(0);\n\t\t}, delay);\n\t}\n\t/**\n\t* Stop the scheduled token refresh, leaving the session itself alone.\n\t*\n\t* This is teardown, not sign-out. `scheduleRefresh` arms an ordinary\n\t* `setTimeout` up to a token lifetime away, and it is not `unref`'d — so on\n\t* Node it holds the event loop open by itself. `client.close()` promised\n\t* that \"a script that does not call this will not exit on its own\", which\n\t* was true, while the converse it plainly implies was not: a signed-in\n\t* client that closed its socket still hung, because this timer outlived it.\n\t* Any script, cron handler or job that signs in hit that.\n\t*\n\t* Deliberately does NOT clear the session, touch storage, or emit\n\t* SIGNED_OUT. Closing a client is not the user signing out — `signOut()`\n\t* POSTs /logout and revokes the whole sign-in, which is the wrong hammer\n\t* (see `abandonSessionLocally`) — and a persisted session must still be\n\t* there for the next client to restore.\n\t*/\n\tfunction stopAutoRefresh() {\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t}\n\tfunction handleAuthResponse(data, event) {\n\t\tconst user = mapRawUser(data.user);\n\t\tconst session = {\n\t\t\taccessToken: data.tokens.accessToken,\n\t\t\trefreshToken: data.tokens.refreshToken || currentSession?.refreshToken || \"\",\n\t\t\texpiresAt: data.tokens.accessTokenExpiresAt,\n\t\t\tuser\n\t\t};\n\t\tcurrentSession = session;\n\t\tsaveSession(session);\n\t\ttransport.setToken(session.accessToken);\n\t\tscheduleRefresh(session.expiresAt);\n\t\temit(event || \"SIGNED_IN\", session);\n\t\treturn session;\n\t}\n\tasync function signInWithEmail(email, password) {\n\t\tconst res = await getFetch()(authUrl(\"/login\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\temail,\n\t\t\t\tpassword\n\t\t\t}),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function signUp(email, password, displayName) {\n\t\tconst fetchFn = getFetch();\n\t\tconst payload = {\n\t\t\temail,\n\t\t\tpassword\n\t\t};\n\t\tif (displayName !== void 0) payload.displayName = displayName;\n\t\tconst res = await fetchFn(authUrl(\"/register\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\t/**\n\t* Sign in with Google.\n\t*\n\t* Supports three invocation styles:\n\t* - `signInWithGoogle({ idToken })` — ID-token flow (One Tap / Sign In button)\n\t* - `signInWithGoogle({ accessToken })` — Access-token flow (popup)\n\t* - `signInWithGoogle({ code, redirectUri })` — Authorization code flow (most secure)\n\t*/\n\tasync function signInWithGoogle(payload) {\n\t\tconst res = await getFetch()(authUrl(\"/google\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst responseBody = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, responseBody, res.statusText);\n\t\tconst session = handleAuthResponse(responseBody, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function signInWithLinkedin(code, redirectUri) {\n\t\tconst res = await getFetch()(authUrl(\"/linkedin\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tcode,\n\t\t\t\tredirectUri\n\t\t\t}),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\t/**\n\t* Generic OAuth sign-in. Posts the given payload to `/auth/{providerId}`.\n\t* Use this for any provider registered on the backend.\n\t*/\n\tasync function signInWithOAuth(providerId, payload) {\n\t\tconst res = await getFetch()(authUrl(`/${providerId}`), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function signInWithGitHub(code, redirectUri) {\n\t\treturn signInWithOAuth(\"github\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithMicrosoft(code, redirectUri) {\n\t\treturn signInWithOAuth(\"microsoft\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithApple(code, redirectUri, user) {\n\t\treturn signInWithOAuth(\"apple\", {\n\t\t\tcode,\n\t\t\tredirectUri,\n\t\t\tuser\n\t\t});\n\t}\n\tasync function signInWithFacebook(code, redirectUri) {\n\t\treturn signInWithOAuth(\"facebook\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithTwitter(code, redirectUri, codeVerifier) {\n\t\treturn signInWithOAuth(\"twitter\", {\n\t\t\tcode,\n\t\t\tredirectUri,\n\t\t\tcodeVerifier\n\t\t});\n\t}\n\tasync function signInWithDiscord(code, redirectUri) {\n\t\treturn signInWithOAuth(\"discord\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithGitLab(code, redirectUri) {\n\t\treturn signInWithOAuth(\"gitlab\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithBitbucket(code, redirectUri) {\n\t\treturn signInWithOAuth(\"bitbucket\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithSlack(code, redirectUri) {\n\t\treturn signInWithOAuth(\"slack\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithSpotify(code, redirectUri) {\n\t\treturn signInWithOAuth(\"spotify\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signOut() {\n\t\tconst fetchFn = getFetch();\n\t\ttry {\n\t\t\tif (authFlowMode === \"cookie\" || currentSession?.refreshToken) await fetchFn(authUrl(\"/logout\"), {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ refreshToken: currentSession?.refreshToken }),\n\t\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t\t});\n\t\t} catch (e) {}\n\t\tcurrentSession = null;\n\t\tclearStoredSession();\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t\ttransport.setToken(null);\n\t\temit(\"SIGNED_OUT\", null);\n\t}\n\t/**\n\t* Serialise refreshes across TABS, not just within one.\n\t*\n\t* The in-flight promise below covers callers inside a single JavaScript\n\t* context. It does nothing about the far more common case: two tabs of the\n\t* same app booting together, each firing its own /refresh with the same\n\t* cookie. The server tolerates that now (superseded tokens stay usable for\n\t* a grace window), but tolerating a stampede is not the same as avoiding\n\t* one, and every extra rotation is another chance to end up holding a\n\t* token whose response never arrived.\n\t*\n\t* Web Locks are best-effort on purpose. supabase-js shipped this and then\n\t* spent a year fielding deadlock reports — a lock held by a crashed or\n\t* frozen tab must never be able to wedge sign-in — so a lock we cannot\n\t* take within the timeout is simply not taken, and the refresh proceeds\n\t* unserialised, exactly as it did before.\n\t*/\n\tconst REFRESH_LOCK_NAME = \"rebase-auth-refresh\";\n\tconst REFRESH_LOCK_TIMEOUT_MS = 5e3;\n\tasync function withRefreshLock(fn) {\n\t\tconst locks = globalThis.navigator?.locks;\n\t\tif (!locks?.request) return fn();\n\t\tconst controller = new AbortController();\n\t\tconst giveUp = setTimeout(() => controller.abort(), REFRESH_LOCK_TIMEOUT_MS);\n\t\ttry {\n\t\t\treturn await locks.request(REFRESH_LOCK_NAME, { signal: controller.signal }, async () => fn());\n\t\t} catch (e) {\n\t\t\tif (e?.name !== \"AbortError\") throw e;\n\t\t\treturn fn();\n\t\t} finally {\n\t\t\tclearTimeout(giveUp);\n\t\t}\n\t}\n\tfunction refreshSession() {\n\t\tif (inFlightRefresh) return inFlightRefresh;\n\t\tinFlightRefresh = withRefreshLock(() => doRefreshSession()).finally(() => {\n\t\t\tinFlightRefresh = null;\n\t\t});\n\t\treturn inFlightRefresh;\n\t}\n\tasync function doRefreshSession() {\n\t\tif (authFlowMode !== \"cookie\" && !currentSession?.refreshToken) throw new Error(\"No active session to refresh\");\n\t\tconst res = await getFetch()(authUrl(\"/refresh\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ refreshToken: currentSession?.refreshToken }),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst accessToken = body.tokens.accessToken;\n\t\ttransport.setToken(accessToken);\n\t\tlet user = currentSession?.user;\n\t\tif (body.user && typeof body.user.uid === \"string\") user = mapRawUser(body.user);\n\t\telse if (!user || !user.uid) try {\n\t\t\tuser = await getUser();\n\t\t} catch {}\n\t\tconst session = {\n\t\t\taccessToken,\n\t\t\trefreshToken: body.tokens.refreshToken || currentSession?.refreshToken || \"\",\n\t\t\texpiresAt: body.tokens.accessTokenExpiresAt,\n\t\t\tuser: user ?? EMPTY_USER\n\t\t};\n\t\tcurrentSession = session;\n\t\tsaveSession(session);\n\t\ttransport.setToken(session.accessToken);\n\t\tscheduleRefresh(session.expiresAt);\n\t\temit(\"TOKEN_REFRESHED\", session);\n\t\treturn session;\n\t}\n\tasync function getUser() {\n\t\treturn (await transport.request(authPath + \"/me\", { method: \"GET\" })).user;\n\t}\n\t/**\n\t* Resolve an email to a minimal public profile (`uid`, `displayName`,\n\t* `photoURL`) for invite-by-email flows. Returns `null` when no account\n\t* matches. Requires the backend to opt in via `auth.allowUserLookup`;\n\t* otherwise the endpoint is absent and this rejects.\n\t*/\n\tasync function findUserByEmail(email) {\n\t\treturn (await transport.request(authPath + \"/find-user\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify({ email })\n\t\t})).user;\n\t}\n\tasync function updateUser(updates) {\n\t\tconst data = await transport.request(authPath + \"/me\", {\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody: JSON.stringify(updates)\n\t\t});\n\t\tif (currentSession) {\n\t\t\tcurrentSession = {\n\t\t\t\t...currentSession,\n\t\t\t\tuser: data.user\n\t\t\t};\n\t\t\tsaveSession(currentSession);\n\t\t\temit(\"USER_UPDATED\", currentSession);\n\t\t}\n\t\treturn data.user;\n\t}\n\tasync function resetPasswordForEmail(email) {\n\t\tconst res = await getFetch()(authUrl(\"/forgot-password\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ email })\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function resetPassword(token, password) {\n\t\tconst res = await getFetch()(authUrl(\"/reset-password\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttoken,\n\t\t\t\tpassword\n\t\t\t})\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function changePassword(oldPassword, newPassword) {\n\t\treturn transport.request(authPath + \"/change-password\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify({\n\t\t\t\toldPassword,\n\t\t\t\tnewPassword\n\t\t\t})\n\t\t});\n\t}\n\t/**\n\t* Link an OAuth provider to the **currently signed-in** account.\n\t*\n\t* Use this when `signIn*` failed with `EMAIL_NOT_VERIFIED` — an account\n\t* with that email already exists under a different sign-in method — or to\n\t* attach a provider whose email differs from the account's.\n\t*\n\t* The payload is the same one the provider's sign-in method takes, e.g.\n\t* `linkProvider(\"google\", { idToken })`.\n\t*\n\t* Unlike sign-in, this does not require the provider to have verified the\n\t* email, and the emails need not match: the active session already proves\n\t* account ownership.\n\t*\n\t* Throws `IDENTITY_ALREADY_LINKED` (409) if that provider identity is\n\t* attached to a different user. Succeeds idempotently (`alreadyLinked:\n\t* true`) if it is already attached to the current one.\n\t*/\n\tasync function linkProvider(providerId, payload) {\n\t\treturn transport.request(authPath + \"/link/\" + providerId, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t}\n\tasync function sendVerificationEmail() {\n\t\treturn transport.request(authPath + \"/send-verification\", { method: \"POST\" });\n\t}\n\tasync function verifyEmail(token) {\n\t\tconst res = await getFetch()(authUrl(\"/verify-email?token=\" + encodeURIComponent(token)), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" }\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function sendMagicLink(email) {\n\t\tconst res = await getFetch()(authUrl(\"/magic-link\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ email })\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function verifyMagicLink(token) {\n\t\tconst res = await getFetch()(authUrl(\"/magic-link/verify\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ token }),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function getSessions() {\n\t\treturn (await transport.request(authPath + \"/sessions\", { method: \"GET\" })).sessions;\n\t}\n\tasync function revokeSession(sessionId) {\n\t\treturn transport.request(authPath + \"/sessions/\" + encodeURIComponent(sessionId), { method: \"DELETE\" });\n\t}\n\tasync function revokeAllSessions() {\n\t\tconst result = await transport.request(authPath + \"/sessions\", { method: \"DELETE\" });\n\t\tcurrentSession = null;\n\t\tclearStoredSession();\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t\ttransport.setToken(null);\n\t\temit(\"SIGNED_OUT\", null);\n\t\treturn result;\n\t}\n\tasync function getAuthConfig() {\n\t\tconst res = await getFetch()(authUrl(\"/config\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" }\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tfunction getSession() {\n\t\treturn currentSession;\n\t}\n\tfunction onAuthStateChange(callback) {\n\t\tlisteners.add(callback);\n\t\treturn () => listeners.delete(callback);\n\t}\n\tif (persistSession) {\n\t\tconst stored = loadStoredSession();\n\t\tif (stored && stored.accessToken) if (stored.expiresAt > Date.now()) {\n\t\t\tcurrentSession = stored;\n\t\t\ttransport.setToken(stored.accessToken);\n\t\t\tscheduleRefresh(stored.expiresAt);\n\t\t\tresolveInitialized();\n\t\t} else if (authFlowMode === \"cookie\" || stored.refreshToken) {\n\t\t\tcurrentSession = stored;\n\t\t\trefreshSession().then(() => {\n\t\t\t\tresolveInitialized();\n\t\t\t}).catch(() => {\n\t\t\t\tcurrentSession = null;\n\t\t\t\tclearStoredSession();\n\t\t\t\ttransport.setToken(null);\n\t\t\t\tresolveInitialized();\n\t\t\t});\n\t\t} else resolveInitialized();\n\t\telse if (authFlowMode === \"cookie\") refreshSession().then(() => {\n\t\t\tresolveInitialized();\n\t\t}).catch(() => {\n\t\t\tresolveInitialized();\n\t\t});\n\t\telse resolveInitialized();\n\t} else resolveInitialized();\n\treturn {\n\t\tsignInWithEmail,\n\t\tsignUp,\n\t\tsignInWithGoogle,\n\t\tsignInWithLinkedin,\n\t\tsignInWithOAuth,\n\t\tsignInWithGitHub,\n\t\tsignInWithMicrosoft,\n\t\tsignInWithApple,\n\t\tsignInWithFacebook,\n\t\tsignInWithTwitter,\n\t\tsignInWithDiscord,\n\t\tsignInWithGitLab,\n\t\tsignInWithBitbucket,\n\t\tsignInWithSlack,\n\t\tsignInWithSpotify,\n\t\tsignOut,\n\t\tstopAutoRefresh,\n\t\trefreshSession,\n\t\thandleUnauthorized,\n\t\tgetUser,\n\t\tfindUserByEmail,\n\t\tupdateUser,\n\t\tresetPasswordForEmail,\n\t\tresetPassword,\n\t\tchangePassword,\n\t\tlinkProvider,\n\t\tsendVerificationEmail,\n\t\tverifyEmail,\n\t\tsendMagicLink,\n\t\tverifyMagicLink,\n\t\tgetSessions,\n\t\trevokeSession,\n\t\trevokeAllSessions,\n\t\tgetAuthConfig,\n\t\tgetSession,\n\t\tonAuthStateChange,\n\t\tcanRestoreSession: () => persistSession || authFlowMode === \"cookie\",\n\t\tisInitialized: () => isInitialized\n\t};\n}\nfunction createCookieStorage(options = {}) {\n\tconst defaultOptions = {\n\t\tpath: \"/\",\n\t\tsameSite: \"Lax\",\n\t\t...options\n\t};\n\treturn {\n\t\tgetItem(key) {\n\t\t\tif (typeof document === \"undefined\") return null;\n\t\t\tconst nameEQ = encodeURIComponent(key) + \"=\";\n\t\t\tconst ca = document.cookie.split(\";\");\n\t\t\tfor (let i = 0; i < ca.length; i++) {\n\t\t\t\tlet c = ca[i];\n\t\t\t\twhile (c.charAt(0) === \" \") c = c.substring(1, c.length);\n\t\t\t\tif (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tsetItem(key, value) {\n\t\t\tif (typeof document === \"undefined\") return;\n\t\t\tlet cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n\t\t\tif (defaultOptions.path) cookieStr += `; path=${defaultOptions.path}`;\n\t\t\tif (defaultOptions.domain) cookieStr += `; domain=${defaultOptions.domain}`;\n\t\t\tif (defaultOptions.maxAge !== void 0) cookieStr += `; max-age=${defaultOptions.maxAge}`;\n\t\t\telse cookieStr += `; max-age=${365 * 24 * 60 * 60}`;\n\t\t\tif (defaultOptions.secure) cookieStr += \"; secure\";\n\t\t\tif (defaultOptions.sameSite) cookieStr += `; samesite=${defaultOptions.sameSite}`;\n\t\t\tdocument.cookie = cookieStr;\n\t\t},\n\t\tremoveItem(key) {\n\t\t\tif (typeof document === \"undefined\") return;\n\t\t\tlet cookieStr = `${encodeURIComponent(key)}=; path=${defaultOptions.path || \"/\"}; max-age=-1`;\n\t\t\tif (defaultOptions.domain) cookieStr += `; domain=${defaultOptions.domain}`;\n\t\t\tdocument.cookie = cookieStr;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/admin.ts\nfunction createAdmin(transport, options) {\n\tconst adminPath = (options || {}).adminPath || \"/admin\";\n\tasync function listUsers() {\n\t\treturn transport.request(adminPath + \"/users\", { method: \"GET\" });\n\t}\n\tasync function listUsersPaginated(options) {\n\t\tconst params = new URLSearchParams();\n\t\tif (options?.limit !== void 0) params.set(\"limit\", String(options.limit));\n\t\tif (options?.offset !== void 0) params.set(\"offset\", String(options.offset));\n\t\tif (options?.search) params.set(\"search\", options.search);\n\t\tif (options?.orderBy) params.set(\"orderBy\", options.orderBy);\n\t\tif (options?.orderDir) params.set(\"orderDir\", options.orderDir);\n\t\tconst qs = params.toString();\n\t\treturn transport.request(adminPath + \"/users\" + (qs ? \"?\" + qs : \"\"), { method: \"GET\" });\n\t}\n\tasync function getUser(userId) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId), { method: \"GET\" });\n\t}\n\tasync function createUser(data) {\n\t\treturn transport.request(adminPath + \"/users\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\tasync function updateUser(userId, data) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId), {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\tasync function deleteUser(userId) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId), { method: \"DELETE\" });\n\t}\n\tasync function resetPassword(userId, options) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId) + \"/reset-password\", {\n\t\t\tmethod: \"POST\",\n\t\t\t...options?.password ? { body: JSON.stringify({ password: options.password }) } : {}\n\t\t});\n\t}\n\tasync function listRoles() {\n\t\treturn transport.request(adminPath + \"/roles\", { method: \"GET\" });\n\t}\n\tasync function bootstrap() {\n\t\treturn transport.request(adminPath + \"/bootstrap\", { method: \"POST\" });\n\t}\n\treturn {\n\t\tlistUsers,\n\t\tlistUsersPaginated,\n\t\tgetUser,\n\t\tcreateUser,\n\t\tupdateUser,\n\t\tdeleteUser,\n\t\tresetPassword,\n\t\tlistRoles,\n\t\tbootstrap\n\t};\n}\n//#endregion\n//#region src/cron.ts\nfunction createCron(transport, options) {\n\tconst cronPath = options?.cronPath || \"/cron\";\n\tasync function listJobs() {\n\t\treturn transport.request(cronPath, { method: \"GET\" });\n\t}\n\tasync function getJob(jobId) {\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId), { method: \"GET\" });\n\t}\n\tasync function triggerJob(jobId) {\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId) + \"/trigger\", { method: \"POST\" });\n\t}\n\tasync function getJobLogs(jobId, options) {\n\t\tconst params = new URLSearchParams();\n\t\tif (options?.limit !== void 0) params.set(\"limit\", String(options.limit));\n\t\tconst qs = params.toString();\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId) + \"/logs\" + (qs ? \"?\" + qs : \"\"), { method: \"GET\" });\n\t}\n\tasync function toggleJob(jobId, enabled) {\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId), {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: JSON.stringify({ enabled })\n\t\t});\n\t}\n\treturn {\n\t\tlistJobs,\n\t\tgetJob,\n\t\ttriggerJob,\n\t\tgetJobLogs,\n\t\ttoggleJob\n\t};\n}\n//#endregion\n//#region src/backups.ts\nfunction createBackups(transport, options) {\n\tconst backupsPath = options?.backupsPath || \"/admin/backups\";\n\tasync function list() {\n\t\treturn transport.request(backupsPath, { method: \"GET\" });\n\t}\n\t/**\n\t* Download a backup's bytes. Uses an authenticated fetch (not the JSON\n\t* transport) so the octet-stream response comes back as a Blob.\n\t*/\n\tasync function download(key) {\n\t\tconst token = await transport.resolveToken();\n\t\tconst url = `${transport.baseUrl}${transport.apiPath}${backupsPath}/download?key=${encodeURIComponent(key)}`;\n\t\tconst res = await fetch(url, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: token ? { Authorization: `Bearer ${token}` } : {}\n\t\t});\n\t\tif (!res.ok) throw new Error(`Failed to download backup (${res.status})`);\n\t\treturn res.blob();\n\t}\n\treturn {\n\t\tlist,\n\t\tdownload\n\t};\n}\n//#endregion\n//#region src/api-keys.ts\n/**\n* Creates a client for managing API keys via the admin routes.\n*\n* @param transport - The shared HTTP transport created by `createTransport`.\n* @param options - Optional overrides (e.g. a custom base path).\n*/\nfunction createApiKeys(transport, options) {\n\tconst apiKeysPath = options?.apiKeysPath || \"/admin/api-keys\";\n\t/** List all API keys (masked). */\n\tasync function listKeys() {\n\t\treturn transport.request(apiKeysPath, { method: \"GET\" });\n\t}\n\t/** Get a single API key by ID (masked). */\n\tasync function getKey(id) {\n\t\treturn transport.request(apiKeysPath + \"/\" + encodeURIComponent(id), { method: \"GET\" });\n\t}\n\t/** Create a new API key. The full secret is included in the response. */\n\tasync function createKey(data) {\n\t\treturn transport.request(apiKeysPath, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\t/** Update an existing API key. */\n\tasync function updateKey(id, data) {\n\t\treturn transport.request(apiKeysPath + \"/\" + encodeURIComponent(id), {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\t/** Revoke (soft-delete) an API key. */\n\tasync function revokeKey(id) {\n\t\treturn transport.request(apiKeysPath + \"/\" + encodeURIComponent(id), { method: \"DELETE\" });\n\t}\n\treturn {\n\t\tlistKeys,\n\t\tgetKey,\n\t\tcreateKey,\n\t\tupdateKey,\n\t\trevokeKey\n\t};\n}\n//#endregion\n//#region src/sdk_query_builder.ts\n/**\n* SDK Query Builder — returns flat rows (`FindResult<M>`) instead of\n* Entity-wrapped results (`FindResponse<M>`).\n*\n* @example\n* const { data } = await rebase.data.posts\n* .where(\"status\", \"==\", \"published\")\n* .orderBy(\"created_at\", \"desc\")\n* .limit(10)\n* .find();\n*\n* console.log(data[0].title); // flat access\n*/\nvar SDKQueryBuilder = class {\n\tcollection;\n\tparams = { where: {} };\n\tconstructor(collection) {\n\t\tthis.collection = collection;\n\t}\n\twhere(columnOrCondition, operator, value) {\n\t\tif (typeof columnOrCondition === \"object\" && columnOrCondition !== null && \"type\" in columnOrCondition) {\n\t\t\tthis.params.logical = columnOrCondition;\n\t\t\treturn this;\n\t\t}\n\t\tif (!this.params.where) this.params.where = {};\n\t\tconst column = columnOrCondition;\n\t\tconst condition = [operator, value];\n\t\tconst existing = this.params.where[column];\n\t\tif (existing === void 0) this.params.where[column] = condition;\n\t\telse if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) this.params.where[column].push(condition);\n\t\telse {\n\t\t\tlet firstCondition;\n\t\t\tif (Array.isArray(existing) && existing.length === 2 && typeof existing[0] === \"string\") firstCondition = existing;\n\t\t\telse firstCondition = [\"==\", existing];\n\t\t\tthis.params.where[column] = [firstCondition, condition];\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Order the results by a specific column.\n\t*/\n\torderBy(column, direction = \"asc\") {\n\t\tthis.params.orderBy = [column, direction];\n\t\treturn this;\n\t}\n\t/**\n\t* Limit the number of results returned.\n\t*/\n\tlimit(count) {\n\t\tthis.params.limit = count;\n\t\treturn this;\n\t}\n\t/**\n\t* Skip the first N results.\n\t*/\n\toffset(count) {\n\t\tthis.params.offset = count;\n\t\treturn this;\n\t}\n\t/**\n\t* Set a free-text search string if supported by the backend.\n\t*/\n\tsearch(searchString) {\n\t\tthis.params.searchString = searchString;\n\t\treturn this;\n\t}\n\t/**\n\t* Include related entities in the response.\n\t* Relations will be populated with full data instead of just IDs.\n\t*\n\t* @param relations - Relation names to include, or \"*\" for all.\n\t* @example\n\t* client.data.posts.include(\"tags\", \"author\").find()\n\t*/\n\tinclude(...relations) {\n\t\tthis.params.include = relations;\n\t\treturn this;\n\t}\n\t/**\n\t* Execute the find query and return the results as flat rows.\n\t*/\n\tasync find() {\n\t\treturn this.collection.find(this.params);\n\t}\n\t/**\n\t* Count the records matching this query.\n\t*/\n\tasync count() {\n\t\tif (!this.collection.count) throw new Error(\"count() is not supported by this collection client.\");\n\t\treturn this.collection.count(this.params);\n\t}\n\t/**\n\t* Listen to realtime updates matching this query.\n\t*/\n\tlisten(onUpdate, onError) {\n\t\tif (!this.collection.listen) throw new Error(\"Listen is only available when RebaseClient is configured with a websocketUrl, and not when it was created with realtime: false.\");\n\t\treturn this.collection.listen(this.params, onUpdate, onError);\n\t}\n};\n//#endregion\n//#region src/collection.ts\nfunction createCollectionClient(transport, slug, ws) {\n\tconst basePath = `/data/${slug}`;\n\tconst client = {\n\t\tasync find(params) {\n\t\t\tconst qs = buildQueryString(params);\n\t\t\tconst raw = await transport.request(basePath + qs, { method: \"GET\" });\n\t\t\treturn {\n\t\t\t\tdata: raw.data || [],\n\t\t\t\tmeta: raw.meta\n\t\t\t};\n\t\t},\n\t\titerate(params) {\n\t\t\treturn paginateFind((p) => client.find(p), params, slug);\n\t\t},\n\t\tfindAll(params) {\n\t\t\treturn collectAllPages((p) => client.find(p), params, slug);\n\t\t},\n\t\tasync findById(id) {\n\t\t\ttry {\n\t\t\t\tconst raw = await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, { method: \"GET\" });\n\t\t\t\tif (!raw) return void 0;\n\t\t\t\treturn raw;\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof RebaseApiError && err.status === 404) return;\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t\tasync create(data, id, options) {\n\t\t\tconst body = { ...data };\n\t\t\tif (id !== void 0) body.id = id;\n\t\t\treturn await transport.request(basePath, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\t...options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}\n\t\t\t});\n\t\t},\n\t\tasync createMany(data, options) {\n\t\t\tif (!Array.isArray(data)) throw new TypeError(\"createMany expects an array of records.\");\n\t\t\tif (data.length === 0) return [];\n\t\t\treturn (await transport.request(`${basePath}/bulk`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\trows: data,\n\t\t\t\t\t...options?.upsert ? { upsert: true } : {}\n\t\t\t\t})\n\t\t\t})).data || [];\n\t\t},\n\t\tasync update(id, data) {\n\t\t\treturn await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, {\n\t\t\t\tmethod: \"PUT\",\n\t\t\t\tbody: JSON.stringify(data)\n\t\t\t});\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait transport.request(`${basePath}/${encodeURIComponent(String(id))}`, { method: \"DELETE\" });\n\t\t},\n\t\tasync count(params) {\n\t\t\tconst qs = buildQueryString({\n\t\t\t\t...params,\n\t\t\t\tlimit: void 0,\n\t\t\t\toffset: void 0,\n\t\t\t\tinclude: void 0\n\t\t\t});\n\t\t\treturn (await transport.request(basePath + \"/count\" + qs, { method: \"GET\" })).count ?? 0;\n\t\t},\n\t\tobserve(params, onResult, onError, options) {\n\t\t\tlet closed = false;\n\t\t\tconst emit = (result) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tonResult({\n\t\t\t\t\t...result,\n\t\t\t\t\tfromCache: false,\n\t\t\t\t\thasPendingWrites: false,\n\t\t\t\t\tpartial: false\n\t\t\t\t});\n\t\t\t};\n\t\t\tclient.find(params).then(emit).catch((error) => {\n\t\t\t\tif (!closed) onError?.(error);\n\t\t\t});\n\t\t\tconst live = options?.realtime !== false && client.listen ? client.listen(params, emit, onError) : void 0;\n\t\t\treturn () => {\n\t\t\t\tclosed = true;\n\t\t\t\tlive?.();\n\t\t\t};\n\t\t},\n\t\tobserveById(id, onResult, onError, options) {\n\t\t\tlet closed = false;\n\t\t\tconst emit = (row) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tonResult(row, {\n\t\t\t\t\tfromCache: false,\n\t\t\t\t\thasPendingWrites: false\n\t\t\t\t});\n\t\t\t};\n\t\t\tclient.findById(id).then(emit).catch((error) => {\n\t\t\t\tif (!closed) onError?.(error);\n\t\t\t});\n\t\t\tconst live = options?.realtime !== false && client.listenById ? client.listenById(id, emit, onError) : void 0;\n\t\t\treturn () => {\n\t\t\t\tclosed = true;\n\t\t\t\tlive?.();\n\t\t\t};\n\t\t},\n\t\twhere(columnOrCondition, operator, value) {\n\t\t\tconst builder = new SDKQueryBuilder(client);\n\t\t\tif (typeof columnOrCondition === \"object\") return builder.where(columnOrCondition);\n\t\t\treturn builder.where(columnOrCondition, operator, value);\n\t\t},\n\t\torderBy(column, direction) {\n\t\t\treturn new SDKQueryBuilder(client).orderBy(column, direction);\n\t\t},\n\t\tlimit(count) {\n\t\t\treturn new SDKQueryBuilder(client).limit(count);\n\t\t},\n\t\toffset(count) {\n\t\t\treturn new SDKQueryBuilder(client).offset(count);\n\t\t},\n\t\tsearch(searchString) {\n\t\t\treturn new SDKQueryBuilder(client).search(searchString);\n\t\t},\n\t\tinclude(...relations) {\n\t\t\treturn new SDKQueryBuilder(client).include(...relations);\n\t\t}\n\t};\n\tif (ws) {\n\t\tclient.listen = (params, onUpdate, onError) => {\n\t\t\tlet active = true;\n\t\t\tlet lastUpdateId = 0;\n\t\t\tconst unsub = ws.listenCollection({\n\t\t\t\tpath: slug,\n\t\t\t\tfilter: params?.where,\n\t\t\t\tlimit: params?.limit,\n\t\t\t\tstartAfter: params?.offset ? String(params.offset) : void 0,\n\t\t\t\torderBy: params?.orderBy?.[0],\n\t\t\t\torder: params?.orderBy?.[1],\n\t\t\t\tsearchString: params?.searchString\n\t\t\t}, (incomingRows) => {\n\t\t\t\tconst currentUpdateId = ++lastUpdateId;\n\t\t\t\tconst requestedLimit = params?.limit || 20;\n\t\t\t\tconst offset = params?.offset || 0;\n\t\t\t\tconst rows = incomingRows;\n\t\t\t\tconst heuristicTotal = rows.length;\n\t\t\t\tconst heuristicHasMore = rows.length >= requestedLimit;\n\t\t\t\tif (client.count) client.count(params).then((total) => {\n\t\t\t\t\tif (active && currentUpdateId === lastUpdateId) onUpdate({\n\t\t\t\t\t\tdata: rows,\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\ttotal,\n\t\t\t\t\t\t\tlimit: requestedLimit,\n\t\t\t\t\t\t\toffset,\n\t\t\t\t\t\t\thasMore: offset + rows.length < total\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).catch(() => {\n\t\t\t\t\tif (active && currentUpdateId === lastUpdateId) onUpdate({\n\t\t\t\t\t\tdata: rows,\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\ttotal: heuristicTotal,\n\t\t\t\t\t\t\tlimit: requestedLimit,\n\t\t\t\t\t\t\toffset,\n\t\t\t\t\t\t\thasMore: heuristicHasMore\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\telse onUpdate({\n\t\t\t\t\tdata: rows,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\ttotal: heuristicTotal,\n\t\t\t\t\t\tlimit: requestedLimit,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\thasMore: heuristicHasMore\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}, onError);\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t\tunsub();\n\t\t\t};\n\t\t};\n\t\tclient.listenById = (id, onUpdate, onError) => {\n\t\t\treturn ws.listenOne({\n\t\t\t\tpath: slug,\n\t\t\t\tid: String(id)\n\t\t\t}, (row) => {\n\t\t\t\tif (row) onUpdate(row);\n\t\t\t\telse onUpdate(void 0);\n\t\t\t}, onError);\n\t\t};\n\t}\n\treturn client;\n}\n//#endregion\n//#region src/functions.ts\n/**\n* Create a `FunctionsClient` backed by the given transport.\n*\n* The transport already handles:\n* - Base URL resolution\n* - JWT injection via `Authorization: Bearer`\n* - 401 retry / `onUnauthorized` flow\n* - Consistent error throwing via `RebaseApiError`\n*\n* @internal\n*/\nfunction createFunctionsClient(transport) {\n\treturn { async invoke(name, payload, options) {\n\t\tconst method = options?.method ?? \"POST\";\n\t\tconst rawPath = options?.path;\n\t\tconst subPath = rawPath ? /^[?#]/.test(rawPath) ? rawPath : `/${rawPath.replace(/^\\//, \"\")}` : \"\";\n\t\tconst routePath = `/functions/${encodeURIComponent(name)}${subPath}`;\n\t\tconst init = { method };\n\t\tif (payload !== void 0 && method !== \"GET\") init.body = JSON.stringify(payload);\n\t\tif (options?.headers) init.headers = options.headers;\n\t\treturn transport.request(routePath, init);\n\t} };\n}\n//#endregion\n//#region src/storage.ts\n/**\n* Create a StorageSource that talks to the Rebase backend REST API.\n*\n* @param transport - HTTP transport instance\n* @param storageId - Optional storage-source key for multi-backend routing.\n* When set, it is forwarded to the server so the correct\n* `StorageController` is resolved from the registry.\n*/\nfunction createStorage(transport, storageId) {\n\tconst urlsCache = /* @__PURE__ */ new Map();\n\t/**\n\t* Base for URLs the *browser* will fetch on its own (file downloads,\n\t* previews). API requests keep going to `baseUrl`; see\n\t* {@link RebaseClientConfig.storageUrlOrigin} for why these can differ.\n\t*/\n\tconst fileUrlBase = () => `${transport.storageUrlOrigin ?? transport.baseUrl}${transport.apiPath}`;\n\t/** Append ?storageId=... to a path when multi-backend routing is active. */\n\tconst withStorageId = (path) => {\n\t\tif (!storageId) return path;\n\t\treturn `${path}${path.includes(\"?\") ? \"&\" : \"?\"}storageId=${encodeURIComponent(storageId)}`;\n\t};\n\tasync function putObject({ file, key, metadata, bucket, public: isPublic }) {\n\t\tconst formData = new FormData();\n\t\tformData.append(\"file\", file);\n\t\tlet effectiveKey = key;\n\t\tif (isPublic && effectiveKey && !isPublicStoragePath(effectiveKey)) effectiveKey = `${PUBLIC_STORAGE_PREFIX}${effectiveKey.replace(/^\\/+/, \"\")}`;\n\t\tif (effectiveKey) formData.append(\"key\", effectiveKey);\n\t\tif (bucket) formData.append(\"bucket\", bucket);\n\t\tif (storageId) formData.append(\"storageId\", storageId);\n\t\tif (metadata) {\n\t\t\tfor (const [key, value] of Object.entries(metadata)) if (value !== void 0 && value !== null) formData.append(`metadata_${key}`, typeof value === \"string\" ? value : JSON.stringify(value));\n\t\t}\n\t\treturn (await transport.request(withStorageId(\"/storage/upload\"), {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: formData,\n\t\t\theaders: {}\n\t\t})).data;\n\t}\n\tasync function getSignedUrl(keyOrUrl, bucket) {\n\t\tconst cacheKey = bucket ? `${bucket}/${keyOrUrl}` : keyOrUrl;\n\t\tconst cachedEntry = urlsCache.get(cacheKey);\n\t\tif (cachedEntry) {\n\t\t\tif (!cachedEntry.expiresAt || cachedEntry.expiresAt > Date.now()) return cachedEntry.config;\n\t\t\turlsCache.delete(cacheKey);\n\t\t}\n\t\tlet filePath = keyOrUrl;\n\t\tif (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\") || filePath.startsWith(\"gs://\"))) filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n\t\tif (bucket && filePath && !filePath.startsWith(bucket)) filePath = `${bucket}/${filePath}`;\n\t\tif (!filePath || filePath.trim() === \"\" || filePath === \"/\") return {\n\t\t\turl: null,\n\t\t\tfileNotFound: true\n\t\t};\n\t\tif (isPublicStoragePath(filePath)) {\n\t\t\tconst publicConfig = { url: withStorageId(`${fileUrlBase()}/storage/file/${filePath}`) };\n\t\t\turlsCache.set(cacheKey, { config: publicConfig });\n\t\t\treturn publicConfig;\n\t\t}\n\t\ttry {\n\t\t\tconst result = await transport.request(withStorageId(`/storage/metadata/${filePath}`));\n\t\t\tif (result.data.public) {\n\t\t\t\tconst publicConfig = {\n\t\t\t\t\turl: withStorageId(`${fileUrlBase()}/storage/file/${filePath}`),\n\t\t\t\t\tmetadata: result.data\n\t\t\t\t};\n\t\t\t\turlsCache.set(cacheKey, { config: publicConfig });\n\t\t\t\treturn publicConfig;\n\t\t\t}\n\t\t\tconst scopedToken = result.data.token;\n\t\t\tconst tokenQuery = scopedToken ? `?token=${scopedToken}` : \"\";\n\t\t\tconst downloadConfig = {\n\t\t\t\turl: withStorageId(`${fileUrlBase()}/storage/file/${filePath}${tokenQuery}`),\n\t\t\t\tmetadata: result.data\n\t\t\t};\n\t\t\tconst expiresAt = result.data.tokenExpiresIn ? Date.now() + (result.data.tokenExpiresIn - 10) * 1e3 : void 0;\n\t\t\turlsCache.set(cacheKey, {\n\t\t\t\tconfig: downloadConfig,\n\t\t\t\texpiresAt\n\t\t\t});\n\t\t\treturn downloadConfig;\n\t\t} catch (e) {\n\t\t\tif (e instanceof Error && \"status\" in e && e.status === 404) return {\n\t\t\t\turl: null,\n\t\t\t\tfileNotFound: true\n\t\t\t};\n\t\t\tthrow e;\n\t\t}\n\t}\n\tasync function getObject(key, bucket) {\n\t\tconst downloadConfig = await getSignedUrl(key, bucket);\n\t\tif (downloadConfig.fileNotFound || !downloadConfig.url) return null;\n\t\tconst response = await transport.fetchFn(downloadConfig.url, { headers: {} });\n\t\tif (response.status === 404) return null;\n\t\tif (!response.ok) throw new Error(\"Failed to get file\");\n\t\tconst blob = await response.blob();\n\t\tconst fileName = (bucket ? `${bucket}/${key}` : key).split(\"/\").pop() || \"file\";\n\t\treturn new File([blob], fileName, { type: blob.type });\n\t}\n\tasync function deleteObject(key, bucket) {\n\t\tlet filePath = key;\n\t\tif (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\") || filePath.startsWith(\"gs://\"))) filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n\t\tif (bucket && filePath && !filePath.startsWith(bucket)) filePath = `${bucket}/${filePath}`;\n\t\tif (!filePath || filePath.trim() === \"\" || filePath === \"/\") return;\n\t\ttry {\n\t\t\tawait transport.request(withStorageId(`/storage/file/${filePath}`), { method: \"DELETE\" });\n\t\t} catch (e) {\n\t\t\tif (!(e instanceof Error && \"status\" in e && e.status === 404)) throw e;\n\t\t}\n\t\turlsCache.delete(bucket ? `${bucket}/${key}` : key);\n\t}\n\tasync function listObjects(prefix, options) {\n\t\tconst params = new URLSearchParams();\n\t\tif (prefix) params.set(\"prefix\", prefix);\n\t\tif (options?.bucket) params.set(\"bucket\", options.bucket);\n\t\tif (options?.maxResults) params.set(\"maxResults\", String(options.maxResults));\n\t\tif (options?.pageToken) params.set(\"pageToken\", options.pageToken);\n\t\tif (storageId) params.set(\"storageId\", storageId);\n\t\treturn (await transport.request(`/storage/list?${params.toString()}`)).data;\n\t}\n\treturn {\n\t\tputObject,\n\t\tgetSignedUrl,\n\t\tgetObject,\n\t\tdeleteObject,\n\t\tlistObjects\n\t};\n}\n//#endregion\n//#region src/storage-registry.ts\n/**\n* Default implementation of the client-side `StorageSourceRegistry`.\n*/\nvar ClientStorageSourceRegistry = class ClientStorageSourceRegistry {\n\tsources = /* @__PURE__ */ new Map();\n\t/**\n\t* Register a storage source.\n\t* @param key - Unique key matching a `StorageSourceDefinition.key`\n\t* @param source - The `StorageSource` instance\n\t*/\n\tregister(key, source) {\n\t\tthis.sources.set(key, source);\n\t}\n\tgetDefault() {\n\t\tconst source = this.sources.get(DEFAULT_STORAGE_SOURCE_KEY);\n\t\tif (!source) throw new Error(`[StorageSourceRegistry] No default storage source registered. Register one with key \"${DEFAULT_STORAGE_SOURCE_KEY}\".`);\n\t\treturn source;\n\t}\n\tget(key) {\n\t\tif (key === void 0 || key === null) return this.sources.get(DEFAULT_STORAGE_SOURCE_KEY);\n\t\treturn this.sources.get(key);\n\t}\n\tgetOrDefault(key) {\n\t\tif (key === void 0 || key === null) return this.getDefault();\n\t\tconst source = this.sources.get(key);\n\t\tif (source) return source;\n\t\tconsole.warn(`[StorageSourceRegistry] Storage source \"${key}\" not found, falling back to \"${DEFAULT_STORAGE_SOURCE_KEY}\".`);\n\t\treturn this.getDefault();\n\t}\n\thas(key) {\n\t\treturn this.sources.has(key);\n\t}\n\tlist() {\n\t\treturn Array.from(this.sources.keys());\n\t}\n\t/**\n\t* Build a registry from `StorageSourceDefinition[]` and an HTTP transport.\n\t*\n\t* - Sources with `transport: \"server\"` are auto-wired via `createStorage(transport, key)`.\n\t* - Sources with `transport: \"direct\"` are **not** auto-wired — they must\n\t* be registered manually after this call (e.g. via a Firebase hook).\n\t*\n\t* @param definitions - Array of storage source definitions\n\t* @param transport - HTTP transport for server-backed sources\n\t*/\n\tstatic fromDefinitions(definitions, transport) {\n\t\tconst registry = new ClientStorageSourceRegistry();\n\t\tfor (const def of definitions) if (def.transport === \"server\") {\n\t\t\tconst source = createStorage(transport, def.key === DEFAULT_STORAGE_SOURCE_KEY ? void 0 : def.key);\n\t\t\tregistry.register(def.key, source);\n\t\t}\n\t\treturn registry;\n\t}\n};\n//#endregion\n//#region src/websocket.ts\n/**\n* Extract error message and code from a WebSocket message payload.\n* Handles both `{ error: string }` and `{ error: { message, code } }` shapes.\n*/\nfunction extractMessageError(message) {\n\tconst payload = message.payload;\n\tconst errPayload = payload?.error;\n\tconst errorMessage = typeof errPayload === \"object\" ? errPayload.message : payload?.message || (typeof errPayload === \"string\" ? errPayload : void 0) || message.error || \"Unknown error\";\n\tconst errorCode = typeof errPayload === \"object\" ? errPayload.code : payload?.code;\n\treturn {\n\t\terrorMessage: typeof errorMessage === \"string\" ? errorMessage : errorMessage == null ? \"Unknown error\" : JSON.stringify(errorMessage),\n\t\terrorCode\n\t};\n}\n/**\n* Broadcast and presence frames.\n*\n* Fire-and-forget (the server sends no response envelope), and exempt from the\n* client-side auth gate — a public channel is usable without an account.\n*/\nvar CHANNEL_MESSAGE_TYPES = /* @__PURE__ */ new Set([\n\t\"join_channel\",\n\t\"leave_channel\",\n\t\"broadcast\",\n\t\"presence_track\",\n\t\"presence_untrack\",\n\t\"presence_state\",\n\t\"channel_history\"\n]);\n/**\n* Low-level realtime WebSocket client.\n*\n* @internal Not a stable app-facing API. `createRebaseClient()` constructs and\n* manages this internally (exposed as `client.ws`, typed by the minimal\n* `RebaseWebSocket` contract in `@rebasepro/types`). It is re-exported from the\n* package root only because the `@rebasepro/client-postgres` driver\n* instantiates it directly; its surface may change without a major bump.\n*/\nvar RebaseWebSocketClient = class {\n\twebsocketUrl;\n\tws = null;\n\tgetAuthToken;\n\tsubscriptions = /* @__PURE__ */ new Map();\n\tlisteners = /* @__PURE__ */ new Map();\n\t/** Channel-name → handlers, for broadcast and presence frames. */\n\tchannelHandlers = /* @__PURE__ */ new Map();\n\t/** Set by `close()`. Blocks any later operation from silently redialling. */\n\tclosedByCaller = false;\n\t/**\n\t* Set when the backoff budget ran out, cleared by anything that earns a\n\t* fresh one.\n\t*\n\t* Unlike {@link closedByCaller} this is not final — nobody *asked* for the\n\t* socket to stay down. Five attempts with exponential backoff is about a\n\t* minute, which a laptop lid, a wifi handover or a backend rollout all\n\t* exceed routinely; treating that as permanent meant realtime silently\n\t* stopped for the rest of the page's life, with a reload the only cure.\n\t*/\n\tgaveUp = false;\n\t/**\n\t* Whether a socket exists at all (open or still opening).\n\t*\n\t* Lets callers distinguish \"authenticate the live socket\" from \"there is\n\t* nothing to authenticate yet\", without that question forcing a dial.\n\t*/\n\tget hasSocket() {\n\t\treturn this.ws !== null;\n\t}\n\t/** So the \"no WebSocket in this environment\" warning is said once, not per call. */\n\twarnedNoWebSocket = false;\n\t/** Subscribe to broadcast/presence frames for one channel. */\n\tonChannelMessage(channel, handler) {\n\t\tif (!this.channelHandlers.has(channel)) this.channelHandlers.set(channel, /* @__PURE__ */ new Set());\n\t\tthis.channelHandlers.get(channel).add(handler);\n\t\treturn () => {\n\t\t\tconst handlers = this.channelHandlers.get(channel);\n\t\t\tif (!handlers) return;\n\t\t\thandlers.delete(handler);\n\t\t\tif (handlers.size === 0) this.channelHandlers.delete(channel);\n\t\t};\n\t}\n\t/** Notified after the socket comes back, so channels can re-join. */\n\tonReconnect(handler) {\n\t\treturn this.on(\"reconnect\", handler);\n\t}\n\ton(event, cb) {\n\t\tif (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());\n\t\tthis.listeners.get(event).add(cb);\n\t\treturn () => this.listeners.get(event).delete(cb);\n\t}\n\temit(event, ...args) {\n\t\tif (this.listeners.has(event)) this.listeners.get(event).forEach((cb) => cb(...args));\n\t}\n\tcollectionSubscriptions = /* @__PURE__ */ new Map();\n\tsingleSubscriptions = /* @__PURE__ */ new Map();\n\tbackendToCollectionKey = /* @__PURE__ */ new Map();\n\tbackendToEntityKey = /* @__PURE__ */ new Map();\n\tpendingRequests = /* @__PURE__ */ new Map();\n\treconnectAttempts = 0;\n\tmaxReconnectAttempts = 5;\n\tisConnected = false;\n\tmessageQueue = [];\n\trequestTimeoutMs = 3e4;\n\tsubscriptionTimeoutMs = 3e4;\n\treconnectTimeout = null;\n\tisAuthenticated = false;\n\tauthPromise = null;\n\tWebSocketConstructor;\n\tonUnauthorized;\n\trefreshInProgress = null;\n\tconstructor(config) {\n\t\tthis.websocketUrl = config.websocketUrl;\n\t\tthis.getAuthToken = config.getAuthToken;\n\t\tthis.onUnauthorized = config.onUnauthorized;\n\t\tthis.WebSocketConstructor = config.WebSocket || (typeof WebSocket !== \"undefined\" ? WebSocket : void 0);\n\t}\n\t/**\n\t* Open the socket if it is not open (or opening) already.\n\t*\n\t* Idempotent, synchronous, and safe to call on every operation that needs a\n\t* live socket — `initWebSocket` already no-ops on an open socket and is\n\t* re-entrant, since the reconnect path has always called it.\n\t*/\n\tensureConnected() {\n\t\tif (this.closedByCaller) return;\n\t\tif (!this.WebSocketConstructor) {\n\t\t\tif (!this.warnedNoWebSocket) {\n\t\t\t\tthis.warnedNoWebSocket = true;\n\t\t\t\tconsole.warn(\"WebSocket is not defined in this environment. Realtime subscriptions will not work unless you provide a WebSocket implementation in the config.\");\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tthis.installOnlineListener();\n\t\tif (this.ws || this.reconnectTimeout) return;\n\t\tif (this.gaveUp) {\n\t\t\tthis.gaveUp = false;\n\t\t\tthis.reconnectAttempts = 0;\n\t\t}\n\t\tthis.initWebSocket();\n\t}\n\t/**\n\t* The browser says the network is back — the usual reason the budget ran\n\t* out in the first place. Registered lazily so a Node client, or a page\n\t* that never subscribes, adds no listener.\n\t*/\n\tinstallOnlineListener() {\n\t\tif (this.onlineListener || typeof window === \"undefined\" || typeof window.addEventListener !== \"function\") return;\n\t\tthis.onlineListener = () => {\n\t\t\tif (this.closedByCaller || !this.gaveUp) return;\n\t\t\tconsole.debug(\"Network is back — retrying the realtime connection\");\n\t\t\tthis.ensureConnected();\n\t\t};\n\t\twindow.addEventListener(\"online\", this.onlineListener);\n\t}\n\tonlineListener = null;\n\t/**\n\t* Authenticate the WebSocket connection\n\t*/\n\tasync authenticate(token) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = `auth_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\treject(/* @__PURE__ */ new Error(\"Authentication timeout\"));\n\t\t\t}, 3e4);\n\t\t\tthis.pendingRequests.set(requestId, {\n\t\t\t\tresolve: () => {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\tthis.isAuthenticated = true;\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\treject(error);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst message = {\n\t\t\t\ttype: \"AUTHENTICATE\",\n\t\t\t\trequestId,\n\t\t\t\tpayload: { token }\n\t\t\t};\n\t\t\tif (!this.isConnected || !this.ws) this.messageQueue.unshift(message);\n\t\t\telse this.ws.send(JSON.stringify(message));\n\t\t});\n\t}\n\t/**\n\t* Set the auth token getter function\n\t*/\n\tsetAuthTokenGetter(getAuthToken) {\n\t\tthis.getAuthToken = getAuthToken;\n\t\tif (this.isConnected && !this.isAuthenticated && !this.authPromise) {\n\t\t\tconsole.debug(\"WebSocket auto-authenticating after token getter set\");\n\t\t\tthis.getAuthToken().then((token) => {\n\t\t\t\tif (!this.ws) return;\n\t\t\t\tif (token) this.authenticate(token).catch((e) => {\n\t\t\t\t\tif (this.ws) console.debug(\"WebSocket auto-auth skipped:\", e?.message || e);\n\t\t\t\t});\n\t\t\t}).catch((e) => {\n\t\t\t\tif (this.ws) console.debug(\"WebSocket auto-auth skipped:\", e?.message || e);\n\t\t\t});\n\t\t}\n\t}\n\t/**\n\t* Drop the socket.\n\t*\n\t* `permanent` distinguishes the two callers. Signing out drops the socket\n\t* but the client stays usable — a later subscribe should reconnect\n\t* anonymously. `client.close()` is the caller saying they are done, and\n\t* must not be undone by a stray queued frame.\n\t*/\n\tdisconnect(permanent = false) {\n\t\tif (permanent) this.closedByCaller = true;\n\t\tif (permanent && this.onlineListener && typeof window !== \"undefined\") {\n\t\t\twindow.removeEventListener(\"online\", this.onlineListener);\n\t\t\tthis.onlineListener = null;\n\t\t}\n\t\tthis.isAuthenticated = false;\n\t\tthis.authPromise = null;\n\t\tif (this.reconnectTimeout) {\n\t\t\tclearTimeout(this.reconnectTimeout);\n\t\t\tthis.reconnectTimeout = null;\n\t\t}\n\t\tif (this.ws) {\n\t\t\tthis.ws.onclose = null;\n\t\t\tthis.ws.onerror = null;\n\t\t\tthis.ws.onopen = null;\n\t\t\tthis.ws.onmessage = null;\n\t\t\tthis.ws.close();\n\t\t\tthis.ws = null;\n\t\t}\n\t}\n\tinitWebSocket() {\n\t\tif (!this.WebSocketConstructor) return;\n\t\tif (this.ws?.readyState === this.WebSocketConstructor.OPEN) return;\n\t\tif (this.ws) {\n\t\t\tthis.ws.onclose = null;\n\t\t\tthis.ws.close();\n\t\t\tthis.ws = null;\n\t\t}\n\t\ttry {\n\t\t\tconst socket = new this.WebSocketConstructor(this.websocketUrl);\n\t\t\tthis.ws = socket;\n\t\t\tthis.ws.onopen = async () => {\n\t\t\t\tconsole.debug(\"Connected to PostgreSQL backend\");\n\t\t\t\tconst wasReconnect = this.reconnectAttempts > 0;\n\t\t\t\tthis.isConnected = true;\n\t\t\t\tthis.reconnectAttempts = 0;\n\t\t\t\tif (this.getAuthToken && !this.isAuthenticated) try {\n\t\t\t\t\tconst token = await this.getAuthToken();\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tawait this.authenticate(token);\n\t\t\t\t\t\tconsole.debug(\"WebSocket auto-authenticated\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.debug(\"WebSocket connected without auth:\", error?.message || error);\n\t\t\t\t}\n\t\t\t\tthis.emit(wasReconnect ? \"reconnect\" : \"connect\");\n\t\t\t\tthis.processMessageQueue();\n\t\t\t\tif (wasReconnect) this.resubscribeAll();\n\t\t\t\tthis.armPendingSubscribeWatchdogs();\n\t\t\t};\n\t\t\tthis.ws.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst message = JSON.parse(event.data, rebaseReviver);\n\t\t\t\t\tthis.handleWebSocketMessage(message);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"Error parsing WebSocket message:\", error);\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.ws.onclose = () => {\n\t\t\t\tconsole.debug(\"Disconnected from PostgreSQL backend\");\n\t\t\t\tif (this.ws === socket) this.ws = null;\n\t\t\t\tthis.isConnected = false;\n\t\t\t\tthis.isAuthenticated = false;\n\t\t\t\tthis.authPromise = null;\n\t\t\t\tthis.suspendSubscribeWatchdogs();\n\t\t\t\tthis.emit(\"disconnect\");\n\t\t\t\tfor (const [reqId, request] of this.pendingRequests.entries()) {\n\t\t\t\t\tif (reqId.startsWith(\"auth_\")) request.reject(/* @__PURE__ */ new Error(\"Connection closed during authentication\"));\n\t\t\t\t\telse if (request.message) {\n\t\t\t\t\t\trequest.message._queuedResolve = request.resolve;\n\t\t\t\t\t\trequest.message._queuedReject = request.reject;\n\t\t\t\t\t\tthis.messageQueue.push(request.message);\n\t\t\t\t\t} else request.reject(new RebaseApiError$1(\"Connection closed\"));\n\t\t\t\t\tthis.pendingRequests.delete(reqId);\n\t\t\t\t}\n\t\t\t\tthis.attemptReconnect();\n\t\t\t};\n\t\t\tthis.ws.onerror = (error) => {\n\t\t\t\tconsole.error(\"WebSocket error:\", error);\n\t\t\t\tthis.isConnected = false;\n\t\t\t\tthis.emit(\"error\", error);\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to initialize WebSocket:\", error);\n\t\t\tthis.attemptReconnect();\n\t\t}\n\t}\n\tprocessMessageQueue() {\n\t\twhile (this.messageQueue.length > 0 && this.isConnected) {\n\t\t\tconst message = this.messageQueue.shift();\n\t\t\tif (message) this.sendMessage(message);\n\t\t}\n\t}\n\tattemptReconnect() {\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) {\n\t\t\tconsole.error(\"Max reconnection attempts reached\");\n\t\t\tthis.gaveUp = true;\n\t\t\tthis.failAllPendingSubscriptions(new RebaseApiError$1(\"Connection lost\", { code: \"CONNECTION_LOST\" }));\n\t\t\treturn;\n\t\t}\n\t\tthis.reconnectAttempts++;\n\t\tconst delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);\n\t\tconsole.debug(`Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts})`);\n\t\tif (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);\n\t\tthis.reconnectTimeout = setTimeout(() => {\n\t\t\tthis.reconnectTimeout = null;\n\t\t\tthis.initWebSocket();\n\t\t}, delay);\n\t}\n\tisAuthError(message) {\n\t\tif (message.type === \"AUTH_ERROR\") return true;\n\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\tif (errorCode === \"UNAUTHORIZED\" || errorCode === \"JWT_EXPIRED\" || errorCode === \"AUTH_ERROR\") return true;\n\t\tconst lowerMessage = errorMessage.toLowerCase();\n\t\treturn lowerMessage.includes(\"unauthorized\") || lowerMessage.includes(\"token expired\") || lowerMessage.includes(\"token is expired\") || lowerMessage.includes(\"invalid token\") || lowerMessage.includes(\"session expired\") || lowerMessage.includes(\"auth error\");\n\t}\n\tasync handleAuthFailure() {\n\t\tif (this.refreshInProgress) return this.refreshInProgress;\n\t\tthis.refreshInProgress = (async () => {\n\t\t\tthis.isAuthenticated = false;\n\t\t\tthis.authPromise = null;\n\t\t\tif (this.onUnauthorized) try {\n\t\t\t\tif (await this.onUnauthorized() && this.getAuthToken) {\n\t\t\t\t\tconst token = await this.getAuthToken();\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tawait this.authenticate(token);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"WebSocket auth refresh failed:\", error);\n\t\t\t}\n\t\t\treturn false;\n\t\t})();\n\t\ttry {\n\t\t\treturn await this.refreshInProgress;\n\t\t} finally {\n\t\t\tthis.refreshInProgress = null;\n\t\t}\n\t}\n\t/**\n\t* Shared logic for re-subscribing a collection or row subscription\n\t* after an auth error is resolved by refreshing credentials.\n\t*/\n\tresubscribeAfterAuthRefresh(message, subscription, subscriptionKey, idPrefix, backendKeyMap, messageType) {\n\t\tthis.handleAuthFailure().then((refreshed) => {\n\t\t\tif (refreshed) {\n\t\t\t\tconst oldBackendId = subscription.backendSubscriptionId;\n\t\t\t\tconst newBackendId = `${idPrefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\t\tsubscription.backendSubscriptionId = newBackendId;\n\t\t\t\tbackendKeyMap.delete(oldBackendId);\n\t\t\t\tbackendKeyMap.set(newBackendId, subscriptionKey);\n\t\t\t\tif (messageType === \"subscribe_collection\") this.sendCollectionSubscribe(subscriptionKey);\n\t\t\t\telse this.sendEntitySubscribe(subscriptionKey);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\tconst error = new RebaseApiError$1(errorMessage, { code: errorCode });\n\t\t\tif (messageType === \"subscribe_collection\") this.failCollectionSubscription(subscriptionKey, error);\n\t\t\telse this.failEntitySubscription(subscriptionKey, error);\n\t\t}).catch((err) => {\n\t\t\tconst error = err instanceof Error ? err : new Error(String(err));\n\t\t\tif (messageType === \"subscribe_collection\") this.failCollectionSubscription(subscriptionKey, error);\n\t\t\telse this.failEntitySubscription(subscriptionKey, error);\n\t\t});\n\t}\n\thandleWebSocketMessage(message) {\n\t\tconst { type, requestId, subscriptionId } = message;\n\t\tif (requestId && this.pendingRequests.has(requestId)) {\n\t\t\tconst pendingReq = this.pendingRequests.get(requestId);\n\t\t\tif (type === \"ERROR\" || type === \"AUTH_ERROR\" || message.error) if (this.isAuthError(message)) {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\tthis.handleAuthFailure().then((refreshed) => {\n\t\t\t\t\tif (refreshed && pendingReq.message) this.doSendMessage(pendingReq.message, pendingReq.resolve, pendingReq.reject).catch(pendingReq.reject);\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\t\tpendingReq.reject(new RebaseApiError$1(errorMessage, { code: errorCode }));\n\t\t\t\t\t}\n\t\t\t\t}).catch((err) => {\n\t\t\t\t\tpendingReq.reject(err);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\tpendingReq.reject(new RebaseApiError$1(errorMessage, { code: errorCode }));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\tpendingReq.resolve(message.payload || message);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.channel === \"string\" && (type === \"broadcast\" || type === \"presence_state\" || type === \"presence_diff\" || type === \"channel_history\")) {\n\t\t\tconst handlers = this.channelHandlers.get(message.channel);\n\t\t\tif (handlers) for (const handler of [...handlers]) try {\n\t\t\t\thandler(message);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Error in channel handler:\", error);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (subscriptionId && type === \"collection_update\") {\n\t\t\tconst subscriptionKey = this.backendToCollectionKey.get(subscriptionId);\n\t\t\tif (subscriptionKey) {\n\t\t\t\tconst collectionSub = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\t\tif (collectionSub) {\n\t\t\t\t\tconst incomingRows = message.rows || [];\n\t\t\t\t\tconst updatePks = message.pks;\n\t\t\t\t\tif (updatePks) collectionSub.pks = updatePks;\n\t\t\t\t\tconst rows = this.mergeRows(collectionSub.latestData, incomingRows, collectionSub.pks);\n\t\t\t\t\tcollectionSub.latestData = rows;\n\t\t\t\t\tcollectionSub.lastUpdated = Date.now();\n\t\t\t\t\tcollectionSub.isInitialDataReceived = true;\n\t\t\t\t\tif (collectionSub.subscribeTimeout) clearTimeout(collectionSub.subscribeTimeout);\n\t\t\t\t\tcollectionSub.subscribeTimeout = void 0;\n\t\t\t\t\tcollectionSub.subscribeInFlight = false;\n\t\t\t\t\tcollectionSub.callbacks.forEach((callback) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcallback.onUpdate(rows);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Error in collection subscription callback:\", error);\n\t\t\t\t\t\t\tif (callback.onError) callback.onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && type === \"collection_patch\") {\n\t\t\tconst subscriptionKey = this.backendToCollectionKey.get(subscriptionId);\n\t\t\tif (subscriptionKey) {\n\t\t\t\tconst collectionSub = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\t\tif (collectionSub && collectionSub.isInitialDataReceived && collectionSub.latestData) {\n\t\t\t\t\tconst patchWireEntity = message.row ?? null;\n\t\t\t\t\tconst patchMessage = message;\n\t\t\t\t\tconst patchEntityId = patchMessage.id;\n\t\t\t\t\tif (patchMessage.pks) collectionSub.pks = patchMessage.pks;\n\t\t\t\t\tconst patchRow = patchWireEntity ? patchWireEntity : null;\n\t\t\t\t\tlet updated;\n\t\t\t\t\tif (patchRow === null) updated = collectionSub.latestData.filter((e) => this.rowAddress(e, collectionSub.pks) !== String(patchEntityId));\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst idx = collectionSub.latestData.findIndex((e) => this.rowAddress(e, collectionSub.pks) === String(patchEntityId));\n\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\tupdated = [...collectionSub.latestData];\n\t\t\t\t\t\t\tupdated[idx] = patchRow;\n\t\t\t\t\t\t} else updated = [patchRow, ...collectionSub.latestData];\n\t\t\t\t\t}\n\t\t\t\t\tcollectionSub.latestData = updated;\n\t\t\t\t\tcollectionSub.lastUpdated = Date.now();\n\t\t\t\t\tcollectionSub.callbacks.forEach((callback) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcallback.onUpdate(updated);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Error in collection patch callback:\", error);\n\t\t\t\t\t\t\tif (callback.onError) callback.onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && type === \"single_update\") {\n\t\t\tconst subscriptionKey = this.backendToEntityKey.get(subscriptionId);\n\t\t\tif (subscriptionKey) {\n\t\t\t\tconst entitySub = this.singleSubscriptions.get(subscriptionKey);\n\t\t\t\tif (entitySub) {\n\t\t\t\t\tconst wireEntity = message.row ?? null;\n\t\t\t\t\tconst row = wireEntity ? wireEntity : null;\n\t\t\t\t\tentitySub.latestData = row;\n\t\t\t\t\tentitySub.lastUpdated = Date.now();\n\t\t\t\t\tentitySub.isInitialDataReceived = true;\n\t\t\t\t\tif (entitySub.subscribeTimeout) clearTimeout(entitySub.subscribeTimeout);\n\t\t\t\t\tentitySub.subscribeTimeout = void 0;\n\t\t\t\t\tentitySub.subscribeInFlight = false;\n\t\t\t\t\tentitySub.callbacks.forEach((callback) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcallback.onUpdate(row);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Error in row subscription callback:\", error);\n\t\t\t\t\t\t\tif (callback.onError) callback.onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && (type === \"ERROR\" || message.error)) {\n\t\t\tconst collectionKey = this.backendToCollectionKey.get(subscriptionId);\n\t\t\tif (collectionKey) {\n\t\t\t\tconst collectionSub = this.collectionSubscriptions.get(collectionKey);\n\t\t\t\tif (collectionSub) {\n\t\t\t\t\tif (this.isAuthError(message)) {\n\t\t\t\t\t\tthis.resubscribeAfterAuthRefresh(message, collectionSub, collectionKey, \"collection\", this.backendToCollectionKey, \"subscribe_collection\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (collectionSub.subscribeTimeout) clearTimeout(collectionSub.subscribeTimeout);\n\t\t\t\t\tcollectionSub.subscribeTimeout = void 0;\n\t\t\t\t\tcollectionSub.subscribeInFlight = false;\n\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\tconst error = new RebaseApiError$1(errorMessage, { code: errorCode });\n\t\t\t\t\tcollectionSub.callbacks.forEach((callback) => {\n\t\t\t\t\t\tif (callback.onError) callback.onError(error);\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst entityKey = this.backendToEntityKey.get(subscriptionId);\n\t\t\tif (entityKey) {\n\t\t\t\tconst entitySub = this.singleSubscriptions.get(entityKey);\n\t\t\t\tif (entitySub) {\n\t\t\t\t\tif (this.isAuthError(message)) {\n\t\t\t\t\t\tthis.resubscribeAfterAuthRefresh(message, entitySub, entityKey, \"row\", this.backendToEntityKey, \"subscribe_one\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (entitySub.subscribeTimeout) clearTimeout(entitySub.subscribeTimeout);\n\t\t\t\t\tentitySub.subscribeTimeout = void 0;\n\t\t\t\t\tentitySub.subscribeInFlight = false;\n\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\tconst error = new RebaseApiError$1(errorMessage, { code: errorCode });\n\t\t\t\t\tentitySub.callbacks.forEach((callback) => {\n\t\t\t\t\t\tif (callback.onError) callback.onError(error);\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && this.subscriptions.has(subscriptionId)) {\n\t\t\tconst callback = this.subscriptions.get(subscriptionId);\n\t\t\tif (!callback) throw new Error(`Subscription callback not found for subscriptionId: ${subscriptionId}`);\n\t\t\tif (message.type === \"ERROR\" || message.error) {\n\t\t\t\tif (callback.onError) {\n\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\tcallback.onError(new RebaseApiError$1(errorMessage, { code: errorCode }));\n\t\t\t\t}\n\t\t\t} else callback.onUpdate(message);\n\t\t}\n\t}\n\tasync ensureAuthenticated(retryCount = 3) {\n\t\tif (this.isAuthenticated || !this.getAuthToken) return;\n\t\tif (!this.authPromise) {\n\t\t\tthis.authPromise = this.runAuthentication(retryCount);\n\t\t\tthis.authPromise.finally(() => {\n\t\t\t\tthis.authPromise = null;\n\t\t\t}).catch(() => void 0);\n\t\t}\n\t\tawait this.authPromise;\n\t}\n\tasync runAuthentication(retryCount) {\n\t\tlet lastError = null;\n\t\tfor (let attempt = 0; attempt < retryCount; attempt++) try {\n\t\t\tconst token = await this.getAuthToken();\n\t\t\tif (!token) throw new Error(\"user not logged in\");\n\t\t\tawait this.authenticate(token);\n\t\t\tconsole.debug(\"WebSocket authenticated on demand\");\n\t\t\treturn;\n\t\t} catch (error) {\n\t\t\tlastError = error;\n\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errMsg.includes(\"not logged in\") || errMsg.includes(\"Session expired\")) {\n\t\t\t\tconsole.warn(\"WebSocket auth failed: user not logged in\");\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (errMsg.includes(\"still loading\")) {\n\t\t\t\tif (attempt < retryCount - 1) {\n\t\t\t\t\tconst delay = Math.min(500 * (attempt + 1), 2e3);\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (attempt < retryCount - 1) {\n\t\t\t\tconst delay = Math.min(1e3 * (attempt + 1), 3e3);\n\t\t\t\tconsole.debug(`WebSocket auth attempt ${attempt + 1} failed, retrying in ${delay}ms...`);\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t}\n\t\t}\n\t\tconsole.warn(\"WebSocket on-demand auth failed after retries:\", lastError);\n\t\tthrow lastError;\n\t}\n\tasync reauthenticate() {\n\t\tif (!this.getAuthToken) return;\n\t\tthis.isAuthenticated = false;\n\t\ttry {\n\t\t\tconst token = await this.getAuthToken();\n\t\t\tif (!token) throw new Error(\"user not logged in\");\n\t\t\tawait this.authenticate(token);\n\t\t\tconsole.debug(\"WebSocket reauthenticated successfully\");\n\t\t} catch (error) {\n\t\t\tconsole.error(\"WebSocket reauthentication failed:\", error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\t/**\n\t* Public because `RebaseRealtimeChannel` sends channel frames through it.\n\t* Not part of the stable surface — prefer `client.realtime.channel(name)`.\n\t*/\n\tsendMessage(message) {\n\t\tconst queuedMsg = message;\n\t\tif (queuedMsg._queuedResolve && queuedMsg._queuedReject) return this.doSendMessage(message, queuedMsg._queuedResolve, queuedMsg._queuedReject);\n\t\tif (!this.isConnected || !this.ws) {\n\t\t\tthis.ensureConnected();\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst queueable = message;\n\t\t\t\tqueueable._queuedResolve = resolve;\n\t\t\t\tqueueable._queuedReject = reject;\n\t\t\t\tthis.messageQueue.push(message);\n\t\t\t});\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.doSendMessage(message, resolve, reject);\n\t\t});\n\t}\n\tasync doSendMessage(message, resolve, reject) {\n\t\tif (message.type !== \"AUTHENTICATE\" && !CHANNEL_MESSAGE_TYPES.has(message.type) && this.getAuthToken && !this.isAuthenticated) try {\n\t\t\tawait this.ensureAuthenticated();\n\t\t} catch (error) {\n\t\t\treject(new RebaseApiError$1(error instanceof Error ? error.message : \"Authentication required\"));\n\t\t\treturn;\n\t\t}\n\t\tconst requestId = message.requestId || `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tmessage.requestId = requestId;\n\t\tconst expectsResponse = !(message.type === \"subscribe_collection\" || message.type === \"subscribe_one\" || message.type === \"unsubscribe\" || CHANNEL_MESSAGE_TYPES.has(message.type));\n\t\tif (expectsResponse && !this.pendingRequests.has(requestId)) {\n\t\t\tconst timeoutHandle = setTimeout(() => {\n\t\t\t\tif (this.pendingRequests.has(requestId)) {\n\t\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\t\treject(new RebaseApiError$1(\"Request timed out\"));\n\t\t\t\t}\n\t\t\t}, this.requestTimeoutMs);\n\t\t\tthis.pendingRequests.set(requestId, {\n\t\t\t\tresolve: (value) => {\n\t\t\t\t\tclearTimeout(timeoutHandle);\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tclearTimeout(timeoutHandle);\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t\ttry {\n\t\t\tthis.ws.send(JSON.stringify(message));\n\t\t\tif (!expectsResponse) resolve(void 0);\n\t\t} catch (error) {\n\t\t\tif (expectsResponse) this.pendingRequests.delete(requestId);\n\t\t\treject(new RebaseApiError$1(\"Failed to send message\", { cause: error }));\n\t\t}\n\t}\n\tasync fetchCollection(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_COLLECTION\",\n\t\t\tpayload: props\n\t\t})).rows || [];\n\t}\n\tasync fetchOne(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_ONE\",\n\t\t\tpayload: props\n\t\t})).row ?? void 0;\n\t}\n\tasync save(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"SAVE\",\n\t\t\tpayload: props\n\t\t})).row;\n\t}\n\tasync delete(props) {\n\t\tawait this.sendMessage({\n\t\t\ttype: \"DELETE\",\n\t\t\tpayload: props\n\t\t});\n\t}\n\tasync executeSql(sql, options) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"EXECUTE_SQL\",\n\t\t\tpayload: {\n\t\t\t\tsql,\n\t\t\t\toptions\n\t\t\t}\n\t\t})).result || [];\n\t}\n\tasync fetchAvailableDatabases() {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_DATABASES\",\n\t\t\tpayload: {}\n\t\t})).databases || [];\n\t}\n\tasync fetchAvailableRoles() {\n\t\treturn (await this.sendMessage({ type: \"FETCH_ROLES\" })).roles || [];\n\t}\n\tasync fetchApplicationRoles() {\n\t\treturn (await this.sendMessage({ type: \"FETCH_APPLICATION_ROLES\" })).roles || [];\n\t}\n\tasync fetchCurrentDatabase() {\n\t\treturn (await this.sendMessage({ type: \"FETCH_CURRENT_DATABASE\" })).database;\n\t}\n\tasync checkUniqueField(path, name, value, id, collection) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"CHECK_UNIQUE_FIELD\",\n\t\t\tpayload: {\n\t\t\t\tpath,\n\t\t\t\tname,\n\t\t\t\tvalue,\n\t\t\t\tid,\n\t\t\t\tcollection\n\t\t\t}\n\t\t})).isUnique;\n\t}\n\tasync count(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"COUNT\",\n\t\t\tpayload: props\n\t\t})).count;\n\t}\n\tasync fetchUnmappedTables(mappedPaths) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_UNMAPPED_TABLES\",\n\t\t\tpayload: { mappedPaths }\n\t\t})).tables || [];\n\t}\n\tasync fetchTableMetadata(tableName) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_TABLE_METADATA\",\n\t\t\tpayload: { tableName }\n\t\t})).metadata || {\n\t\t\tcolumns: [],\n\t\t\tforeignKeys: [],\n\t\t\tjunctions: [],\n\t\t\tpolicies: []\n\t\t};\n\t}\n\tasync createBranch(name, options) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"CREATE_BRANCH\",\n\t\t\tpayload: {\n\t\t\t\tname,\n\t\t\t\toptions\n\t\t\t}\n\t\t})).branch;\n\t}\n\tasync deleteBranch(name) {\n\t\tawait this.sendMessage({\n\t\t\ttype: \"DELETE_BRANCH\",\n\t\t\tpayload: { name }\n\t\t});\n\t}\n\tasync listBranches() {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"LIST_BRANCHES\",\n\t\t\tpayload: {}\n\t\t})).branches || [];\n\t}\n\t/**\n\t* Recursively compare two values for structural equality.\n\t* Handles primitives, null, undefined, Date, RegExp, arrays, and plain objects.\n\t*/\n\tdeepEqual(a, b) {\n\t\tif (a === b) return true;\n\t\tif (a === null || b === null || a === void 0 || b === void 0) return false;\n\t\tif (typeof a !== typeof b) return false;\n\t\tif (typeof a !== \"object\") return false;\n\t\tif (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n\t\tif (a instanceof Date || b instanceof Date) return false;\n\t\tif (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;\n\t\tif (a instanceof RegExp || b instanceof RegExp) return false;\n\t\tconst aIsArray = Array.isArray(a);\n\t\tconst bIsArray = Array.isArray(b);\n\t\tif (aIsArray !== bIsArray) return false;\n\t\tif (aIsArray && bIsArray) {\n\t\t\tif (a.length !== b.length) return false;\n\t\t\tfor (let i = 0; i < a.length; i++) if (!this.deepEqual(a[i], b[i])) return false;\n\t\t\treturn true;\n\t\t}\n\t\tconst aObj = a;\n\t\tconst bObj = b;\n\t\tconst aKeys = Object.keys(aObj);\n\t\tconst bKeys = Object.keys(bObj);\n\t\tif (aKeys.length !== bKeys.length) return false;\n\t\tfor (const key of aKeys) {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;\n\t\t\tif (!this.deepEqual(aObj[key], bObj[key])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\tnormalizeForComparison(val) {\n\t\tif (!val) return val;\n\t\tif (Array.isArray(val)) return val.map((item) => this.normalizeForComparison(item));\n\t\tif (typeof val === \"object\") {\n\t\t\tif (val instanceof Date) return val;\n\t\t\tif (val instanceof RegExp) return val;\n\t\t\tconst obj = val;\n\t\t\tif (obj.__type === \"relation\") {\n\t\t\t\tconst { data, ...rest } = obj;\n\t\t\t\treturn rest;\n\t\t\t}\n\t\t\tconst result = {};\n\t\t\tfor (const [k, v] of Object.entries(obj)) result[k] = this.normalizeForComparison(v);\n\t\t\treturn result;\n\t\t}\n\t\treturn val;\n\t}\n\t/**\n\t* The address of a row, for matching it against another copy of itself.\n\t*\n\t* A row is exactly its columns and carries no address, so it is derived\n\t* from the key columns the server named — including the ordinary case where\n\t* that key is `id`, which the server reports like any other.\n\t*\n\t* Undefined when there are no keys, which means the server could not\n\t* resolve any: such rows genuinely cannot be recognised, and guessing at a\n\t* column called `id` would be inventing an identity for a table that has\n\t* none.\n\t*/\n\trowAddress(row, pks) {\n\t\tif (!pks || pks.length === 0) return void 0;\n\t\tconst address = buildCompositeId(row, pks);\n\t\tif (!address || address.split(COMPOSITE_ID_SEPARATOR).every((part) => part === \"\")) return void 0;\n\t\treturn address;\n\t}\n\t/**\n\t* Merge incoming rows with cached data, preserving cached references\n\t* for rows whose values haven't changed. This avoids unnecessary\n\t* React re-renders when the server refetches all rows but most\n\t* haven't actually changed.\n\t*/\n\tmergeRows(cached, incoming, pks) {\n\t\tif (!cached || cached.length === 0) return incoming;\n\t\tconst cachedById = /* @__PURE__ */ new Map();\n\t\tfor (const row of cached) {\n\t\t\tconst address = this.rowAddress(row, pks);\n\t\t\tif (address !== void 0) cachedById.set(address, row);\n\t\t}\n\t\treturn incoming.map((incomingRow) => {\n\t\t\tconst address = this.rowAddress(incomingRow, pks);\n\t\t\tconst cachedRow = address === void 0 ? void 0 : cachedById.get(address);\n\t\t\tif (!cachedRow) return incomingRow;\n\t\t\tconst normCached = this.normalizeForComparison(cachedRow);\n\t\t\tconst normIncoming = this.normalizeForComparison(incomingRow);\n\t\t\tif (this.deepEqual(normCached, normIncoming)) return cachedRow;\n\t\t\telse {\n\t\t\t\tconst mismatches = {};\n\t\t\t\tconst allKeys = /* @__PURE__ */ new Set([...Object.keys(normCached), ...Object.keys(normIncoming)]);\n\t\t\t\tfor (const key of allKeys) if (!this.deepEqual(normCached[key], normIncoming[key])) mismatches[key] = {\n\t\t\t\t\tcached: normCached[key],\n\t\t\t\t\tincoming: normIncoming[key]\n\t\t\t\t};\n\t\t\t\tconsole.debug(`[RebaseWS] Row ${address} refetch mismatch:\\n`, JSON.stringify(mismatches, null, 2));\n\t\t\t}\n\t\t\treturn incomingRow;\n\t\t});\n\t}\n\tlistenCollection(props, onUpdate, onError) {\n\t\tthis.ensureConnected();\n\t\tconst subscriptionKey = this.createCollectionSubscriptionKey(props);\n\t\tconst callbackId = `callback_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst existingSubscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (existingSubscription) {\n\t\t\tconst callbackMap = existingSubscription.callbacks;\n\t\t\tcallbackMap.set(callbackId, {\n\t\t\t\tonUpdate,\n\t\t\t\tonError\n\t\t\t});\n\t\t\tif (existingSubscription.latestData !== void 0 && existingSubscription.isInitialDataReceived) try {\n\t\t\t\tonUpdate(existingSubscription.latestData);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Error in collection subscription callback:\", error);\n\t\t\t\tif (onError) onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t}\n\t\t\telse if (!existingSubscription.subscribeInFlight) this.sendCollectionSubscribe(subscriptionKey);\n\t\t\treturn () => {\n\t\t\t\tcallbackMap.delete(callbackId);\n\t\t\t\tif (callbackMap.size === 0) {\n\t\t\t\t\tif (this.collectionSubscriptions.get(subscriptionKey) !== existingSubscription) return;\n\t\t\t\t\tif (existingSubscription.subscribeTimeout) clearTimeout(existingSubscription.subscribeTimeout);\n\t\t\t\t\tthis.collectionSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToCollectionKey.delete(existingSubscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: existingSubscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tconst backendSubscriptionId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst callbackMap = /* @__PURE__ */ new Map();\n\t\tcallbackMap.set(callbackId, {\n\t\t\tonUpdate,\n\t\t\tonError\n\t\t});\n\t\tthis.collectionSubscriptions.set(subscriptionKey, {\n\t\t\tbackendSubscriptionId,\n\t\t\tcallbacks: callbackMap,\n\t\t\tprops\n\t\t});\n\t\tthis.backendToCollectionKey.set(backendSubscriptionId, subscriptionKey);\n\t\tthis.sendCollectionSubscribe(subscriptionKey);\n\t\treturn () => {\n\t\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\tif (subscription) {\n\t\t\t\tconst callbacks = subscription.callbacks;\n\t\t\t\tcallbacks.delete(callbackId);\n\t\t\t\tif (callbacks.size === 0) {\n\t\t\t\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\t\t\t\tthis.collectionSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToCollectionKey.delete(subscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: subscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tlistenOne(props, onUpdate, onError) {\n\t\tthis.ensureConnected();\n\t\tconst subscriptionKey = this.createSingleSubscriptionKey(props);\n\t\tconst callbackId = `callback_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst existingSubscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (existingSubscription) {\n\t\t\tconst callbackMap = existingSubscription.callbacks;\n\t\t\tcallbackMap.set(callbackId, {\n\t\t\t\tonUpdate,\n\t\t\t\tonError\n\t\t\t});\n\t\t\tif (existingSubscription.latestData !== void 0 && existingSubscription.isInitialDataReceived) try {\n\t\t\t\tonUpdate(existingSubscription.latestData);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Error in row subscription callback:\", error);\n\t\t\t\tif (onError) onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t}\n\t\t\telse if (!existingSubscription.subscribeInFlight) this.sendEntitySubscribe(subscriptionKey);\n\t\t\treturn () => {\n\t\t\t\tcallbackMap.delete(callbackId);\n\t\t\t\tif (callbackMap.size === 0) {\n\t\t\t\t\tif (this.singleSubscriptions.get(subscriptionKey) !== existingSubscription) return;\n\t\t\t\t\tif (existingSubscription.subscribeTimeout) clearTimeout(existingSubscription.subscribeTimeout);\n\t\t\t\t\tthis.singleSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToEntityKey.delete(existingSubscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: existingSubscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tconst backendSubscriptionId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst callbackMap = /* @__PURE__ */ new Map();\n\t\tcallbackMap.set(callbackId, {\n\t\t\tonUpdate,\n\t\t\tonError\n\t\t});\n\t\tthis.singleSubscriptions.set(subscriptionKey, {\n\t\t\tbackendSubscriptionId,\n\t\t\tcallbacks: callbackMap,\n\t\t\tprops\n\t\t});\n\t\tthis.backendToEntityKey.set(backendSubscriptionId, subscriptionKey);\n\t\tthis.sendEntitySubscribe(subscriptionKey);\n\t\treturn () => {\n\t\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\t\tif (subscription) {\n\t\t\t\tconst callbacks = subscription.callbacks;\n\t\t\t\tcallbacks.delete(callbackId);\n\t\t\t\tif (callbacks.size === 0) {\n\t\t\t\t\tthis.singleSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToEntityKey.delete(subscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: subscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t* Send a `subscribe_collection` for an already-registered subscription and\n\t* arm its watchdog.\n\t*\n\t* Every path that registers a collection subscription goes through here, so\n\t* that a subscribe which never lands — a rejected send, or a server that\n\t* never answers — always ends up in `failCollectionSubscription` rather than\n\t* leaving the entry parked with `isInitialDataReceived === false` forever.\n\t*/\n\tsendCollectionSubscribe(subscriptionKey) {\n\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeInFlight = true;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeTimeout = void 0;\n\t\tif (this.isConnected) this.sendCollectionSubscribeWatchdog(subscriptionKey);\n\t\tthis.sendMessage({\n\t\t\ttype: \"subscribe_collection\",\n\t\t\tpayload: {\n\t\t\t\t...subscription.props,\n\t\t\t\tsubscriptionId: backendSubscriptionId\n\t\t\t}\n\t\t}).catch((error) => {\n\t\t\tconst current = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tthis.failCollectionSubscription(subscriptionKey, error instanceof Error ? error : new Error(String(error)));\n\t\t});\n\t}\n\t/** The `listenOne` counterpart of {@link sendCollectionSubscribe}. */\n\tsendEntitySubscribe(subscriptionKey) {\n\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeInFlight = true;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeTimeout = void 0;\n\t\tif (this.isConnected) this.sendEntitySubscribeWatchdog(subscriptionKey);\n\t\tthis.sendMessage({\n\t\t\ttype: \"subscribe_one\",\n\t\t\tpayload: {\n\t\t\t\t...subscription.props,\n\t\t\t\tsubscriptionId: backendSubscriptionId\n\t\t\t}\n\t\t}).catch((error) => {\n\t\t\tconst current = this.singleSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tthis.failEntitySubscription(subscriptionKey, error instanceof Error ? error : new Error(String(error)));\n\t\t});\n\t}\n\t/**\n\t* Report a subscribe failure to every listener and drop the registration.\n\t*\n\t* Dropping it is the point: the callbacks stay live (their components are\n\t* still mounted and have been told), but the next `listenCollection` for\n\t* these params finds no entry and issues a fresh subscribe instead of\n\t* silently attaching to a dead one.\n\t*/\n\tfailCollectionSubscription(subscriptionKey, error) {\n\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeInFlight = false;\n\t\tthis.collectionSubscriptions.delete(subscriptionKey);\n\t\tthis.backendToCollectionKey.delete(subscription.backendSubscriptionId);\n\t\tsubscription.callbacks.forEach((callback) => {\n\t\t\tif (callback.onError) try {\n\t\t\t\tcallback.onError(error);\n\t\t\t} catch (callbackError) {\n\t\t\t\tconsole.error(\"Error in collection subscription error callback:\", callbackError);\n\t\t\t}\n\t\t});\n\t}\n\t/** The `listenOne` counterpart of {@link failCollectionSubscription}. */\n\tfailEntitySubscription(subscriptionKey, error) {\n\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeInFlight = false;\n\t\tthis.singleSubscriptions.delete(subscriptionKey);\n\t\tthis.backendToEntityKey.delete(subscription.backendSubscriptionId);\n\t\tsubscription.callbacks.forEach((callback) => {\n\t\t\tif (callback.onError) try {\n\t\t\t\tcallback.onError(error);\n\t\t\t} catch (callbackError) {\n\t\t\t\tconsole.error(\"Error in row subscription error callback:\", callbackError);\n\t\t\t}\n\t\t});\n\t}\n\t/**\n\t* Stop the watchdogs without failing anything — used when the socket drops,\n\t* since the reconnect path re-subscribes everything anyway and a watchdog\n\t* firing mid-reconnect would tear down healthy subscriptions.\n\t*/\n\tsuspendSubscribeWatchdogs() {\n\t\tfor (const sub of this.collectionSubscriptions.values()) {\n\t\t\tif (sub.subscribeTimeout) clearTimeout(sub.subscribeTimeout);\n\t\t\tsub.subscribeTimeout = void 0;\n\t\t\tsub.subscribeInFlight = false;\n\t\t}\n\t\tfor (const sub of this.singleSubscriptions.values()) {\n\t\t\tif (sub.subscribeTimeout) clearTimeout(sub.subscribeTimeout);\n\t\t\tsub.subscribeTimeout = void 0;\n\t\t\tsub.subscribeInFlight = false;\n\t\t}\n\t}\n\t/**\n\t* Arm watchdogs for subscribes that were requested while offline and have\n\t* just been flushed to the socket. Their timers were deliberately not set at\n\t* request time, so without this they would have no timeout at all.\n\t*/\n\tarmPendingSubscribeWatchdogs() {\n\t\tfor (const [key, sub] of this.collectionSubscriptions.entries()) if (sub.subscribeInFlight && !sub.subscribeTimeout) this.sendCollectionSubscribeWatchdog(key);\n\t\tfor (const [key, sub] of this.singleSubscriptions.entries()) if (sub.subscribeInFlight && !sub.subscribeTimeout) this.sendEntitySubscribeWatchdog(key);\n\t}\n\tsendCollectionSubscribeWatchdog(subscriptionKey) {\n\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeTimeout = setTimeout(() => {\n\t\t\tconst current = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tif (!current.subscribeInFlight) return;\n\t\t\tthis.failCollectionSubscription(subscriptionKey, new RebaseApiError$1(\"Subscription timed out\", { code: \"SUBSCRIPTION_TIMEOUT\" }));\n\t\t}, this.subscriptionTimeoutMs);\n\t}\n\tsendEntitySubscribeWatchdog(subscriptionKey) {\n\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeTimeout = setTimeout(() => {\n\t\t\tconst current = this.singleSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tif (!current.subscribeInFlight) return;\n\t\t\tthis.failEntitySubscription(subscriptionKey, new RebaseApiError$1(\"Subscription timed out\", { code: \"SUBSCRIPTION_TIMEOUT\" }));\n\t\t}, this.subscriptionTimeoutMs);\n\t}\n\t/**\n\t* Fail every subscription that never received data. Called when reconnection\n\t* is given up on, so views surface an error instead of spinning forever.\n\t*/\n\tfailAllPendingSubscriptions(error) {\n\t\tfor (const key of [...this.collectionSubscriptions.keys()]) {\n\t\t\tconst sub = this.collectionSubscriptions.get(key);\n\t\t\tif (sub && !sub.isInitialDataReceived) this.failCollectionSubscription(key, error);\n\t\t}\n\t\tfor (const key of [...this.singleSubscriptions.keys()]) {\n\t\t\tconst sub = this.singleSubscriptions.get(key);\n\t\t\tif (sub && !sub.isInitialDataReceived) this.failEntitySubscription(key, error);\n\t\t}\n\t}\n\t/**\n\t* Re-send all active subscriptions to the backend after a reconnect.\n\t* The server wipes subscription state when a client disconnects, so\n\t* we need to re-register everything to resume receiving updates.\n\t*/\n\tresubscribeAll() {\n\t\tconsole.debug(`[WS] Re-subscribing: ${this.collectionSubscriptions.size} collection(s), ${this.singleSubscriptions.size} row(ies)`);\n\t\tfor (const [key, sub] of this.collectionSubscriptions.entries()) {\n\t\t\tconst oldBackendId = sub.backendSubscriptionId;\n\t\t\tconst newBackendId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\tsub.backendSubscriptionId = newBackendId;\n\t\t\tthis.backendToCollectionKey.delete(oldBackendId);\n\t\t\tthis.backendToCollectionKey.set(newBackendId, key);\n\t\t\tthis.sendCollectionSubscribe(key);\n\t\t}\n\t\tfor (const [key, sub] of this.singleSubscriptions.entries()) {\n\t\t\tconst oldBackendId = sub.backendSubscriptionId;\n\t\t\tconst newBackendId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\tsub.backendSubscriptionId = newBackendId;\n\t\t\tthis.backendToEntityKey.delete(oldBackendId);\n\t\t\tthis.backendToEntityKey.set(newBackendId, key);\n\t\t\tthis.sendEntitySubscribe(key);\n\t\t}\n\t}\n\tcreateCollectionSubscriptionKey(props) {\n\t\tconst key = {\n\t\t\tpath: props.path,\n\t\t\tfilter: props.filter,\n\t\t\tlimit: props.limit,\n\t\t\tstartAfter: props.startAfter,\n\t\t\torderBy: props.orderBy,\n\t\t\torder: props.order,\n\t\t\tsearchString: props.searchString,\n\t\t\tcollection: props.collection?.name\n\t\t};\n\t\treturn JSON.stringify(key, (_, value) => {\n\t\t\tif (value && typeof value === \"object\" && !Array.isArray(value)) return Object.keys(value).sort().reduce((sorted, k) => {\n\t\t\t\tsorted[k] = value[k];\n\t\t\t\treturn sorted;\n\t\t\t}, {});\n\t\t\treturn value;\n\t\t});\n\t}\n\tcreateSingleSubscriptionKey(props) {\n\t\treturn `${props.path}|${props.id}`;\n\t}\n};\n//#endregion\n//#region src/realtime-channel.ts\n/**\n* Re-send presence comfortably inside the server's 30s expiry.\n*\n* Two-thirds of the window: one lost heartbeat still leaves time for the next\n* before the entry is reaped, so a single dropped frame is not a disappearance.\n*/\nvar PRESENCE_HEARTBEAT_MS = 2e4;\n/**\n* How long live messages are held back waiting for a catch-up response.\n*\n* Short, because the cost of waiting is visible — on a collaborative document\n* this is a stall in everyone else's edits appearing. Long enough that a slow\n* replay of a busy channel is not abandoned needlessly.\n*/\nvar CATCH_UP_TIMEOUT_MS = 1e4;\nvar RebaseRealtimeChannel = class {\n\tname;\n\ttransport;\n\tpresenceHandlers = /* @__PURE__ */ new Set();\n\tbroadcastHandlers = /* @__PURE__ */ new Set();\n\tunsubscribers = [];\n\t/** Last known roster, kept so handlers always get a full picture. */\n\tpresences = {};\n\t/** What this client last tracked, replayed on reconnect and heartbeat. */\n\ttrackedState = null;\n\theartbeat = null;\n\tjoined = false;\n\t/** Whether this handle asks the server to replay missed messages. */\n\twantsHistory;\n\t/**\n\t* Highest sequence number delivered to handlers so far.\n\t*\n\t* This is the resume point sent as `sinceSeq`, and the watermark that makes\n\t* replay idempotent: catch-up ranges overlap with what arrived live, and\n\t* anything at or below this has already been seen.\n\t*/\n\tlastSeq = 0;\n\t/**\n\t* Live messages that arrived while a catch-up was in flight.\n\t*\n\t* Without this they would be delivered ahead of the older messages being\n\t* fetched, and — worse — would advance {@link lastSeq} past them, so the\n\t* catch-up response would then be discarded as already-seen and those\n\t* messages would be lost for good. Held here and flushed, in order, once\n\t* the replay lands.\n\t*/\n\tpendingLive = [];\n\tcatchUpInFlight = false;\n\t/**\n\t* Deadline for a catch-up response.\n\t*\n\t* Buffering live messages is only safe because the wait is bounded. A\n\t* catch-up frame that never arrives — a server that dropped it, a socket\n\t* that died between request and reply — would otherwise leave the channel\n\t* silently holding every subsequent edit forever, which is a worse failure\n\t* than the one replay was added to fix.\n\t*/\n\tcatchUpTimeout = null;\n\t/**\n\t* Callers of {@link history} awaiting the next `channel_history` frame.\n\t*\n\t* These frames are addressed by channel rather than by request id, so they\n\t* are matched in arrival order. Requests on one channel are serialized by\n\t* the socket, so FIFO is the right correlation here.\n\t*/\n\thistoryWaiters = [];\n\tconstructor(name, transport, options = {}) {\n\t\tthis.name = name;\n\t\tthis.transport = transport;\n\t\tthis.wantsHistory = options.history ?? false;\n\t}\n\t/**\n\t* Turn on catch-up for a handle that was created without it.\n\t*\n\t* The client hands back the same channel object for a given name, so a\n\t* later `channel(name, { history: true })` has no new object to configure —\n\t* it upgrades this one instead. Idempotent, and never downgrades: one\n\t* caller asking for history must not be switched off by another that did\n\t* not ask.\n\t*/\n\tenableHistory() {\n\t\tif (this.wantsHistory) return;\n\t\tthis.wantsHistory = true;\n\t\tif (this.joined) this.requestHistory();\n\t}\n\t/**\n\t* Join the channel and ask for the current roster.\n\t*\n\t* Called automatically by `track`, `broadcast`, `onPresence` and\n\t* `onBroadcast`; calling it directly is only needed to start receiving\n\t* before there is anything to send.\n\t*/\n\t/**\n\t* Send a channel message.\n\t*\n\t* Every channel message is read by the server out of a `payload` envelope\n\t* (`payload?.channel`, `payload?.state`, `payload?.event`). Sending those\n\t* fields flat does not error: `payload?.channel` simply reads as\n\t* `undefined`, so the client is registered into channel `undefined` with\n\t* empty state, and the echo comes back with no `channel` for\n\t* `onChannelMessage` to match — presence and broadcast both go quiet with\n\t* nothing logged. Funnelled through one place so a new message type cannot\n\t* reintroduce that.\n\t*/\n\tsend(type, fields = {}) {\n\t\treturn this.transport.sendMessage({\n\t\t\ttype,\n\t\t\tpayload: {\n\t\t\t\tchannel: this.name,\n\t\t\t\t...fields\n\t\t\t}\n\t\t});\n\t}\n\tasync join() {\n\t\tif (this.joined) return;\n\t\tthis.joined = true;\n\t\tthis.unsubscribers.push(this.transport.onChannelMessage(this.name, (message) => this.handle(message)));\n\t\tthis.unsubscribers.push(this.transport.onReconnect(() => {\n\t\t\tthis.rejoin();\n\t\t}));\n\t\tawait this.send(\"join_channel\");\n\t\tawait this.send(\"presence_state\");\n\t\tif (this.wantsHistory) await this.requestHistory();\n\t}\n\tasync rejoin() {\n\t\ttry {\n\t\t\tawait this.send(\"join_channel\");\n\t\t\tawait this.send(\"presence_state\");\n\t\t\tif (this.trackedState) await this.send(\"presence_track\", { state: this.trackedState });\n\t\t\tif (this.wantsHistory) await this.requestHistory();\n\t\t} catch {}\n\t}\n\t/**\n\t* Ask the server for everything after {@link lastSeq}.\n\t*\n\t* Live messages are buffered from here until the answer arrives — see\n\t* {@link pendingLive}.\n\t*/\n\tasync requestHistory(limit) {\n\t\tthis.catchUpInFlight = true;\n\t\tif (this.catchUpTimeout) clearTimeout(this.catchUpTimeout);\n\t\tthis.catchUpTimeout = setTimeout(() => this.abandonCatchUp(), CATCH_UP_TIMEOUT_MS);\n\t\tthis.catchUpTimeout.unref?.();\n\t\ttry {\n\t\t\tawait this.send(\"channel_history\", {\n\t\t\t\tsinceSeq: this.lastSeq,\n\t\t\t\t...limit !== void 0 ? { limit } : {}\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.abandonCatchUp();\n\t\t}\n\t}\n\t/**\n\t* Give up waiting for a catch-up and release what was held back.\n\t*\n\t* The buffered messages are still the freshest thing this client has, so\n\t* they are delivered rather than dropped. Callers of {@link history} are\n\t* answered with `retained: false` — accurate in the sense that matters:\n\t* this client has no history to work from and has to resync.\n\t*/\n\tabandonCatchUp() {\n\t\tif (this.catchUpTimeout) {\n\t\t\tclearTimeout(this.catchUpTimeout);\n\t\t\tthis.catchUpTimeout = null;\n\t\t}\n\t\tif (!this.catchUpInFlight) return;\n\t\tthis.catchUpInFlight = false;\n\t\tfor (const resolve of this.historyWaiters.splice(0)) resolve({\n\t\t\tmessages: [],\n\t\t\tretained: false\n\t\t});\n\t\tthis.flushPendingLive();\n\t}\n\t/**\n\t* Publish this client's presence state, and keep publishing it.\n\t*\n\t* Calling `track` again replaces the state (and restarts the heartbeat),\n\t* which is how you update e.g. a cursor position.\n\t*/\n\tasync track(state) {\n\t\tawait this.join();\n\t\tthis.trackedState = state;\n\t\tawait this.send(\"presence_track\", { state });\n\t\tif (!this.heartbeat) {\n\t\t\tthis.heartbeat = setInterval(() => {\n\t\t\t\tif (!this.trackedState) return;\n\t\t\t\tthis.send(\"presence_track\", { state: this.trackedState }).catch(() => {});\n\t\t\t}, PRESENCE_HEARTBEAT_MS);\n\t\t\tthis.heartbeat.unref?.();\n\t\t}\n\t}\n\t/** Stop publishing presence, without leaving the channel. */\n\tasync untrack() {\n\t\tthis.stopHeartbeat();\n\t\tthis.trackedState = null;\n\t\tif (this.joined) await this.send(\"presence_untrack\");\n\t}\n\t/**\n\t* Observe the roster. The handler fires immediately with what is already\n\t* known, then on every change.\n\t*/\n\tonPresence(handler) {\n\t\tthis.presenceHandlers.add(handler);\n\t\tthis.join();\n\t\tif (Object.keys(this.presences).length > 0) handler({ ...this.presences });\n\t\treturn () => this.presenceHandlers.delete(handler);\n\t}\n\t/** Send a broadcast. The sender does not receive its own message. */\n\tasync broadcast(event, payload) {\n\t\tawait this.join();\n\t\tawait this.send(\"broadcast\", {\n\t\t\tevent,\n\t\t\tpayload\n\t\t});\n\t}\n\tonBroadcast(eventOrHandler, maybeHandler) {\n\t\tconst wrapped = typeof eventOrHandler === \"string\" ? (e) => {\n\t\t\tif (e.event === eventOrHandler) maybeHandler(e.payload);\n\t\t} : eventOrHandler;\n\t\tthis.broadcastHandlers.add(wrapped);\n\t\tthis.join();\n\t\treturn () => this.broadcastHandlers.delete(wrapped);\n\t}\n\t/**\n\t* The last sequence number this channel has delivered.\n\t*\n\t* Zero on a channel that retains nothing. Persist it if you want catch-up\n\t* to survive a page reload as well as a reconnect, and pass it back via\n\t* {@link history}.\n\t*/\n\tget sequence() {\n\t\treturn this.lastSeq;\n\t}\n\t/**\n\t* Fetch retained messages explicitly, instead of waiting for join or\n\t* reconnect to do it.\n\t*\n\t* Defaults to resuming from {@link sequence}. Messages are delivered to\n\t* `onBroadcast` handlers as usual — the returned value is for callers that\n\t* want to inspect the batch, or to learn from `retained` that the channel\n\t* keeps no history at all.\n\t*/\n\tasync history(options = {}) {\n\t\tawait this.join();\n\t\tif (options.sinceSeq !== void 0) this.lastSeq = options.sinceSeq;\n\t\tconst result = new Promise((resolve) => {\n\t\t\tthis.historyWaiters.push(resolve);\n\t\t});\n\t\tawait this.requestHistory(options.limit);\n\t\treturn result;\n\t}\n\t/** Leave the channel and release every listener and timer. */\n\tasync leave() {\n\t\tthis.stopHeartbeat();\n\t\tthis.trackedState = null;\n\t\tthis.presences = {};\n\t\tthis.presenceHandlers.clear();\n\t\tthis.broadcastHandlers.clear();\n\t\tthis.lastSeq = 0;\n\t\tthis.pendingLive = [];\n\t\tthis.catchUpInFlight = false;\n\t\tif (this.catchUpTimeout) {\n\t\t\tclearTimeout(this.catchUpTimeout);\n\t\t\tthis.catchUpTimeout = null;\n\t\t}\n\t\tfor (const resolve of this.historyWaiters.splice(0)) resolve({\n\t\t\tmessages: [],\n\t\t\tretained: false\n\t\t});\n\t\tfor (const off of this.unsubscribers) off();\n\t\tthis.unsubscribers = [];\n\t\tif (this.joined) {\n\t\t\tthis.joined = false;\n\t\t\tawait this.send(\"leave_channel\");\n\t\t}\n\t}\n\tstopHeartbeat() {\n\t\tif (this.heartbeat) {\n\t\t\tclearInterval(this.heartbeat);\n\t\t\tthis.heartbeat = null;\n\t\t}\n\t}\n\t/** Fold an incoming frame into the roster and fan it out. */\n\thandle(message) {\n\t\tswitch (message.type) {\n\t\t\tcase \"presence_state\":\n\t\t\t\tthis.presences = message.presences ?? {};\n\t\t\t\tthis.emitPresence();\n\t\t\t\tbreak;\n\t\t\tcase \"presence_diff\": {\n\t\t\t\tconst joins = message.joins ?? {};\n\t\t\t\tconst leaves = message.leaves ?? {};\n\t\t\t\tfor (const [id, state] of Object.entries(joins)) this.presences[id] = state;\n\t\t\t\tfor (const id of Object.keys(leaves)) delete this.presences[id];\n\t\t\t\tthis.emitPresence({\n\t\t\t\t\tjoins,\n\t\t\t\t\tleaves\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"broadcast\": {\n\t\t\t\tconst seq = typeof message.seq === \"number\" ? message.seq : void 0;\n\t\t\t\tconst event = {\n\t\t\t\t\tevent: message.event,\n\t\t\t\t\tpayload: message.payload,\n\t\t\t\t\t...seq !== void 0 ? { seq } : {}\n\t\t\t\t};\n\t\t\t\tif (seq === void 0) {\n\t\t\t\t\tthis.deliver(event);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (this.catchUpInFlight) {\n\t\t\t\t\tthis.pendingLive.push(event);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (seq <= this.lastSeq) break;\n\t\t\t\tthis.lastSeq = seq;\n\t\t\t\tthis.deliver(event);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"channel_history\": {\n\t\t\t\tthis.catchUpInFlight = false;\n\t\t\t\tif (this.catchUpTimeout) {\n\t\t\t\t\tclearTimeout(this.catchUpTimeout);\n\t\t\t\t\tthis.catchUpTimeout = null;\n\t\t\t\t}\n\t\t\t\tconst entries = message.messages ?? [];\n\t\t\t\tconst retained = message.retained === true;\n\t\t\t\tconst latestSeq = typeof message.latestSeq === \"number\" ? message.latestSeq : void 0;\n\t\t\t\tfor (const resolve of this.historyWaiters.splice(0)) resolve({\n\t\t\t\t\tmessages: entries,\n\t\t\t\t\tretained,\n\t\t\t\t\tlatestSeq\n\t\t\t\t});\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tif (entry.seq <= this.lastSeq) continue;\n\t\t\t\t\tthis.lastSeq = entry.seq;\n\t\t\t\t\tthis.deliver({\n\t\t\t\t\t\tevent: entry.event,\n\t\t\t\t\t\tpayload: entry.payload,\n\t\t\t\t\t\tseq: entry.seq,\n\t\t\t\t\t\treplayed: true\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthis.flushPendingLive();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t/** Deliver everything held back during a catch-up, in sequence order. */\n\tflushPendingLive() {\n\t\tif (this.pendingLive.length === 0) return;\n\t\tconst buffered = this.pendingLive.sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0));\n\t\tthis.pendingLive = [];\n\t\tfor (const event of buffered) {\n\t\t\tconst seq = event.seq;\n\t\t\tif (seq !== void 0) {\n\t\t\t\tif (seq <= this.lastSeq) continue;\n\t\t\t\tthis.lastSeq = seq;\n\t\t\t}\n\t\t\tthis.deliver(event);\n\t\t}\n\t}\n\tdeliver(event) {\n\t\tfor (const handler of [...this.broadcastHandlers]) handler(event);\n\t}\n\temitPresence(diff) {\n\t\tconst snapshot = { ...this.presences };\n\t\tfor (const handler of this.presenceHandlers) handler(snapshot, diff);\n\t}\n};\n//#endregion\n//#region src/offline-codec.ts\n/**\n* Lossless round-tripping of rows through the offline store.\n*\n* Both persistence backends move values by structured clone, which keeps\n* `Date` but flattens every class instance to a plain object. For\n* `EntityReference`/`EntityRelation` that is harmless — they carry their own\n* `__type` discriminator, so the JSON reviver can rebuild them — but\n* `GeoPoint` and `Vector` do not, and would come back out of the cache as\n* anonymous `{ latitude, longitude }` / `{ value }` bags. A row read from the\n* cache must be indistinguishable from the same row read from the network, so\n* those two are tagged on the way in and revived on the way out.\n*\n* Type tests here are structural rather than `instanceof`, because a structured\n* clone can arrive from another realm — an iframe, a worker, or the polyfill\n* the tests run against — where the constructor identity differs but the value\n* is the real thing. Only *plain* objects are walked; anything else is passed\n* through whole, so a class instance is never quietly reduced to `{}`.\n*/\nfunction isDate(value) {\n\treturn Object.prototype.toString.call(value) === \"[object Date]\";\n}\n/** An object literal — not a Date, RegExp, Map, or any class instance. */\nfunction isPlainObject(value) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto === null || proto === Object.prototype) return true;\n\treturn proto.constructor?.name === \"Object\";\n}\nfunction dehydrateValue(value) {\n\tif (value === null || value === void 0) return value;\n\tif (value instanceof GeoPoint) return {\n\t\t__type: \"GeoPoint\",\n\t\tlatitude: value.latitude,\n\t\tlongitude: value.longitude\n\t};\n\tif (value instanceof Vector) return {\n\t\t__type: \"Vector\",\n\t\tvalue: [...value.value]\n\t};\n\tif (value instanceof EntityReference || value instanceof EntityRelation) return value;\n\tif (Array.isArray(value)) return value.map(dehydrateValue);\n\tif (isPlainObject(value)) {\n\t\tconst out = {};\n\t\tfor (const [key, inner] of Object.entries(value)) out[key] = dehydrateValue(inner);\n\t\treturn out;\n\t}\n\treturn value;\n}\nfunction hydrateValue(value) {\n\tif (value === null || value === void 0 || isDate(value)) return value;\n\tif (Array.isArray(value)) return value.map(hydrateValue);\n\tif (typeof value === \"object\") {\n\t\tconst revived = rebaseReviver(\"\", value);\n\t\tif (revived !== value) return revived;\n\t\tif (!isPlainObject(value)) return value;\n\t\tconst out = {};\n\t\tfor (const [key, inner] of Object.entries(value)) out[key] = hydrateValue(inner);\n\t\treturn out;\n\t}\n\treturn value;\n}\n/** Prepare a row for the store. */\nfunction dehydrateRow(row) {\n\treturn dehydrateValue(row);\n}\n/** Restore a row read back from the store. */\nfunction hydrateRow(row) {\n\treturn hydrateValue(row);\n}\n//#endregion\n//#region src/offline-connectivity.ts\n/**\n* Whether the network is worth trying, and when to try again after it wasn't.\n*\n* `navigator.onLine` is necessary but not sufficient: it reports the state of\n* the network interface, so it stays `true` behind a captive portal, on a\n* connection that resolves DNS but reaches nothing, and while the API itself\n* is down. This tracks what actually happened to requests as well, so the\n* first failure is the only one an app pays for — everything after it inside\n* the backoff window skips the doomed round trip and answers from the local\n* store immediately, which is the difference between an app that freezes when\n* the wifi drops and one that does not.\n*/\n/** The request never reached the server, so nothing was decided by it. */\nfunction isNetworkError(error) {\n\tif (error instanceof RebaseApiError) return error.status === 0;\n\tif (error instanceof TypeError) return true;\n\tconst name = error?.name;\n\treturn name === \"AbortError\" || name === \"TimeoutError\" || name === \"NetworkError\";\n}\n/**\n* Statuses that mean \"not now\" rather than \"not ever\": a queued write that\n* gets one of these is worth replaying, while a 400 or a 403 never will be.\n* 500 is deliberately absent — an unhandled server error is far more often a\n* bug the same payload will hit again than a blip, and retrying it forever\n* jams every write behind it.\n*/\nvar RETRYABLE_STATUSES = /* @__PURE__ */ new Set([\n\t408,\n\t425,\n\t429,\n\t502,\n\t503,\n\t504\n]);\n/** Is this failure worth another attempt later? */\nfunction isRetryableError(error) {\n\tif (isNetworkError(error)) return true;\n\tif (error instanceof RebaseApiError) return error.status !== void 0 && RETRYABLE_STATUSES.has(error.status);\n\treturn false;\n}\n/**\n* Did this write fail because the row is already there?\n*\n* Matched on the SQLSTATE the server passes through (`23505`, unique_violation)\n* and on 409, never on the message — a duplicate-key message names the\n* constraint and the values, so it is neither stable nor safe to parse.\n*\n* The queue uses this to recognise its own earlier attempt. A create whose\n* response was lost is replayed, and for a row carrying an id the SDK generated\n* the server can only be rejecting it because the first attempt actually landed.\n*/\nfunction isDuplicateKeyError(error) {\n\tif (!(error instanceof RebaseApiError)) return false;\n\treturn error.code === \"23505\" || error.status === 409;\n}\nvar ConnectivityMonitor = class {\n\tstate = \"online\";\n\tbackoffMs;\n\tinitialBackoffMs;\n\tmaxBackoffMs;\n\tretryAt = 0;\n\ttimer;\n\tlisteners = /* @__PURE__ */ new Set();\n\trespectBackoff;\n\tnow;\n\tsetTimer;\n\tclearTimer;\n\t/** Called when the backoff window expires, to drive an automatic retry. */\n\tonRetryDue;\n\thandleOnline = () => {\n\t\tthis.retryAt = 0;\n\t\tthis.backoffMs = this.initialBackoffMs;\n\t\tthis.clearPendingTimer();\n\t\tthis.setState(\"online\");\n\t\tthis.onRetryDue?.();\n\t};\n\thandleOffline = () => {\n\t\tthis.setState(\"offline\");\n\t};\n\tconstructor(options = {}) {\n\t\tthis.initialBackoffMs = options.initialBackoffMs ?? 1e3;\n\t\tthis.maxBackoffMs = Math.max(this.initialBackoffMs, options.maxBackoffMs ?? 6e4);\n\t\tthis.backoffMs = this.initialBackoffMs;\n\t\tthis.respectBackoff = options.respectBackoff ?? true;\n\t\tthis.now = options.now ?? (() => Date.now());\n\t\tthis.setTimer = options.setTimer ?? ((fn, ms) => setTimeout(fn, ms));\n\t\tthis.clearTimer = options.clearTimer ?? ((handle) => clearTimeout(handle));\n\t\tif (typeof window !== \"undefined\" && typeof window.addEventListener === \"function\") {\n\t\t\twindow.addEventListener(\"online\", this.handleOnline);\n\t\t\twindow.addEventListener(\"offline\", this.handleOffline);\n\t\t}\n\t\tif (typeof navigator !== \"undefined\" && navigator.onLine === false) this.state = \"offline\";\n\t}\n\t/** What the app should be told: are we connected? */\n\tisOnline() {\n\t\tif (typeof navigator !== \"undefined\" && navigator.onLine === false) return false;\n\t\treturn this.state === \"online\";\n\t}\n\t/**\n\t* Should this request even be sent? False means \"answer from the local\n\t* store instead\" — the request would only burn a timeout to reach the same\n\t* conclusion the last one already did.\n\t*/\n\tshouldAttempt() {\n\t\tif (typeof navigator !== \"undefined\" && navigator.onLine === false) return false;\n\t\tif (this.state === \"online\" || !this.respectBackoff) return true;\n\t\treturn this.now() >= this.retryAt;\n\t}\n\t/** A request reached the server. */\n\tmarkSuccess() {\n\t\tthis.backoffMs = this.initialBackoffMs;\n\t\tthis.retryAt = 0;\n\t\tthis.clearPendingTimer();\n\t\tthis.setState(\"online\");\n\t}\n\t/** A request did not reach the server: we are offline until proven otherwise. */\n\tmarkFailure() {\n\t\tthis.deferRetry();\n\t\tthis.setState(\"offline\");\n\t}\n\t/**\n\t* Back off and try again later without claiming the connection is gone.\n\t* This is what a 429 or a 503 deserves — the server answered, so the app\n\t* is demonstrably online; it just should not hammer.\n\t*/\n\tdeferRetry() {\n\t\tconst jitter = .8 + Math.random() * .4;\n\t\tthis.retryAt = this.now() + this.backoffMs * jitter;\n\t\tconst delay = Math.max(0, this.retryAt - this.now());\n\t\tthis.backoffMs = Math.min(this.maxBackoffMs, this.backoffMs * 2);\n\t\tthis.scheduleRetry(delay);\n\t}\n\t/** Milliseconds until the next attempt is allowed; 0 when one is allowed now. */\n\tmsUntilRetry() {\n\t\tif (this.state === \"online\") return 0;\n\t\treturn Math.max(0, this.retryAt - this.now());\n\t}\n\tonChange(listener) {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\tdispose() {\n\t\tif (typeof window !== \"undefined\" && typeof window.removeEventListener === \"function\") {\n\t\t\twindow.removeEventListener(\"online\", this.handleOnline);\n\t\t\twindow.removeEventListener(\"offline\", this.handleOffline);\n\t\t}\n\t\tthis.clearPendingTimer();\n\t\tthis.listeners.clear();\n\t\tthis.onRetryDue = void 0;\n\t}\n\tscheduleRetry(delay) {\n\t\tthis.clearPendingTimer();\n\t\tif (!this.onRetryDue) return;\n\t\tthis.timer = this.setTimer(() => {\n\t\t\tthis.timer = void 0;\n\t\t\tthis.onRetryDue?.();\n\t\t}, delay);\n\t\tthis.timer.unref?.();\n\t}\n\tclearPendingTimer() {\n\t\tif (this.timer !== void 0) {\n\t\t\tthis.clearTimer(this.timer);\n\t\t\tthis.timer = void 0;\n\t\t}\n\t}\n\tsetState(next) {\n\t\tif (this.state === next) return;\n\t\tthis.state = next;\n\t\tconst online = this.isOnline();\n\t\tfor (const listener of this.listeners) listener(online);\n\t}\n};\n//#endregion\n//#region src/offline-store.ts\n/**\n* Monotonic within a tab, unique across tabs, and sortable as a plain string:\n* `<ms base36, padded>-<counter>-<random>`. The padding is what keeps\n* lexicographic order equal to chronological order, and the random suffix is\n* what stops two tabs from writing the same queue key in the same millisecond\n* — which would silently drop one of the two writes.\n*/\nvar mutationCounter = 0;\nfunction createMutationId(now = Date.now()) {\n\treturn `${now.toString(36).padStart(10, \"0\")}-${(mutationCounter = (mutationCounter + 1) % 1679616).toString(36).padStart(4, \"0\")}-${Math.random().toString(36).slice(2, 10).padStart(8, \"0\")}`;\n}\n/**\n* In-memory store: the default outside the browser and the workhorse of the\n* test suite. Values are deep-copied on the way in and out so a caller\n* mutating a returned row cannot silently edit the \"persisted\" copy — the\n* IndexedDB implementation gets the same guarantee for free from structured\n* cloning, and the two must not differ in aliasing behaviour.\n*/\nvar MemoryOfflineStore = class {\n\tcache = /* @__PURE__ */ new Map();\n\tqueue = /* @__PURE__ */ new Map();\n\tasync getCache(key) {\n\t\tconst entry = this.cache.get(key);\n\t\treturn entry ? structuredClone(entry) : void 0;\n\t}\n\tasync setCache(key, entry) {\n\t\tthis.cache.set(key, structuredClone(entry));\n\t}\n\tasync setCacheMany(entries) {\n\t\tfor (const { key, entry } of entries) this.cache.set(key, structuredClone(entry));\n\t}\n\tasync deleteCache(keys) {\n\t\tfor (const key of keys) this.cache.delete(key);\n\t}\n\tasync listCache(prefix) {\n\t\tconst out = [];\n\t\tfor (const [key, entry] of this.cache) if (key.startsWith(prefix)) out.push({\n\t\t\tkey,\n\t\t\tcachedAt: entry.cachedAt\n\t\t});\n\t\treturn out;\n\t}\n\tasync listCacheEntries(prefix) {\n\t\tconst out = [];\n\t\tfor (const [key, entry] of this.cache) if (key.startsWith(prefix)) out.push({\n\t\t\tkey,\n\t\t\t...structuredClone(entry)\n\t\t});\n\t\tout.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);\n\t\treturn out;\n\t}\n\tasync enqueue(key, mutation) {\n\t\tthis.queue.set(key, structuredClone(mutation));\n\t}\n\tasync dequeue(key) {\n\t\tthis.queue.delete(key);\n\t}\n\tasync listQueue(prefix) {\n\t\treturn [...this.queue.entries()].filter(([key]) => key.startsWith(prefix)).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, mutation]) => structuredClone(mutation));\n\t}\n\tasync clear(prefix) {\n\t\tfor (const key of [...this.cache.keys()]) if (key.startsWith(prefix)) this.cache.delete(key);\n\t\tfor (const key of [...this.queue.keys()]) if (key.startsWith(prefix)) this.queue.delete(key);\n\t}\n};\nvar IDB_NAME = \"rebase-offline\";\n/**\n* v2 introduced the normalized row cache and string mutation ids. A v1\n* database holds whole-response blobs under keys this version cannot read and\n* queue entries ordered by a numeric `seq` this version no longer writes, so\n* the upgrade drops both stores rather than trying to translate them. Offline\n* support had not shipped in a release when v2 landed, so nothing in the wild\n* loses a queued write to this.\n*/\nvar IDB_VERSION = 2;\nvar CACHE_STORE = \"cache\";\nvar QUEUE_STORE = \"queue\";\n/** The exclusive upper bound of an IDBKeyRange covering every key under `prefix`. */\nfunction prefixRange(prefix) {\n\treturn IDBKeyRange.bound(prefix, prefix + \"\", false, false);\n}\nfunction requestToPromise(request) {\n\treturn new Promise((resolve, reject) => {\n\t\trequest.onsuccess = () => resolve(request.result);\n\t\trequest.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error(\"IndexedDB request failed\"));\n\t});\n}\n/** Resolve when the whole transaction commits, not just when the last request returns. */\nfunction transactionDone(tx) {\n\treturn new Promise((resolve, reject) => {\n\t\ttx.oncomplete = () => resolve();\n\t\ttx.onabort = tx.onerror = () => reject(tx.error ?? /* @__PURE__ */ new Error(\"IndexedDB transaction failed\"));\n\t});\n}\n/**\n* IndexedDB-backed store — the browser default, so cached rows and queued\n* writes survive a reload or a browser restart. Everything lives in one\n* database with two object stores; keys are the manager's full prefixed\n* strings, so multiple users (scopes) share the database without ever\n* sharing entries.\n*/\nvar IndexedDBOfflineStore = class {\n\tdbPromise;\n\topen() {\n\t\tif (!this.dbPromise) this.dbPromise = new Promise((resolve, reject) => {\n\t\t\tconst request = indexedDB.open(IDB_NAME, IDB_VERSION);\n\t\t\trequest.onupgradeneeded = (event) => {\n\t\t\t\tconst db = request.result;\n\t\t\t\tif (event.oldVersion > 0 && event.oldVersion < 2) {\n\t\t\t\t\tif (db.objectStoreNames.contains(CACHE_STORE)) db.deleteObjectStore(CACHE_STORE);\n\t\t\t\t\tif (db.objectStoreNames.contains(QUEUE_STORE)) db.deleteObjectStore(QUEUE_STORE);\n\t\t\t\t}\n\t\t\t\tif (!db.objectStoreNames.contains(CACHE_STORE)) db.createObjectStore(CACHE_STORE);\n\t\t\t\tif (!db.objectStoreNames.contains(QUEUE_STORE)) db.createObjectStore(QUEUE_STORE);\n\t\t\t};\n\t\t\trequest.onsuccess = () => {\n\t\t\t\tconst db = request.result;\n\t\t\t\tdb.onversionchange = () => {\n\t\t\t\t\tdb.close();\n\t\t\t\t\tthis.dbPromise = void 0;\n\t\t\t\t};\n\t\t\t\tresolve(db);\n\t\t\t};\n\t\t\trequest.onerror = () => {\n\t\t\t\tthis.dbPromise = void 0;\n\t\t\t\treject(request.error ?? /* @__PURE__ */ new Error(\"Failed to open IndexedDB\"));\n\t\t\t};\n\t\t\trequest.onblocked = () => {\n\t\t\t\tthis.dbPromise = void 0;\n\t\t\t\treject(/* @__PURE__ */ new Error(\"IndexedDB upgrade blocked by another tab\"));\n\t\t\t};\n\t\t});\n\t\treturn this.dbPromise;\n\t}\n\tasync store(name, mode) {\n\t\treturn (await this.open()).transaction(name, mode).objectStore(name);\n\t}\n\tasync getCache(key) {\n\t\treturn await requestToPromise((await this.store(CACHE_STORE, \"readonly\")).get(key));\n\t}\n\tasync setCache(key, entry) {\n\t\tawait requestToPromise((await this.store(CACHE_STORE, \"readwrite\")).put(entry, key));\n\t}\n\tasync setCacheMany(entries) {\n\t\tif (entries.length === 0) return;\n\t\tconst store = await this.store(CACHE_STORE, \"readwrite\");\n\t\tfor (const { key, entry } of entries) store.put(entry, key);\n\t\tawait transactionDone(store.transaction);\n\t}\n\tasync deleteCache(keys) {\n\t\tif (keys.length === 0) return;\n\t\tconst store = await this.store(CACHE_STORE, \"readwrite\");\n\t\tfor (const key of keys) store.delete(key);\n\t\tawait transactionDone(store.transaction);\n\t}\n\tasync listCache(prefix) {\n\t\tconst store = await this.store(CACHE_STORE, \"readonly\");\n\t\tconst [keys, entries] = await Promise.all([requestToPromise(store.getAllKeys(prefixRange(prefix))), requestToPromise(store.getAll(prefixRange(prefix)))]);\n\t\treturn keys.map((key, i) => ({\n\t\t\tkey: String(key),\n\t\t\tcachedAt: entries[i]?.cachedAt ?? 0\n\t\t}));\n\t}\n\tasync listCacheEntries(prefix) {\n\t\tconst store = await this.store(CACHE_STORE, \"readonly\");\n\t\tconst [keys, entries] = await Promise.all([requestToPromise(store.getAllKeys(prefixRange(prefix))), requestToPromise(store.getAll(prefixRange(prefix)))]);\n\t\treturn keys.map((key, i) => {\n\t\t\tconst entry = entries[i];\n\t\t\treturn {\n\t\t\t\tkey: String(key),\n\t\t\t\tvalue: entry?.value,\n\t\t\t\tcachedAt: entry?.cachedAt ?? 0\n\t\t\t};\n\t\t});\n\t}\n\tasync enqueue(key, mutation) {\n\t\tawait requestToPromise((await this.store(QUEUE_STORE, \"readwrite\")).put(mutation, key));\n\t}\n\tasync dequeue(key) {\n\t\tawait requestToPromise((await this.store(QUEUE_STORE, \"readwrite\")).delete(key));\n\t}\n\tasync listQueue(prefix) {\n\t\treturn await requestToPromise((await this.store(QUEUE_STORE, \"readonly\")).getAll(prefixRange(prefix)));\n\t}\n\tasync clear(prefix) {\n\t\tawait requestToPromise((await this.store(CACHE_STORE, \"readwrite\")).delete(prefixRange(prefix)));\n\t\tawait requestToPromise((await this.store(QUEUE_STORE, \"readwrite\")).delete(prefixRange(prefix)));\n\t}\n};\n//#endregion\n//#region src/offline-query.ts\n/**\n* A local evaluator for `FindParams`, so cached rows can answer a query the\n* client has never sent to the server — and so a row written offline shows up\n* in every filtered list it belongs to, not just in unfiltered ones.\n*\n* This mirrors the Postgres driver's semantics rather than JavaScript's:\n*\n* - Comparing against NULL is *unknown*, not false-or-true. `status != \"done\"`\n* excludes rows where `status` is null, exactly as SQL does — a JS `!==`\n* would have included them.\n* - `ORDER BY` puts nulls last ascending and first descending, which is the\n* Postgres default.\n* - The wire format carries no types, so values arriving as strings are\n* compared numerically against numeric columns and as instants against\n* date columns. `[\"==\", \"3\"]` matches the number `3`, as it does server-side.\n*\n* Two things it deliberately approximates, both flagged by\n* {@link isExactlyEvaluable}: `searchString` becomes a case-insensitive\n* substring scan over the row's string fields (the server runs real full-text\n* search over the collection's configured columns), and `include` cannot be\n* evaluated at all, because the related rows live in collections this query\n* knows nothing about.\n*/\nvar collator = typeof Intl !== \"undefined\" && typeof Intl.Collator === \"function\" ? new Intl.Collator(void 0, {\n\tnumeric: false,\n\tsensitivity: \"variant\"\n}) : void 0;\nfunction isNullish(value) {\n\treturn value === null || value === void 0;\n}\n/**\n* Reduce a value to something comparable. Relations compare by the id they\n* point at — the column holds a foreign key, so that is what the server\n* compares too.\n*/\nfunction toComparable(value) {\n\tif (value instanceof Date) return value.getTime();\n\tif (value instanceof EntityRelation) return value.id;\n\tif (value && typeof value === \"object\") {\n\t\tconst record = value;\n\t\tif (typeof record.__type === \"string\" && \"id\" in record) return record.id;\n\t}\n\treturn value;\n}\n/**\n* Three-way compare with SQL's type coercion but not its collation. Returns\n* `undefined` when the two values are not ordered relative to each other,\n* which is how NULL propagates through a comparison.\n*/\nfunction compareValues(a, b) {\n\tconst left = toComparable(a);\n\tconst right = toComparable(b);\n\tif (isNullish(left) || isNullish(right)) return void 0;\n\tif (typeof left === \"boolean\" || typeof right === \"boolean\") return (left === true || left === \"true\" || left === 1 ? 1 : 0) - (right === true || right === \"true\" || right === 1 ? 1 : 0);\n\tconst leftNum = typeof left === \"number\" ? left : numericOrNaN(left);\n\tconst rightNum = typeof right === \"number\" ? right : numericOrNaN(right);\n\tif (!Number.isNaN(leftNum) && !Number.isNaN(rightNum)) return leftNum < rightNum ? -1 : leftNum > rightNum ? 1 : 0;\n\tif (typeof left === \"number\" || typeof right === \"number\") {\n\t\tconst leftTime = toTime(left);\n\t\tconst rightTime = toTime(right);\n\t\tif (leftTime !== void 0 && rightTime !== void 0) return leftTime < rightTime ? -1 : leftTime > rightTime ? 1 : 0;\n\t}\n\tconst leftStr = String(left);\n\tconst rightStr = String(right);\n\tif (collator) return collator.compare(leftStr, rightStr);\n\treturn leftStr < rightStr ? -1 : leftStr > rightStr ? 1 : 0;\n}\nfunction numericOrNaN(value) {\n\tif (typeof value === \"number\") return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst n = Number(value);\n\t\treturn Number.isNaN(n) ? NaN : n;\n\t}\n\tif (typeof value === \"bigint\") return Number(value);\n\treturn NaN;\n}\nfunction toTime(value) {\n\tif (typeof value === \"number\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst t = Date.parse(value);\n\t\treturn Number.isNaN(t) ? void 0 : t;\n\t}\n}\n/** Equality with the wire's type erasure allowed for, but never across NULL. */\nfunction looseEquals(a, b) {\n\tconst left = toComparable(a);\n\tconst right = toComparable(b);\n\tif (isNullish(left) || isNullish(right)) return isNullish(left) && isNullish(right);\n\tif (left === right) return true;\n\treturn compareValues(left, right) === 0;\n}\n/**\n* Translate a SQL `LIKE` pattern to an anchored regular expression.\n* `%` matches any run of characters, `_` exactly one, and a backslash escapes\n* either of them.\n*/\nfunction likeToRegExp(pattern, caseInsensitive) {\n\tlet source = \"^\";\n\tfor (let i = 0; i < pattern.length; i++) {\n\t\tconst char = pattern[i];\n\t\tif (char === \"\\\\\" && i + 1 < pattern.length) {\n\t\t\tsource += pattern[i + 1].replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\t\t\ti++;\n\t\t} else if (char === \"%\") source += \"[\\\\s\\\\S]*\";\n\t\telse if (char === \"_\") source += \"[\\\\s\\\\S]\";\n\t\telse source += char.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\t}\n\treturn new RegExp(source + \"$\", caseInsensitive ? \"i\" : \"\");\n}\nfunction asArray(value) {\n\tif (Array.isArray(value)) return value;\n\tif (value === void 0) return [];\n\treturn [value];\n}\n/** Evaluate one canonical operator against one row value. */\nfunction matchesOperator(rowValue, op, filterValue) {\n\tswitch (op) {\n\t\tcase \"is-null\": return isNullish(rowValue);\n\t\tcase \"is-not-null\": return !isNullish(rowValue);\n\t\tcase \"==\": return looseEquals(rowValue, filterValue);\n\t\tcase \"!=\":\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\treturn !looseEquals(rowValue, filterValue);\n\t\tcase \"<\":\n\t\tcase \"<=\":\n\t\tcase \">\":\n\t\tcase \">=\": {\n\t\t\tconst cmp = compareValues(rowValue, filterValue);\n\t\t\tif (cmp === void 0) return false;\n\t\t\tif (op === \"<\") return cmp < 0;\n\t\t\tif (op === \"<=\") return cmp <= 0;\n\t\t\tif (op === \">\") return cmp > 0;\n\t\t\treturn cmp >= 0;\n\t\t}\n\t\tcase \"in\":\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\treturn asArray(filterValue).some((v) => looseEquals(rowValue, v));\n\t\tcase \"not-in\":\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\treturn !asArray(filterValue).some((v) => looseEquals(rowValue, v));\n\t\tcase \"array-contains\":\n\t\t\tif (!Array.isArray(rowValue)) return false;\n\t\t\treturn rowValue.some((v) => looseEquals(v, filterValue));\n\t\tcase \"array-contains-any\": {\n\t\t\tif (!Array.isArray(rowValue)) return false;\n\t\t\tconst wanted = asArray(filterValue);\n\t\t\treturn rowValue.some((v) => wanted.some((w) => looseEquals(v, w)));\n\t\t}\n\t\tcase \"like\":\n\t\tcase \"not-like\":\n\t\tcase \"ilike\":\n\t\tcase \"not-ilike\": {\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\tconst insensitive = op === \"ilike\" || op === \"not-ilike\";\n\t\t\tconst negated = op === \"not-like\" || op === \"not-ilike\";\n\t\t\tconst matched = likeToRegExp(String(filterValue), insensitive).test(String(rowValue));\n\t\t\treturn negated ? !matched : matched;\n\t\t}\n\t\tdefault: return true;\n\t}\n}\nfunction isTuple(value) {\n\treturn Array.isArray(value) && value.length === 2 && typeof value[0] === \"string\" && toCanonicalOp(value[0]) !== void 0;\n}\n/** Evaluate a `where` clause: every field, and every tuple on a field, AND-ed. */\nfunction matchesWhere(row, where) {\n\tif (!where) return true;\n\tfor (const [field, condition] of Object.entries(where)) {\n\t\tif (condition === void 0) continue;\n\t\tconst tuples = isTuple(condition) ? [condition] : Array.isArray(condition) ? condition.filter(isTuple) : [];\n\t\tfor (const [rawOp, value] of tuples) {\n\t\t\tconst op = toCanonicalOp(rawOp) ?? rawOp;\n\t\t\tif (!matchesOperator(row[field], op, value)) return false;\n\t\t}\n\t}\n\treturn true;\n}\n/** Evaluate a nested and/or tree. */\nfunction matchesLogical(row, condition) {\n\tif (!condition) return true;\n\tif (\"type\" in condition) {\n\t\tconst children = condition.conditions ?? [];\n\t\tif (children.length === 0) return true;\n\t\treturn condition.type === \"or\" ? children.some((c) => matchesLogical(row, c)) : children.every((c) => matchesLogical(row, c));\n\t}\n\tconst op = toCanonicalOp(condition.operator) ?? condition.operator;\n\treturn matchesOperator(row[condition.column], op, condition.value);\n}\n/**\n* Approximate the server's full-text search with a case-insensitive substring\n* scan over the row's own string fields. Narrower than the real thing (no\n* stemming, no configured search columns), and it never matches a field the\n* cached row does not carry — a local list may therefore be missing rows the\n* server would have returned, which is why {@link isExactlyEvaluable} refuses\n* to call a search query exact.\n*/\nfunction matchesSearch(row, searchString) {\n\tif (!searchString) return true;\n\tconst needle = searchString.trim().toLowerCase();\n\tif (!needle) return true;\n\tfor (const value of Object.values(row)) {\n\t\tif (typeof value === \"string\" && value.toLowerCase().includes(needle)) return true;\n\t\tif (typeof value === \"number\" && String(value).includes(needle)) return true;\n\t}\n\treturn false;\n}\n/** Does this row belong in the result set for `params`, ignoring pagination? */\nfunction matchesParams(row, params) {\n\tif (!params) return true;\n\treturn matchesWhere(row, params.where) && matchesLogical(row, params.logical) && matchesSearch(row, params.searchString);\n}\n/**\n* Sort in place, Postgres-style: nulls last ascending, first descending, with\n* the row id as a tiebreak so paging through an unsorted-but-equal run does\n* not shuffle rows between pages.\n*/\nfunction sortRows(rows, orderBy) {\n\tif (!orderBy) return rows;\n\tconst [field, direction = \"asc\"] = orderBy;\n\tconst sign = direction === \"desc\" ? -1 : 1;\n\treturn rows.sort((a, b) => {\n\t\tconst av = a[field];\n\t\tconst bv = b[field];\n\t\tconst aNull = isNullish(toComparable(av));\n\t\tconst bNull = isNullish(toComparable(bv));\n\t\tif (aNull || bNull) {\n\t\t\tif (aNull && bNull) return tiebreak(a, b);\n\t\t\treturn (aNull ? 1 : -1) * (direction === \"desc\" ? -1 : 1);\n\t\t}\n\t\tconst cmp = compareValues(av, bv);\n\t\tif (cmp === void 0 || cmp === 0) return tiebreak(a, b);\n\t\treturn cmp * sign;\n\t});\n}\nfunction tiebreak(a, b) {\n\treturn compareValues(a.id, b.id) ?? 0;\n}\n/** Resolve `page`/`offset`/`limit` the way the server does. */\nfunction resolvePagination(params) {\n\tconst limit = params?.limit ?? 20;\n\treturn {\n\t\tlimit,\n\t\toffset: params?.page != null ? Math.max(0, (params.page - 1) * limit) : params?.offset ?? 0\n\t};\n}\n/**\n* Can a locally evaluated answer to `params` be trusted to match the server's,\n* assuming the cache holds every row of the collection?\n*\n* `include` pulls in rows from other collections that this evaluator never\n* sees, and `searchString` is only approximated — both make the local answer a\n* best effort rather than an equivalent one.\n*/\nfunction isExactlyEvaluable(params) {\n\tif (!params) return true;\n\tif (params.include && params.include.length > 0) return false;\n\tif (params.searchString) return false;\n\treturn true;\n}\n/** Run a full query — filter, sort, paginate — over a set of rows. */\nfunction runLocalQuery(rows, params) {\n\tconst matched = rows.filter((row) => matchesParams(row, params));\n\tsortRows(matched, params?.orderBy);\n\tconst { limit, offset } = resolvePagination(params);\n\tconst page = matched.slice(offset, offset + limit);\n\treturn {\n\t\tdata: page,\n\t\tmeta: {\n\t\t\ttotal: matched.length,\n\t\t\tlimit,\n\t\t\toffset,\n\t\t\thasMore: offset + page.length < matched.length\n\t\t}\n\t};\n}\n//#endregion\n//#region src/offline.ts\n/** True when a read failed because there was neither network nor local data. */\nfunction isOfflineError(error) {\n\treturn error instanceof RebaseApiError && error.code === \"offline\";\n}\nfunction offlineError(message) {\n\treturn new RebaseApiError(message, {\n\t\tstatus: 0,\n\t\tcode: \"offline\"\n\t});\n}\nfunction generateOfflineId() {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n\treturn `off-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\nvar MISSING = \"\\0missing\";\nvar OfflineManager = class {\n\tstore;\n\tmaxCachedQueries;\n\tmaxCachedRows;\n\tmaxRetries;\n\tonSyncError;\n\tcreateInner;\n\tinners = /* @__PURE__ */ new Map();\n\tconnectivity;\n\tscope = \"anon\";\n\t/** The local database: normalized rows and query snapshots per collection. */\n\tcollections = /* @__PURE__ */ new Map();\n\t/** In-memory mirror of the current scope's queue, in replay order. */\n\tqueue = [];\n\t/**\n\t* The mutation currently on the wire, if any.\n\t*\n\t* `flush` awaits `replay(op)` with `op` still at the head of `queue`, so for\n\t* the whole duration of that request the in-flight op is also the queue's\n\t* *tail* whenever it is the only entry. Both shortcuts in `enqueue` reach\n\t* for the tail, and neither may touch an op the server is already reading:\n\t*\n\t* - Coalescing an update into it mutates a payload that has already been\n\t* serialized and sent, and `drop` then removes the whole entry on ACK —\n\t* so the second edit is neither sent nor kept. A silently lost write.\n\t* - Cancelling it out against a delete assumes the server never saw the\n\t* create. It is seeing it right now, so the row would be created and the\n\t* delete never queued — an orphan row nothing will ever remove.\n\t*\n\t* Guarding on the id rather than on a boolean keeps this correct if the\n\t* flush loop ever sends more than one op at a time.\n\t*/\n\tinFlightId = null;\n\tqueueLoad;\n\t/** Serializes enqueues so concurrent writes keep the order the app made them. */\n\tenqueueChain = Promise.resolve();\n\tflushPromise;\n\tqueueListeners = /* @__PURE__ */ new Set();\n\tstatusListeners = /* @__PURE__ */ new Set();\n\tobservers = /* @__PURE__ */ new Map();\n\trefreshPending = /* @__PURE__ */ new Set();\n\trevCounter = 0;\n\tdisposed = false;\n\tcurrentStatus = {\n\t\tonline: true,\n\t\tsyncing: false,\n\t\tpending: 0\n\t};\n\tchannel;\n\ttabId = createMutationId();\n\tapi;\n\tconstructor(config, createInner) {\n\t\tthis.store = config.store ?? (typeof indexedDB !== \"undefined\" ? new IndexedDBOfflineStore() : new MemoryOfflineStore());\n\t\tthis.maxCachedQueries = config.maxCachedQueriesPerCollection ?? 50;\n\t\tthis.maxCachedRows = config.maxCachedRowsPerCollection ?? 5e3;\n\t\tthis.maxRetries = config.maxRetries ?? 5;\n\t\tthis.onSyncError = config.onSyncError;\n\t\tthis.createInner = createInner;\n\t\tconst maxBackoffMs = config.syncIntervalMs ?? 6e4;\n\t\tthis.connectivity = new ConnectivityMonitor({\n\t\t\tmaxBackoffMs: Math.max(1e3, maxBackoffMs),\n\t\t\trespectBackoff: maxBackoffMs > 0\n\t\t});\n\t\tif (maxBackoffMs > 0) this.connectivity.onRetryDue = () => {\n\t\t\tthis.sync().catch(() => void 0);\n\t\t};\n\t\tthis.connectivity.onChange((online) => {\n\t\t\tthis.patchStatus({ online });\n\t\t\tif (online) this.revalidateAll();\n\t\t});\n\t\tthis.currentStatus.online = this.connectivity.isOnline();\n\t\tif ((config.crossTab ?? this.store instanceof IndexedDBOfflineStore) && typeof BroadcastChannel !== \"undefined\") try {\n\t\t\tthis.channel = new BroadcastChannel(\"rebase-offline\");\n\t\t\tthis.channel.onmessage = (event) => this.onBroadcast(event.data);\n\t\t\tthis.channel.unref?.();\n\t\t} catch {}\n\t\tthis.api = {\n\t\t\tsync: () => this.sync(),\n\t\t\tpending: async () => {\n\t\t\t\tawait this.ensureQueueLoaded();\n\t\t\t\treturn this.queue.map((m) => structuredClone(m));\n\t\t\t},\n\t\t\tstatus: () => ({ ...this.currentStatus }),\n\t\t\tonStatusChange: (listener) => {\n\t\t\t\tthis.statusListeners.add(listener);\n\t\t\t\treturn () => this.statusListeners.delete(listener);\n\t\t\t},\n\t\t\tclear: async () => {\n\t\t\t\tawait this.store.clear(`${this.scope}|`);\n\t\t\t\tthis.queue = [];\n\t\t\t\tthis.resetCollections();\n\t\t\t\tthis.patchStatus({\n\t\t\t\t\tpending: 0,\n\t\t\t\t\tlastError: void 0\n\t\t\t\t});\n\t\t\t\tthis.notifyQueue();\n\t\t\t\tfor (const slug of this.observers.keys()) this.notifyCollection(slug, false);\n\t\t\t},\n\t\t\tonQueueChange: (listener) => {\n\t\t\t\tthis.queueListeners.add(listener);\n\t\t\t\treturn () => this.queueListeners.delete(listener);\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t* Cache and queue are partitioned per signed-in user: cached rows are\n\t* RLS-filtered for the user who fetched them, and queued writes must\n\t* replay under the credentials that made them — so neither may ever leak\n\t* across a sign-out/sign-in on a shared browser.\n\t*/\n\tsetScope(uid) {\n\t\tconst next = uid || \"anon\";\n\t\tif (next === this.scope) return;\n\t\tthis.scope = next;\n\t\tthis.queueLoad = void 0;\n\t\tthis.queue = [];\n\t\tthis.resetCollections();\n\t\tthis.patchStatus({\n\t\t\tpending: 0,\n\t\t\tlastError: void 0\n\t\t});\n\t\tthis.notifyQueue();\n\t\tfor (const slug of this.observers.keys()) this.notifyCollection(slug, false);\n\t\tthis.revalidateAll();\n\t\tthis.sync().catch(() => void 0);\n\t}\n\t/**\n\t* Throw away every local row, for a scope change or an explicit clear.\n\t*\n\t* The state objects are replaced rather than emptied, so a load still in\n\t* flight for the previous user fails its identity check and discards what\n\t* it read instead of grafting it onto the new one. The replacements are\n\t* marked ready: nothing needs loading until something asks, and observers\n\t* have to be told *now* that the rows they are showing are gone.\n\t*/\n\tresetCollections() {\n\t\tconst slugs = [...this.collections.keys()];\n\t\tthis.collections = /* @__PURE__ */ new Map();\n\t\tfor (const slug of slugs) this.collections.set(slug, {\n\t\t\trows: /* @__PURE__ */ new Map(),\n\t\t\tsnapshots: /* @__PURE__ */ new Map(),\n\t\t\tfresh: /* @__PURE__ */ new Set(),\n\t\t\tfreshRows: /* @__PURE__ */ new Set(),\n\t\t\tabsent: /* @__PURE__ */ new Set(),\n\t\t\tready: true\n\t\t});\n\t}\n\t/** Release listeners, timers and the cross-tab channel (client.close()). */\n\tdispose() {\n\t\tthis.disposed = true;\n\t\tthis.connectivity.dispose();\n\t\ttry {\n\t\t\tthis.channel?.close();\n\t\t} catch {}\n\t\tthis.observers.clear();\n\t\tthis.queueListeners.clear();\n\t\tthis.statusListeners.clear();\n\t}\n\twrap(slug, inner) {\n\t\tthis.inners.set(slug, inner);\n\t\tconst wrapped = {\n\t\t\tfind: async (params) => {\n\t\t\t\tconst state = await this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst res = await inner.find(params);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, res.data ?? []);\n\t\t\t\t\tconst snapshot = this.recordSnapshot(slug, params, res);\n\t\t\t\t\tconst answer = this.answer(slug, params, snapshot);\n\t\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: answer.data,\n\t\t\t\t\t\tmeta: answer.meta\n\t\t\t\t\t};\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) {\n\t\t\t\t\t\tif (isRetryableError(error) && this.hasLocalAnswer(state, slug, params)) {\n\t\t\t\t\t\t\tconst answer = this.answer(slug, params, this.snapshotFor(slug, params));\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tdata: answer.data,\n\t\t\t\t\t\t\t\tmeta: answer.meta\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst answer = this.localFind(slug, params);\n\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\treturn {\n\t\t\t\t\tdata: answer.data,\n\t\t\t\t\tmeta: answer.meta\n\t\t\t\t};\n\t\t\t},\n\t\t\titerate: (params) => paginateFind((p) => wrapped.find(p), params, slug),\n\t\t\tfindAll: (params) => collectAllPages((p) => wrapped.find(p), params, slug),\n\t\t\tfindById: async (id) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst row = await inner.findById(id);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tif (row !== void 0) await this.ingest(slug, [row]);\n\t\t\t\t\telse if (!this.hasPending(slug, id)) this.removeLocalRow(slug, id, true);\n\t\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\t\treturn this.localRow(slug, id);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst local = this.localRow(slug, id);\n\t\t\t\tif (local !== void 0 || this.hasPending(slug, id)) return local;\n\t\t\t\tif (this.collections.get(slug)?.absent.has(String(id))) return void 0;\n\t\t\t\tthrow offlineError(`Offline: \"${slug}\" row ${String(id)} is not in the local database.`);\n\t\t\t},\n\t\t\tcreate: async (data, id) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst row = await inner.create(data, id);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, [row]);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t\t\treturn row;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst providedId = id ?? data.id;\n\t\t\t\tconst rowId = providedId ?? generateOfflineId();\n\t\t\t\tconst row = {\n\t\t\t\t\t...data,\n\t\t\t\t\tid: rowId\n\t\t\t\t};\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"create\",\n\t\t\t\t\tid: rowId,\n\t\t\t\t\tdata: row,\n\t\t\t\t\tgeneratedId: providedId === void 0,\n\t\t\t\t\trollback: { rows: { [String(rowId)]: this.rawLocalRow(slug, rowId) ?? null } }\n\t\t\t\t});\n\t\t\t\tthis.setLocalRow(slug, rowId, row);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\treturn row;\n\t\t\t},\n\t\t\tcreateMany: async (data, options) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (!Array.isArray(data)) throw new TypeError(\"createMany expects an array of records.\");\n\t\t\t\tif (data.length === 0) return [];\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst rows = await inner.createMany(data, options);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, rows);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t\t\treturn rows;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst rows = data.map((r) => ({\n\t\t\t\t\t...r,\n\t\t\t\t\tid: r.id ?? generateOfflineId()\n\t\t\t\t}));\n\t\t\t\tconst rollback = {};\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst key = String(row.id);\n\t\t\t\t\trollback[key] = this.rawLocalRow(slug, row.id) ?? null;\n\t\t\t\t}\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"createMany\",\n\t\t\t\t\tdata: rows,\n\t\t\t\t\tupsert: options?.upsert,\n\t\t\t\t\trollback: { rows: rollback }\n\t\t\t\t});\n\t\t\t\tfor (const row of rows) this.setLocalRow(slug, row.id, row);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\treturn rows;\n\t\t\t},\n\t\t\tupdate: async (id, data) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt() && !this.hasPending(slug, id)) try {\n\t\t\t\t\tconst row = await inner.update(id, data);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, [row]);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\treturn row;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst base = this.rawLocalRow(slug, id);\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"update\",\n\t\t\t\t\tid,\n\t\t\t\t\tdata,\n\t\t\t\t\trollback: { rows: { [String(id)]: base ?? null } }\n\t\t\t\t});\n\t\t\t\tconst optimistic = {\n\t\t\t\t\t...base ?? {},\n\t\t\t\t\t...data,\n\t\t\t\t\tid\n\t\t\t\t};\n\t\t\t\tthis.setLocalRow(slug, id, optimistic);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\treturn optimistic;\n\t\t\t},\n\t\t\tdelete: async (id) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt() && !this.hasPending(slug, id)) try {\n\t\t\t\t\tawait inner.delete(id);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tthis.removeLocalRow(slug, id, true);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"delete\",\n\t\t\t\t\tid,\n\t\t\t\t\trollback: { rows: { [String(id)]: this.rawLocalRow(slug, id) ?? null } }\n\t\t\t\t});\n\t\t\t\tthis.removeLocalRow(slug, id);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t},\n\t\t\tcount: async (params) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst n = await inner.count(params);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tthis.writeCache(this.countKey(slug, params), n);\n\t\t\t\t\treturn Math.max(0, n + this.pendingDelta(slug, params));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst cached = await this.readCache(this.countKey(slug, params));\n\t\t\t\tif (cached !== void 0) return Math.max(0, cached + this.pendingDelta(slug, params));\n\t\t\t\tconst state = this.collections.get(slug);\n\t\t\t\tif (state && state.rows.size > 0) return runLocalQuery([...state.rows.values()].map((e) => e.row), params).meta.total;\n\t\t\t\tthrow offlineError(`Offline: no cached count for \"${slug}\".`);\n\t\t\t},\n\t\t\tobserve: (params, onResult, onError, options) => this.observe(slug, wrapped, inner, params, onResult, onError, options),\n\t\t\tobserveById: (id, onResult, onError, options) => this.observeById(slug, wrapped, inner, id, onResult, onError, options),\n\t\t\twhere(columnOrCondition, operator, value) {\n\t\t\t\tconst builder = new SDKQueryBuilder(wrapped);\n\t\t\t\tif (typeof columnOrCondition === \"object\") return builder.where(columnOrCondition);\n\t\t\t\treturn builder.where(columnOrCondition, operator, value);\n\t\t\t},\n\t\t\torderBy: (column, direction) => new SDKQueryBuilder(wrapped).orderBy(column, direction),\n\t\t\tlimit: (count) => new SDKQueryBuilder(wrapped).limit(count),\n\t\t\toffset: (count) => new SDKQueryBuilder(wrapped).offset(count),\n\t\t\tsearch: (searchString) => new SDKQueryBuilder(wrapped).search(searchString),\n\t\t\tinclude: (...relations) => new SDKQueryBuilder(wrapped).include(...relations)\n\t\t};\n\t\tif (inner.listen) wrapped.listen = (params, onUpdate, onError) => inner.listen(params, (response) => {\n\t\t\tthis.ingest(slug, response.data ?? []).then(() => this.notifyCollection(slug, false));\n\t\t\tonUpdate(response);\n\t\t}, onError);\n\t\tif (inner.listenById) wrapped.listenById = (id, onUpdate, onError) => inner.listenById(id, (row) => {\n\t\t\tif (row) this.ingest(slug, [row]).then(() => this.notifyCollection(slug, false));\n\t\t\tonUpdate(row);\n\t\t}, onError);\n\t\treturn wrapped;\n\t}\n\tobserve(slug, wrapped, inner, params, onResult, onError, options) {\n\t\tlet closed = false;\n\t\tlet unlisten;\n\t\tconst observer = {\n\t\t\tslug,\n\t\t\tparams,\n\t\t\tsettled: false,\n\t\t\trefresh: () => wrapped.find(params).catch(() => void 0),\n\t\t\temit: () => {\n\t\t\t\tif (closed || !this.collections.get(slug)?.ready) return;\n\t\t\t\tconst result = this.answer(slug, params, this.snapshotFor(slug, params));\n\t\t\t\tconst signature = `${result.fromCache ? \"c\" : \"s\"}${result.hasPendingWrites ? \"p\" : \"-\"}` + this.signature(slug, result.data, result.meta.total);\n\t\t\t\tif (observer.settled && signature === observer.signature) return;\n\t\t\t\tobserver.signature = signature;\n\t\t\t\tobserver.settled = true;\n\t\t\t\tonResult(observer.error ? {\n\t\t\t\t\t...result,\n\t\t\t\t\terror: observer.error\n\t\t\t\t} : result);\n\t\t\t}\n\t\t};\n\t\tthis.observersFor(slug).add(observer);\n\t\t(async () => {\n\t\t\tawait this.ensureCollection(slug);\n\t\t\tif (closed) return;\n\t\t\tif (this.hasLocalAnswer(this.collections.get(slug), slug, params)) observer.emit();\n\t\t\ttry {\n\t\t\t\tawait wrapped.find(params);\n\t\t\t\tobserver.error = void 0;\n\t\t\t} catch (error) {\n\t\t\t\tobserver.error = error;\n\t\t\t\tif (closed) return;\n\t\t\t\tif (!observer.settled) {\n\t\t\t\t\tonError?.(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!closed) observer.emit();\n\t\t})();\n\t\tif (options?.realtime !== false && inner.listen) unlisten = inner.listen(params, (response) => {\n\t\t\tthis.ingest(slug, response.data ?? []).then(() => {\n\t\t\t\tthis.recordSnapshot(slug, params, response);\n\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t});\n\t\t}, onError);\n\t\treturn () => {\n\t\t\tclosed = true;\n\t\t\tthis.observersFor(slug).delete(observer);\n\t\t\tunlisten?.();\n\t\t};\n\t}\n\tobserveById(slug, wrapped, inner, id, onResult, onError, options) {\n\t\tlet closed = false;\n\t\tlet unlisten;\n\t\tconst observer = {\n\t\t\tslug,\n\t\t\tid,\n\t\t\tsettled: false,\n\t\t\trefresh: () => wrapped.findById(id).catch(() => void 0),\n\t\t\temit: () => {\n\t\t\t\tif (closed || !this.collections.get(slug)?.ready) return;\n\t\t\t\tconst row = this.localRow(slug, id);\n\t\t\t\tconst entry = this.collections.get(slug)?.rows.get(String(id));\n\t\t\t\tconst fromCache = !this.collections.get(slug)?.freshRows.has(String(id));\n\t\t\t\tconst hasPendingWrites = this.hasPending(slug, id);\n\t\t\t\tconst signature = `${fromCache ? \"c\" : \"s\"}${hasPendingWrites ? \"p\" : \"-\"}|` + (row === void 0 ? MISSING : `${String(id)}:${entry?.rev ?? 0}`);\n\t\t\t\tif (observer.settled && signature === observer.signature) return;\n\t\t\t\tobserver.signature = signature;\n\t\t\t\tobserver.settled = true;\n\t\t\t\tonResult(row, {\n\t\t\t\t\tfromCache,\n\t\t\t\t\thasPendingWrites\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t\tthis.observersFor(slug).add(observer);\n\t\t(async () => {\n\t\t\tawait this.ensureCollection(slug);\n\t\t\tif (closed) return;\n\t\t\tif (this.localRow(slug, id) !== void 0) observer.emit();\n\t\t\ttry {\n\t\t\t\tawait wrapped.findById(id);\n\t\t\t} catch (error) {\n\t\t\t\tif (closed) return;\n\t\t\t\tif (!observer.settled) {\n\t\t\t\t\tonError?.(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!closed) observer.emit();\n\t\t})();\n\t\tif (options?.realtime !== false && inner.listenById) unlisten = inner.listenById(id, (row) => {\n\t\t\tif (!row) {\n\t\t\t\tif (!this.hasPending(slug, id)) this.removeLocalRow(slug, id, true);\n\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.ingest(slug, [row]).then(() => this.notifyCollection(slug, false));\n\t\t}, onError);\n\t\treturn () => {\n\t\t\tclosed = true;\n\t\t\tthis.observersFor(slug).delete(observer);\n\t\t\tunlisten?.();\n\t\t};\n\t}\n\tobserversFor(slug) {\n\t\tlet set = this.observers.get(slug);\n\t\tif (!set) {\n\t\t\tset = /* @__PURE__ */ new Set();\n\t\t\tthis.observers.set(slug, set);\n\t\t}\n\t\treturn set;\n\t}\n\t/** Cheap change detection: which rows, in what order, at which revision. */\n\tsignature(slug, rows, total) {\n\t\tconst state = this.collections.get(slug);\n\t\treturn `${total}|${rows.map((row) => {\n\t\t\tconst key = String(row.id);\n\t\t\treturn `${key}:${state?.rows.get(key)?.rev ?? 0}`;\n\t\t}).join(\",\")}`;\n\t}\n\tnotifyCollection(slug, broadcast = true) {\n\t\tconst set = this.observers.get(slug);\n\t\tif (set) for (const observer of [...set]) observer.emit();\n\t\tif (broadcast) this.broadcast({\n\t\t\ttype: \"rows\",\n\t\t\tslugs: [slug]\n\t\t});\n\t}\n\t/** Connectivity came back (or the user changed): re-read everything live. */\n\trevalidateAll() {\n\t\tfor (const slug of this.observers.keys()) {\n\t\t\tthis.notifyCollection(slug, false);\n\t\t\tthis.scheduleRefresh(slug);\n\t\t}\n\t}\n\tcollectionState(slug) {\n\t\tlet state = this.collections.get(slug);\n\t\tif (!state) {\n\t\t\tstate = {\n\t\t\t\trows: /* @__PURE__ */ new Map(),\n\t\t\t\tsnapshots: /* @__PURE__ */ new Map(),\n\t\t\t\tfresh: /* @__PURE__ */ new Set(),\n\t\t\t\tfreshRows: /* @__PURE__ */ new Set(),\n\t\t\t\tabsent: /* @__PURE__ */ new Set(),\n\t\t\t\tready: false\n\t\t\t};\n\t\t\tthis.collections.set(slug, state);\n\t\t}\n\t\treturn state;\n\t}\n\tensureCollection(slug) {\n\t\tconst state = this.collectionState(slug);\n\t\tif (!state.loaded) {\n\t\t\tconst scope = this.scope;\n\t\t\tstate.loaded = (async () => {\n\t\t\t\tawait this.ensureQueueLoaded();\n\t\t\t\tconst [rows, snapshots, absent] = await Promise.all([\n\t\t\t\t\tthis.store.listCacheEntries(`${scope}|row|${slug}|`).catch(() => []),\n\t\t\t\t\tthis.store.listCacheEntries(`${scope}|q|${slug}|`).catch(() => []),\n\t\t\t\t\tthis.store.listCache(`${scope}|abs|${slug}|`).catch(() => [])\n\t\t\t\t]);\n\t\t\t\tif (this.scope !== scope || this.collections.get(slug) !== state) return;\n\t\t\t\tfor (const entry of rows) {\n\t\t\t\t\tconst row = entry.value;\n\t\t\t\t\tif (!row || row.id === void 0 || row.id === null) continue;\n\t\t\t\t\tstate.rows.set(String(row.id), {\n\t\t\t\t\t\trow: hydrateRow(row),\n\t\t\t\t\t\tcachedAt: entry.cachedAt,\n\t\t\t\t\t\trev: ++this.revCounter\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor (const entry of snapshots) {\n\t\t\t\t\tconst key = entry.key.slice(`${scope}|q|${slug}|`.length);\n\t\t\t\t\tif (entry.value) state.snapshots.set(key, entry.value);\n\t\t\t\t}\n\t\t\t\tfor (const entry of absent) state.absent.add(entry.key.slice(`${scope}|abs|${slug}|`.length));\n\t\t\t})().catch(() => void 0).finally(() => {\n\t\t\t\tstate.ready = true;\n\t\t\t});\n\t\t}\n\t\treturn state.loaded.then(() => state);\n\t}\n\tsnapshotFor(slug, params) {\n\t\treturn this.collections.get(slug)?.snapshots.get(buildQueryString(params));\n\t}\n\thasLocalAnswer(state, slug, params) {\n\t\tif (!state) return false;\n\t\treturn state.snapshots.has(buildQueryString(params)) || state.rows.size > 0;\n\t}\n\t/**\n\t* Answer a query from the local database.\n\t*\n\t* With a snapshot, the server's own page — its ids, order and total — is\n\t* the skeleton, and the local rows fill it in: rows deleted locally drop\n\t* out, rows edited locally show the edit, and rows *created* locally join\n\t* the first page if they match. Without one, the query is evaluated\n\t* outright over every cached row, which is the best that can be done for a\n\t* query the server has never answered here.\n\t*/\n\tanswer(slug, params, snapshot) {\n\t\tconst state = this.collections.get(slug);\n\t\tconst exact = isExactlyEvaluable(params);\n\t\tconst fromCache = !state?.fresh.has(buildQueryString(params));\n\t\tif (!state) return {\n\t\t\tdata: [],\n\t\t\tmeta: {\n\t\t\t\ttotal: 0,\n\t\t\t\tlimit: params?.limit ?? 20,\n\t\t\t\toffset: params?.offset ?? 0,\n\t\t\t\thasMore: false\n\t\t\t},\n\t\t\tfromCache: true,\n\t\t\thasPendingWrites: false,\n\t\t\tpartial: true\n\t\t};\n\t\tif (!snapshot) {\n\t\t\tconst local = runLocalQuery([...state.rows.values()].map((e) => e.row), params);\n\t\t\treturn {\n\t\t\t\t...local,\n\t\t\t\tfromCache,\n\t\t\t\thasPendingWrites: local.data.some((row) => this.hasPending(slug, row.id)),\n\t\t\t\tpartial: true\n\t\t\t};\n\t\t}\n\t\tconst rows = [];\n\t\tconst seen = /* @__PURE__ */ new Set();\n\t\t/** Rows the server counted that we know are no longer in the result. */\n\t\tlet removed = 0;\n\t\tfor (const id of snapshot.ids) {\n\t\t\tconst key = String(id);\n\t\t\tconst entry = state.rows.get(key);\n\t\t\tif (!entry) {\n\t\t\t\tif (state.absent.has(key) || this.hasPending(slug, key)) removed++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (exact && this.hasPending(slug, key) && !matchesParams(entry.row, params)) {\n\t\t\t\tremoved++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\trows.push(entry.row);\n\t\t\tseen.add(key);\n\t\t}\n\t\tlet added = 0;\n\t\tconst offset = snapshot.offset ?? 0;\n\t\tif (exact && offset === 0) {\n\t\t\tfor (const [key, entry] of state.rows) {\n\t\t\t\tif (seen.has(key) || !this.hasPending(slug, key)) continue;\n\t\t\t\tif (!this.isLocallyCreated(slug, key)) continue;\n\t\t\t\tif (!matchesParams(entry.row, params)) continue;\n\t\t\t\trows.push(entry.row);\n\t\t\t\tadded++;\n\t\t\t}\n\t\t\tif (added > 0 && params?.orderBy) sortRows(rows, params.orderBy);\n\t\t}\n\t\treturn {\n\t\t\tdata: rows,\n\t\t\tmeta: {\n\t\t\t\ttotal: Math.max(rows.length, snapshot.total - removed + added),\n\t\t\t\tlimit: snapshot.limit,\n\t\t\t\toffset,\n\t\t\t\thasMore: snapshot.hasMore\n\t\t\t},\n\t\t\tfromCache,\n\t\t\thasPendingWrites: rows.some((row) => this.hasPending(slug, row.id)),\n\t\t\tpartial: !exact\n\t\t};\n\t}\n\tlocalFind(slug, params) {\n\t\tconst state = this.collections.get(slug);\n\t\tconst snapshot = this.snapshotFor(slug, params);\n\t\tstate?.fresh.delete(buildQueryString(params));\n\t\tif (!snapshot && (!state || state.rows.size === 0)) throw offlineError(`Offline: no cached data for \"${slug}\".`);\n\t\tconst answer = this.answer(slug, params, snapshot);\n\t\treturn snapshot ? answer : {\n\t\t\t...answer,\n\t\t\tpartial: true\n\t\t};\n\t}\n\trawLocalRow(slug, id) {\n\t\tconst entry = this.collections.get(slug)?.rows.get(String(id));\n\t\treturn entry ? { ...entry.row } : void 0;\n\t}\n\tlocalRow(slug, id) {\n\t\treturn this.collections.get(slug)?.rows.get(String(id))?.row;\n\t}\n\tsetLocalRow(slug, id, row) {\n\t\tconst state = this.collectionState(slug);\n\t\tconst key = String(id);\n\t\tconst cachedAt = Date.now();\n\t\tstate.rows.set(key, {\n\t\t\trow: { ...row },\n\t\t\tcachedAt,\n\t\t\trev: ++this.revCounter\n\t\t});\n\t\tstate.freshRows.delete(key);\n\t\tthis.forgetTombstone(slug, key);\n\t\tthis.writeCache(this.rowKey(slug, key), dehydrateRow(row), cachedAt);\n\t\tthis.evictRows(slug);\n\t}\n\t/**\n\t* Drop a row and, when the server is the one saying it is gone, remember\n\t* that. \"I looked it up and it does not exist\" is real knowledge: without\n\t* it, opening a deleted row while offline would report a missing local\n\t* database instead of a missing row.\n\t*/\n\tremoveLocalRow(slug, id, known = false) {\n\t\tconst state = this.collectionState(slug);\n\t\tconst key = String(id);\n\t\tconst existed = state.rows.delete(key);\n\t\tif (known) {\n\t\t\tstate.absent.add(key);\n\t\t\tstate.freshRows.add(key);\n\t\t\tthis.writeCache(this.absentKey(slug, key), true);\n\t\t} else state.freshRows.delete(key);\n\t\tif (existed) this.deleteCache([this.rowKey(slug, key)]);\n\t}\n\tforgetTombstone(slug, key) {\n\t\tif (!this.collectionState(slug).absent.delete(key)) return;\n\t\tthis.deleteCache([this.absentKey(slug, key)]);\n\t}\n\t/**\n\t* Merge server rows into the local database. A row with unsynced local\n\t* writes keeps them: the server's copy is the base the queued mutations\n\t* are re-applied to, not a replacement for what the user did.\n\t*\n\t* Rows that came back unchanged keep their identity and revision, so a\n\t* refetch that changed nothing does not re-render every live query that\n\t* touches them — or rewrite them all to disk.\n\t*/\n\tasync ingest(slug, rows) {\n\t\tif (rows.length === 0) return;\n\t\tconst state = await this.ensureCollection(slug);\n\t\tconst cachedAt = Date.now();\n\t\tconst writes = [];\n\t\tconst deletes = [];\n\t\tfor (const raw of rows) {\n\t\t\tif (!raw || raw.id === void 0 || raw.id === null) continue;\n\t\t\tconst key = String(raw.id);\n\t\t\tconst merged = this.hasPending(slug, key) ? this.applyPendingToRow(slug, key, { ...raw }) : { ...raw };\n\t\t\tif (merged === void 0) {\n\t\t\t\tstate.rows.delete(key);\n\t\t\t\tdeletes.push(this.rowKey(slug, key));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.forgetTombstone(slug, key);\n\t\t\tstate.freshRows.add(key);\n\t\t\tconst existing = state.rows.get(key);\n\t\t\tif (existing && JSON.stringify(existing.row) === JSON.stringify(merged)) {\n\t\t\t\texisting.cachedAt = cachedAt;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstate.rows.set(key, {\n\t\t\t\trow: merged,\n\t\t\t\tcachedAt,\n\t\t\t\trev: ++this.revCounter\n\t\t\t});\n\t\t\twrites.push({\n\t\t\t\tkey: this.rowKey(slug, key),\n\t\t\t\tentry: {\n\t\t\t\t\tvalue: dehydrateRow(merged),\n\t\t\t\t\tcachedAt\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif (writes.length > 0) this.store.setCacheMany(writes).catch(() => void 0);\n\t\tif (deletes.length > 0) this.deleteCache(deletes);\n\t\tthis.evictRows(slug);\n\t}\n\t/**\n\t* Fold the queued mutations for one row over a base, newest last.\n\t* `afterMutationId` skips everything up to and including that mutation,\n\t* which is how a just-replayed write avoids being applied on top of the\n\t* server's response to it.\n\t*/\n\tapplyPendingToRow(slug, idKey, base, afterMutationId) {\n\t\tlet row = base;\n\t\tlet skipping = afterMutationId !== void 0;\n\t\tfor (const op of this.queue) {\n\t\t\tif (skipping) {\n\t\t\t\tif (op.mutationId === afterMutationId) skipping = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (op.collection !== slug) continue;\n\t\t\tif (op.type === \"createMany\") {\n\t\t\t\tconst match = op.data?.find((r) => String(r.id) === idKey);\n\t\t\t\tif (match) row = { ...match };\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (op.id === void 0 || String(op.id) !== idKey) continue;\n\t\t\tif (op.type === \"create\") row = { ...op.data };\n\t\t\telse if (op.type === \"update\") row = {\n\t\t\t\t...row ?? {},\n\t\t\t\t...op.data,\n\t\t\t\tid: op.id\n\t\t\t};\n\t\t\telse if (op.type === \"delete\") row = void 0;\n\t\t}\n\t\treturn row;\n\t}\n\trecordSnapshot(slug, params, result) {\n\t\tconst meta = result.meta ?? {\n\t\t\ttotal: result.data?.length ?? 0,\n\t\t\tlimit: 20,\n\t\t\toffset: 0,\n\t\t\thasMore: false\n\t\t};\n\t\tconst snapshot = {\n\t\t\tids: (result.data ?? []).map((row) => row.id).filter((id) => id !== void 0),\n\t\t\ttotal: meta.total ?? result.data?.length ?? 0,\n\t\t\tlimit: meta.limit ?? params?.limit ?? 20,\n\t\t\toffset: meta.offset ?? params?.offset ?? 0,\n\t\t\thasMore: meta.hasMore ?? false\n\t\t};\n\t\tconst state = this.collectionState(slug);\n\t\tconst key = buildQueryString(params);\n\t\tstate.snapshots.set(key, snapshot);\n\t\tstate.fresh.add(key);\n\t\tthis.writeCache(`${this.scope}|q|${slug}|${key}`, snapshot);\n\t\tthis.evictSnapshots(slug);\n\t\treturn snapshot;\n\t}\n\t/**\n\t* A write changed which rows belong in a list, and only the server can say\n\t* how — a row it generated is in no cached page, and the totals moved.\n\t* Re-run every live query on the collection; queries nobody is watching\n\t* are corrected by their next `find`.\n\t*\n\t* Coalesced per microtask so a burst of writes costs one round trip, and\n\t* skipped entirely while offline, where the local database is already the\n\t* best answer available.\n\t*/\n\tscheduleRefresh(slug) {\n\t\tif (this.refreshPending.has(slug)) return;\n\t\tconst observers = this.observers.get(slug);\n\t\tif (!observers || observers.size === 0) return;\n\t\tthis.refreshPending.add(slug);\n\t\tPromise.resolve().then(() => {\n\t\t\tthis.refreshPending.delete(slug);\n\t\t\tif (this.disposed || !this.connectivity.shouldAttempt()) return;\n\t\t\tfor (const observer of [...this.observers.get(slug) ?? []]) observer.refresh();\n\t\t});\n\t}\n\tevictRows(slug) {\n\t\tconst state = this.collections.get(slug);\n\t\tif (!state || state.rows.size <= this.maxCachedRows) return;\n\t\tconst evictable = [...state.rows.entries()].filter(([key]) => !this.hasPending(slug, key)).sort((a, b) => a[1].cachedAt - b[1].cachedAt);\n\t\tconst excess = state.rows.size - this.maxCachedRows;\n\t\tconst doomed = evictable.slice(0, excess);\n\t\tfor (const [key] of doomed) state.rows.delete(key);\n\t\tif (doomed.length > 0) this.deleteCache(doomed.map(([key]) => this.rowKey(slug, key)));\n\t\tif (state.absent.size > this.maxCachedRows) {\n\t\t\tconst stale = [...state.absent].slice(0, state.absent.size - this.maxCachedRows);\n\t\t\tfor (const key of stale) state.absent.delete(key);\n\t\t\tthis.deleteCache(stale.map((key) => this.absentKey(slug, key)));\n\t\t}\n\t}\n\tevictSnapshots(slug) {\n\t\tconst state = this.collections.get(slug);\n\t\tif (!state || state.snapshots.size <= this.maxCachedQueries) return;\n\t\tconst excess = state.snapshots.size - this.maxCachedQueries;\n\t\tconst doomed = [...state.snapshots.keys()].slice(0, excess);\n\t\tfor (const key of doomed) state.snapshots.delete(key);\n\t\tthis.deleteCache(doomed.map((key) => `${this.scope}|q|${slug}|${key}`));\n\t}\n\tensureQueueLoaded() {\n\t\tif (!this.queueLoad) {\n\t\t\tconst scope = this.scope;\n\t\t\tthis.queueLoad = this.store.listQueue(`${scope}|`).then((queue) => {\n\t\t\t\tif (this.scope !== scope) return;\n\t\t\t\tthis.queue = queue;\n\t\t\t\tthis.patchStatus({ pending: queue.length });\n\t\t\t\tthis.notifyQueue();\n\t\t\t}).catch(() => void 0);\n\t\t}\n\t\treturn this.queueLoad;\n\t}\n\tenqueue(mutation) {\n\t\tconst result = this.enqueueChain.then(async () => {\n\t\t\tawait this.ensureQueueLoaded();\n\t\t\tif (mutation.type === \"update\") {\n\t\t\t\tconst tail = this.queue[this.queue.length - 1];\n\t\t\t\tif (tail && tail.mutationId !== this.inFlightId && tail.collection === mutation.collection && (tail.type === \"create\" || tail.type === \"update\") && tail.id === mutation.id) {\n\t\t\t\t\ttail.data = {\n\t\t\t\t\t\t...tail.data,\n\t\t\t\t\t\t...mutation.data,\n\t\t\t\t\t\tid: tail.id\n\t\t\t\t\t};\n\t\t\t\t\tawait this.store.enqueue(this.queueKey(tail), tail);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (mutation.type === \"delete\") {\n\t\t\t\tif (this.queue.some((m) => m.collection === mutation.collection && m.type === \"create\" && m.id === mutation.id && m.generatedId === true && m.mutationId !== this.inFlightId)) {\n\t\t\t\t\tconst doomed = this.queue.filter((m) => m.collection === mutation.collection && m.id === mutation.id && (m.type === \"create\" || m.type === \"update\") && m.mutationId !== this.inFlightId);\n\t\t\t\t\tfor (const op of doomed) await this.store.dequeue(this.queueKey(op));\n\t\t\t\t\tthis.queue = this.queue.filter((m) => !doomed.includes(m));\n\t\t\t\t\tthis.afterQueueChange();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst full = {\n\t\t\t\t...mutation,\n\t\t\t\tmutationId: createMutationId(),\n\t\t\t\tqueuedAt: Date.now()\n\t\t\t};\n\t\t\tawait this.store.enqueue(this.queueKey(full), full);\n\t\t\tthis.queue.push(full);\n\t\t\tthis.afterQueueChange();\n\t\t});\n\t\tthis.enqueueChain = result.catch(() => void 0);\n\t\treturn result;\n\t}\n\thasPending(slug, id) {\n\t\tconst key = String(id);\n\t\treturn this.queue.some((op) => {\n\t\t\tif (op.collection !== slug) return false;\n\t\t\tif (op.type === \"createMany\") return op.data?.some((r) => String(r.id) === key) ?? false;\n\t\t\treturn op.id !== void 0 && String(op.id) === key;\n\t\t});\n\t}\n\t/** Is this row one the server has never been told about? */\n\tisLocallyCreated(slug, idKey) {\n\t\treturn this.queue.some((op) => {\n\t\t\tif (op.collection !== slug) return false;\n\t\t\tif (op.type === \"create\") return op.id !== void 0 && String(op.id) === idKey;\n\t\t\tif (op.type === \"createMany\") return op.data?.some((r) => String(r.id) === idKey) ?? false;\n\t\t\treturn false;\n\t\t});\n\t}\n\t/** How many rows the queue adds to (or removes from) a server-side count. */\n\tpendingDelta(slug, params) {\n\t\tif (!isExactlyEvaluable(params)) return 0;\n\t\tlet delta = 0;\n\t\tfor (const op of this.queue) {\n\t\t\tif (op.collection !== slug) continue;\n\t\t\tif (op.type === \"create\") {\n\t\t\t\tif (matchesParams(op.data, params)) delta++;\n\t\t\t} else if (op.type === \"createMany\") {\n\t\t\t\tfor (const row of op.data ?? []) if (matchesParams(row, params)) delta++;\n\t\t\t} else if (op.type === \"delete\") {\n\t\t\t\tconst before = op.rollback?.rows?.[String(op.id)];\n\t\t\t\tif (before && matchesParams(before, params)) delta--;\n\t\t\t}\n\t\t}\n\t\treturn delta;\n\t}\n\tsync() {\n\t\tif (this.flushPromise) return this.flushPromise;\n\t\tthis.flushPromise = this.withLock(() => this.flush()).finally(() => {\n\t\t\tthis.flushPromise = void 0;\n\t\t});\n\t\treturn this.flushPromise;\n\t}\n\tasync flush() {\n\t\tawait this.ensureQueueLoaded();\n\t\tawait this.reloadQueue();\n\t\tif (this.queue.length === 0) return {\n\t\t\tflushed: 0,\n\t\t\tremaining: 0\n\t\t};\n\t\tthis.patchStatus({ syncing: true });\n\t\tconst touched = /* @__PURE__ */ new Set();\n\t\tconst queuedAtStart = this.queue.length;\n\t\tlet flushed = 0;\n\t\ttry {\n\t\t\twhile (this.queue.length > 0 && !this.disposed) {\n\t\t\t\tconst op = this.queue[0];\n\t\t\t\ttouched.add(op.collection);\n\t\t\t\tthis.inFlightId = op.mutationId;\n\t\t\t\ttry {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.replay(op);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (isNetworkError(error)) {\n\t\t\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\top.attempts = (op.attempts ?? 0) + 1;\n\t\t\t\t\t\top.lastError = error?.message ?? String(error);\n\t\t\t\t\t\tif (isRetryableError(error) && op.attempts < this.maxRetries) {\n\t\t\t\t\t\t\tawait this.store.enqueue(this.queueKey(op), op).catch(() => void 0);\n\t\t\t\t\t\t\tthis.connectivity.deferRetry();\n\t\t\t\t\t\t\tthis.patchStatus({ lastError: op.lastError });\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.rejectMutation(op, error);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.drop(op);\n\t\t\t\t\tflushed++;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.inFlightId = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.patchStatus({ syncing: false });\n\t\t}\n\t\tif (this.queue.length !== queuedAtStart) {\n\t\t\tfor (const slug of touched) {\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t}\n\t\t\tthis.broadcast({ type: \"queue\" });\n\t\t}\n\t\tif (this.queue.length === 0) this.patchStatus({ lastSyncedAt: Date.now() });\n\t\treturn {\n\t\t\tflushed,\n\t\t\tremaining: this.queue.length\n\t\t};\n\t}\n\tasync replay(op) {\n\t\tconst inner = this.innerFor(op.collection);\n\t\tif (op.type === \"create\") {\n\t\t\tlet row;\n\t\t\ttry {\n\t\t\t\trow = await inner.create(op.data, void 0, { idempotencyKey: op.mutationId });\n\t\t\t} catch (error) {\n\t\t\t\tif (!(op.generatedId === true && isDuplicateKeyError(error))) throw error;\n\t\t\t\trow = await inner.findById(op.id).catch(() => void 0);\n\t\t\t\tif (!row) return;\n\t\t\t}\n\t\t\tawait this.adoptServerRow(op, op.id, row);\n\t\t} else if (op.type === \"createMany\") {\n\t\t\tconst queued = op.data ?? [];\n\t\t\tconst rows = await inner.createMany(queued, op.upsert ? { upsert: true } : void 0);\n\t\t\tfor (let i = 0; i < rows.length; i++) await this.adoptServerRow(op, queued[i]?.id, rows[i]);\n\t\t} else if (op.type === \"update\") {\n\t\t\tconst row = await inner.update(op.id, op.data);\n\t\t\tawait this.ingestReplaced(op, op.id, row);\n\t\t} else if (op.type === \"delete\") {\n\t\t\tawait inner.delete(op.id);\n\t\t\tthis.removeLocalRow(op.collection, op.id, true);\n\t\t}\n\t}\n\t/**\n\t* Take the server's version of a row the client created offline.\n\t*\n\t* The server may have assigned a different id — a serial column ignores\n\t* the id we invented — in which case every local trace of the temporary id\n\t* has to move with it, including queued writes that were made against it\n\t* before it was ever sent.\n\t*/\n\tasync adoptServerRow(op, localId, row) {\n\t\tif (!row) return;\n\t\tconst slug = op.collection;\n\t\tconst serverId = row.id;\n\t\tif (localId !== void 0 && serverId !== void 0 && String(serverId) !== String(localId)) {\n\t\t\tconst oldKey = String(localId);\n\t\t\tthis.removeLocalRow(slug, localId);\n\t\t\tfor (const queued of this.queue) {\n\t\t\t\tif (queued.collection !== slug) continue;\n\t\t\t\tlet dirty = false;\n\t\t\t\tif (queued.id !== void 0 && String(queued.id) === oldKey) {\n\t\t\t\t\tqueued.id = serverId;\n\t\t\t\t\tif (queued.data && !Array.isArray(queued.data)) queued.data.id = serverId;\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t\tconst rollbackRows = queued.rollback?.rows;\n\t\t\t\tif (rollbackRows && oldKey in rollbackRows) {\n\t\t\t\t\trollbackRows[String(serverId)] = rollbackRows[oldKey];\n\t\t\t\t\tdelete rollbackRows[oldKey];\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t\tif (dirty) await this.store.enqueue(this.queueKey(queued), queued).catch(() => void 0);\n\t\t\t}\n\t\t}\n\t\tawait this.ingestReplaced(op, serverId ?? localId, row);\n\t}\n\t/**\n\t* Write a server row over the local one, ignoring the mutation that just\n\t* produced it — re-applying that would put the pre-server values back on\n\t* top of the server's answer — but keeping every write queued *after* it.\n\t* Those are still unsent, and dropping them here would make the row snap\n\t* back to the server's version in front of the user, only to change again\n\t* when they replay a moment later.\n\t*/\n\tasync ingestReplaced(op, id, row) {\n\t\tconst slug = op.collection;\n\t\tconst state = await this.ensureCollection(slug);\n\t\tconst key = String(id);\n\t\tconst merged = this.applyPendingToRow(slug, key, { ...row }, op.mutationId);\n\t\tif (merged === void 0) {\n\t\t\tthis.removeLocalRow(slug, key);\n\t\t\treturn;\n\t\t}\n\t\tconst cachedAt = Date.now();\n\t\tstate.rows.set(key, {\n\t\t\trow: merged,\n\t\t\tcachedAt,\n\t\t\trev: ++this.revCounter\n\t\t});\n\t\tif (this.applyPendingToRow(slug, key, void 0, op.mutationId) === void 0) state.freshRows.add(key);\n\t\tthis.writeCache(this.rowKey(slug, key), dehydrateRow(merged), cachedAt);\n\t}\n\t/**\n\t* The server refused a mutation. Put back what it changed, and discard the\n\t* queued writes that were built on top of it: an edit to a row whose\n\t* creation was rejected can only fail the same way, and applying it would\n\t* leave the local database claiming a row the server does not have.\n\t*\n\t* The cascade stops the moment a later write stops *depending* on the\n\t* rejected one. An `update` reads the row it edits, so it is doomed with\n\t* it; a `create` overwrites the row outright and a `delete` needs nothing\n\t* of it, so both stand on their own and are kept — dropping them would\n\t* silently lose writes the server would have accepted.\n\t*/\n\tasync rejectMutation(op, error) {\n\t\tconst ids = new Set(Object.keys(op.rollback?.rows ?? {}));\n\t\tif (op.id !== void 0) ids.add(String(op.id));\n\t\tconst doomed = [op];\n\t\tconst orphaned = new Set(ids);\n\t\tconst position = this.queue.indexOf(op);\n\t\tfor (const later of this.queue.slice(position + 1)) {\n\t\t\tif (later.collection !== op.collection) continue;\n\t\t\tconst hit = this.idsOf(later).filter((id) => orphaned.has(id));\n\t\t\tif (hit.length === 0) continue;\n\t\t\tif (later.type === \"update\") doomed.push(later);\n\t\t\telse for (const id of hit) orphaned.delete(id);\n\t\t}\n\t\tfor (const dropped of doomed) await this.drop(dropped);\n\t\tfor (const [idKey, previous] of Object.entries(op.rollback?.rows ?? {})) {\n\t\t\tconst restored = this.applyPendingToRow(op.collection, idKey, previous ?? void 0);\n\t\t\tif (restored === void 0) this.removeLocalRow(op.collection, idKey);\n\t\t\telse this.setLocalRow(op.collection, idKey, restored);\n\t\t}\n\t\tthis.patchStatus({ lastError: error.message });\n\t\tthis.notifyCollection(op.collection);\n\t\tthis.scheduleRefresh(op.collection);\n\t\tfor (const dropped of doomed) this.onSyncError?.(error, dropped);\n\t}\n\t/** Every row id a mutation writes to. */\n\tidsOf(op) {\n\t\tif (op.type === \"createMany\") return (op.data ?? []).map((r) => String(r.id));\n\t\treturn op.id === void 0 ? [] : [String(op.id)];\n\t}\n\tasync drop(op) {\n\t\tawait this.store.dequeue(this.queueKey(op)).catch(() => void 0);\n\t\tthis.queue = this.queue.filter((m) => m.mutationId !== op.mutationId);\n\t\tthis.afterQueueChange(false);\n\t}\n\t/** Replay uses unwrapped clients: a failure must never re-enqueue itself. */\n\tinnerFor(slug) {\n\t\tlet inner = this.inners.get(slug);\n\t\tif (!inner) {\n\t\t\tinner = this.createInner(slug);\n\t\t\tthis.inners.set(slug, inner);\n\t\t}\n\t\treturn inner;\n\t}\n\tasync withLock(fn) {\n\t\tconst locks = globalThis.navigator?.locks;\n\t\tif (!locks?.request) return fn();\n\t\ttry {\n\t\t\treturn await locks.request(`rebase-offline-sync:${this.scope}`, fn);\n\t\t} catch {\n\t\t\treturn fn();\n\t\t}\n\t}\n\tbroadcast(message) {\n\t\tif (!this.channel) return;\n\t\ttry {\n\t\t\tthis.channel.postMessage({\n\t\t\t\t...message,\n\t\t\t\tscope: this.scope,\n\t\t\t\tsender: this.tabId\n\t\t\t});\n\t\t} catch {}\n\t}\n\tonBroadcast(message) {\n\t\tif (this.disposed || !message || typeof message !== \"object\") return;\n\t\tconst msg = message;\n\t\tif (msg.sender === this.tabId || msg.scope !== this.scope) return;\n\t\tif (msg.type === \"rows\") for (const slug of msg.slugs ?? []) this.reloadCollection(slug);\n\t\telse if (msg.type === \"queue\") this.reloadQueue();\n\t}\n\t/** Re-read one collection from the store, replacing what is in memory. */\n\tasync reloadCollection(slug) {\n\t\tconst state = this.collections.get(slug);\n\t\tif (!state?.loaded) return;\n\t\tawait this.reloadQueue();\n\t\tconst scope = this.scope;\n\t\tconst [rows, snapshots, absent] = await Promise.all([\n\t\t\tthis.store.listCacheEntries(`${scope}|row|${slug}|`).catch(() => []),\n\t\t\tthis.store.listCacheEntries(`${scope}|q|${slug}|`).catch(() => []),\n\t\t\tthis.store.listCache(`${scope}|abs|${slug}|`).catch(() => [])\n\t\t]);\n\t\tif (this.scope !== scope || this.collections.get(slug) !== state) return;\n\t\tconst next = /* @__PURE__ */ new Map();\n\t\tfor (const entry of rows) {\n\t\t\tconst row = entry.value;\n\t\t\tif (!row || row.id === void 0 || row.id === null) continue;\n\t\t\tconst key = String(row.id);\n\t\t\tconst existing = state.rows.get(key);\n\t\t\tconst hydrated = hydrateRow(row);\n\t\t\tconst unchanged = existing && JSON.stringify(existing.row) === JSON.stringify(hydrated);\n\t\t\tnext.set(key, {\n\t\t\t\trow: hydrated,\n\t\t\t\tcachedAt: entry.cachedAt,\n\t\t\t\trev: unchanged ? existing.rev : ++this.revCounter\n\t\t\t});\n\t\t}\n\t\tstate.rows = next;\n\t\tstate.snapshots = /* @__PURE__ */ new Map();\n\t\tfor (const entry of snapshots) {\n\t\t\tconst key = entry.key.slice(`${scope}|q|${slug}|`.length);\n\t\t\tif (entry.value) state.snapshots.set(key, entry.value);\n\t\t}\n\t\tstate.absent = new Set(absent.map((entry) => entry.key.slice(`${scope}|abs|${slug}|`.length)));\n\t\tthis.notifyCollection(slug, false);\n\t}\n\tasync reloadQueue() {\n\t\tconst scope = this.scope;\n\t\tconst queue = await this.store.listQueue(`${scope}|`).catch(() => void 0);\n\t\tif (!queue || this.scope !== scope) return;\n\t\tthis.queue = queue;\n\t\tthis.afterQueueChange(false);\n\t}\n\tafterQueueChange(broadcast = true) {\n\t\tthis.patchStatus({ pending: this.queue.length });\n\t\tthis.notifyQueue();\n\t\tif (broadcast) this.broadcast({ type: \"queue\" });\n\t}\n\tnotifyQueue() {\n\t\tfor (const listener of this.queueListeners) listener(this.queue.length);\n\t}\n\tpatchStatus(patch) {\n\t\tlet changed = false;\n\t\tfor (const [key, value] of Object.entries(patch)) if (this.currentStatus[key] !== value) {\n\t\t\tthis.currentStatus[key] = value;\n\t\t\tchanged = true;\n\t\t}\n\t\tif (!changed) return;\n\t\tconst snapshot = { ...this.currentStatus };\n\t\tfor (const listener of this.statusListeners) listener(snapshot);\n\t}\n\tcountKey(slug, params) {\n\t\treturn `${this.scope}|count|${slug}|${buildQueryString(params)}`;\n\t}\n\trowKey(slug, id) {\n\t\treturn `${this.scope}|row|${slug}|${String(id)}`;\n\t}\n\tabsentKey(slug, id) {\n\t\treturn `${this.scope}|abs|${slug}|${String(id)}`;\n\t}\n\tqueueKey(mutation) {\n\t\treturn `${this.scope}|${mutation.mutationId}`;\n\t}\n\tasync readCache(key) {\n\t\ttry {\n\t\t\treturn (await this.store.getCache(key))?.value;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n\tasync writeCache(key, value, cachedAt = Date.now()) {\n\t\ttry {\n\t\t\tawait this.store.setCache(key, {\n\t\t\t\tvalue,\n\t\t\t\tcachedAt\n\t\t\t});\n\t\t} catch {}\n\t}\n\tasync deleteCache(keys) {\n\t\ttry {\n\t\t\tawait this.store.deleteCache(keys);\n\t\t} catch {}\n\t}\n};\n//#endregion\n//#region src/index.ts\n/**\n* Derive a WebSocket URL from an HTTP base URL.\n* `http://` → `ws://`, `https://` → `wss://`.\n*/\nfunction deriveWebSocketUrl(baseUrl) {\n\tif (typeof window !== \"undefined\") {\n\t\tlet absoluteUrl = \"\";\n\t\tif (!baseUrl) absoluteUrl = window.location.origin;\n\t\telse if (/^https?:\\/\\//i.test(baseUrl) || /^wss?:\\/\\//i.test(baseUrl)) absoluteUrl = baseUrl;\n\t\telse try {\n\t\t\tabsoluteUrl = new URL(baseUrl, window.location.href).origin;\n\t\t} catch {\n\t\t\tabsoluteUrl = window.location.origin;\n\t\t}\n\t\tconst protocol = absoluteUrl.startsWith(\"https:\") || absoluteUrl.startsWith(\"wss:\") ? \"wss:\" : \"ws:\";\n\t\treturn absoluteUrl.replace(/^https?:\\/\\//i, `${protocol}//`).replace(/^wss?:\\/\\//i, `${protocol}//`).replace(/\\/$/, \"\");\n\t}\n\tif (!baseUrl) return \"\";\n\tif (!/^https?:\\/\\//i.test(baseUrl) && !/^wss?:\\/\\//i.test(baseUrl)) return \"\";\n\treturn baseUrl.replace(/^https?:\\/\\//i, (match) => match.toLowerCase() === \"https://\" ? \"wss://\" : \"ws://\").replace(/\\/$/, \"\");\n}\nfunction createRebaseClient(options) {\n\tconst transport = createTransport(options, { credentialOutOfBand: options.auth?.authFlowMode === \"cookie\" });\n\tconst auth = createAuth(transport, options.auth);\n\tconst admin = createAdmin(transport, options.admin);\n\tconst cron = createCron(transport, options.cron);\n\tconst backups = createBackups(transport);\n\tconst apiKeys = createApiKeys(transport, options.apiKeys);\n\tconst storage = createStorage(transport);\n\tconst functions = createFunctionsClient(transport);\n\tconst createStorageSource = (storageId) => storageId === DEFAULT_STORAGE_SOURCE_KEY ? storage : createStorage(transport, storageId);\n\tconst storageRegistry = new ClientStorageSourceRegistry();\n\tstorageRegistry.register(DEFAULT_STORAGE_SOURCE_KEY, storage);\n\tfor (const def of options.storageSources ?? []) if (def.transport === \"server\" && def.key !== DEFAULT_STORAGE_SOURCE_KEY) storageRegistry.register(def.key, createStorageSource(def.key));\n\tlet storageSourcesPromise;\n\tconst fetchStorageSources = () => {\n\t\tif (storageSourcesPromise) return storageSourcesPromise;\n\t\tstorageSourcesPromise = transport.request(\"/storage/sources\").then((res) => {\n\t\t\tconst defs = res.data ?? [];\n\t\t\tfor (const def of defs) if (def.transport === \"server\" && def.key !== DEFAULT_STORAGE_SOURCE_KEY && !storageRegistry.has(def.key)) storageRegistry.register(def.key, createStorageSource(def.key));\n\t\t\treturn defs;\n\t\t}).catch((e) => {\n\t\t\tstorageSourcesPromise = void 0;\n\t\t\tthrow e;\n\t\t});\n\t\treturn storageSourcesPromise;\n\t};\n\tconst resolvedWsUrl = options.realtime !== false ? options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl) : void 0;\n\tlet ws;\n\t/** One channel object per name — see `realtime.channel`. */\n\tconst realtimeChannels = /* @__PURE__ */ new Map();\n\tif (resolvedWsUrl) {\n\t\tws = new RebaseWebSocketClient({\n\t\t\twebsocketUrl: resolvedWsUrl,\n\t\t\tgetAuthToken: async () => {\n\t\t\t\tlet session = auth.getSession();\n\t\t\t\tif (session && session.expiresAt <= Date.now() + 1e4) try {\n\t\t\t\t\tsession = await auth.refreshSession();\n\t\t\t\t} catch (e) {}\n\t\t\t\treturn session?.accessToken || options.token || \"\";\n\t\t\t},\n\t\t\tonUnauthorized: options.onUnauthorized || (() => auth.handleUnauthorized())\n\t\t});\n\t\tauth.onAuthStateChange((event, session) => {\n\t\t\tif (!ws) return;\n\t\t\tif (event === \"SIGNED_OUT\") ws.disconnect();\n\t\t\telse if (event === \"SIGNED_IN\" || event === \"TOKEN_REFRESHED\") {\n\t\t\t\tif (session?.accessToken && ws.hasSocket) ws.authenticate(session.accessToken).catch(console.warn);\n\t\t\t}\n\t\t});\n\t}\n\tif (!options.onUnauthorized) transport.setOnUnauthorized(() => auth.handleUnauthorized());\n\t/**\n\t* Suggest the closest known collection key for a mistyped accessor.\n\t* Uses edit-distance-1 and prefix matching — no external dependency.\n\t*/\n\tfunction suggestCollection(prop, knownKeys) {\n\t\tconst prefixMatch = knownKeys.find((k) => k.startsWith(prop) || prop.startsWith(k));\n\t\tif (prefixMatch) return prefixMatch;\n\t\tfor (const key of knownKeys) {\n\t\t\tif (Math.abs(key.length - prop.length) > 1) continue;\n\t\t\tlet diffs = 0;\n\t\t\tconst longer = key.length >= prop.length ? key : prop;\n\t\t\tconst shorter = key.length >= prop.length ? prop : key;\n\t\t\tif (longer.length === shorter.length) for (let i = 0; i < longer.length; i++) {\n\t\t\t\tif (longer[i] !== shorter[i]) {\n\t\t\t\t\tif (i + 1 < longer.length && longer[i] === shorter[i + 1] && longer[i + 1] === shorter[i]) {\n\t\t\t\t\t\tdiffs++;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tif (diffs > 1) break;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tdiffs++;\n\t\t\t\t}\n\t\t\t\tif (diffs > 1) break;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlet li = 0;\n\t\t\t\tlet si = 0;\n\t\t\t\twhile (li < longer.length) {\n\t\t\t\t\tif (si < shorter.length && longer[li] === shorter[si]) si++;\n\t\t\t\t\telse diffs++;\n\t\t\t\t\tli++;\n\t\t\t\t\tif (diffs > 1) break;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (diffs <= 1) return key;\n\t\t}\n\t}\n\tconst offlineManager = options.offline ? new OfflineManager(typeof options.offline === \"object\" ? options.offline : {}, (slug) => createCollectionClient(transport, slug)) : void 0;\n\tif (offlineManager) {\n\t\tofflineManager.setScope(auth.getSession()?.user?.uid);\n\t\tauth.onAuthStateChange((event, session) => {\n\t\t\tofflineManager.setScope(event === \"SIGNED_OUT\" ? void 0 : session?.user?.uid);\n\t\t});\n\t}\n\tconst collectionClients = /* @__PURE__ */ new Map();\n\tlet untypedWarned = false;\n\tfunction collection(slug) {\n\t\tif (!collectionClients.has(slug)) {\n\t\t\tconst inner = createCollectionClient(transport, slug, ws);\n\t\t\tcollectionClients.set(slug, offlineManager ? offlineManager.wrap(slug, inner) : inner);\n\t\t}\n\t\treturn collectionClients.get(slug);\n\t}\n\tconst dataProxy = new Proxy({ collection }, { get(_target, prop) {\n\t\tif (prop === \"collection\") return collection;\n\t\tif (typeof prop === \"symbol\") return void 0;\n\t\tif (typeof prop === \"string\" && prop !== \"then\" && prop !== \"toJSON\" && prop !== \"$$typeof\") {\n\t\t\tif (options.collections) {\n\t\t\t\tif (prop in options.collections) return collection(options.collections[prop]);\n\t\t\t\tconst knownKeys = Object.keys(options.collections);\n\t\t\t\tconst suggestion = suggestCollection(prop, knownKeys);\n\t\t\t\tlet msg = `Unknown collection accessor \"${prop}\". Known collections: ${knownKeys.join(\", \")}.`;\n\t\t\t\tif (suggestion) msg += ` Did you mean \"${suggestion}\"?`;\n\t\t\t\tmsg += ` Use data.collection(\"<slug>\") for dynamic slugs.`;\n\t\t\t\tthrow new RebaseClientError(msg);\n\t\t\t}\n\t\t\tif (!untypedWarned) {\n\t\t\t\tuntypedWarned = true;\n\t\t\t\tconsole.warn(`[Rebase] Untyped data access detected (client.data.${prop}). Collection names are resolved via snake_case conversion, which may cause silent 404s at request time. Pass a \\`collections\\` dictionary to createRebaseClient() or use the generated SDK for type-safe access.`);\n\t\t\t}\n\t\t\treturn collection(toSnakeCase(prop));\n\t\t}\n\t} });\n\treturn {\n\t\tauth,\n\t\tadmin,\n\t\tcron,\n\t\tbackups,\n\t\tapiKeys,\n\t\tfunctions,\n\t\tstorage,\n\t\tstorageRegistry,\n\t\tcreateStorageSource,\n\t\tfetchStorageSources,\n\t\tws,\n\t\trealtime: { \n\t\t/**\n\t\t* Join a broadcast/presence channel.\n\t\t*\n\t\t* Repeated calls with the same name return the same channel, so\n\t\t* separate components can attach handlers without each opening its\n\t\t* own membership — and `leave()` from one would otherwise silently\n\t\t* cut off the others.\n\t\t*/\nchannel: (name, options) => {\n\t\t\tif (!ws) throw new RebaseClientError(\"Realtime is disabled on this client (realtime: false), so channels are unavailable.\");\n\t\t\tlet existing = realtimeChannels.get(name);\n\t\t\tif (!existing) {\n\t\t\t\texisting = new RebaseRealtimeChannel(name, ws, options);\n\t\t\t\trealtimeChannels.set(name, existing);\n\t\t\t} else if (options?.history) existing.enableHistory();\n\t\t\treturn existing;\n\t\t} },\n\t\t/**\n\t\t* Release every handle that can keep a process alive — see the\n\t\t* `close` docblock on the client interface.\n\t\t*\n\t\t* Safe to call when realtime was never started, safe when signed out,\n\t\t* and safe to call twice.\n\t\t*/\n\t\tclose: () => {\n\t\t\tfor (const channel of realtimeChannels.values()) channel.leave();\n\t\t\trealtimeChannels.clear();\n\t\t\tws?.disconnect(true);\n\t\t\tofflineManager?.dispose();\n\t\t\tauth.stopAutoRefresh();\n\t\t},\n\t\tsetToken: transport.setToken,\n\t\tsetAuthTokenGetter: transport.setAuthTokenGetter,\n\t\tsetOnUnauthorized: transport.setOnUnauthorized,\n\t\tresolveToken: transport.resolveToken,\n\t\tbaseUrl: transport.baseUrl,\n\t\tapiPath: transport.apiPath,\n\t\tcollection,\n\t\tcall: async (endpoint, payload) => {\n\t\t\tconst prefix = endpoint.startsWith(\"/\") ? \"\" : \"/\";\n\t\t\tconst res = await transport.request(`${prefix}${endpoint}`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: payload ? JSON.stringify(payload) : void 0\n\t\t\t});\n\t\t\treturn res.data ?? res;\n\t\t},\n\t\tdata: dataProxy,\n\t\t...offlineManager ? { offline: offlineManager.api } : {}\n\t};\n}\n//#endregion\nexport { MemoryOfflineStore, QueryBuilder, RebaseApiError, RebaseClientError, RebasePaginationError, RebaseRealtimeChannel, RebaseWebSocketClient, and, cond, createBackups, createCookieStorage, createMemoryStorage, createRebaseClient, isOfflineError, or };\n\n//# sourceMappingURL=index.es.js.map","import { Hono } from \"hono\";\nimport { HonoEnv } from \"../api/types\";\nimport { BackendCollectionRegistry } from \"../collections/BackendCollectionRegistry\";\nimport { ApiError, errorHandler } from \"../api/errors\";\nimport { DataDriver } from \"@rebasepro/types\";\n/**\n * Create Hono routes for entity history.\n * Mounted at `{basePath}/data/:slug/:id/history`.\n */\nexport interface HistoryService {\n fetchHistory(tableName: string, id: string, options: { limit: number, offset: number }): Promise<{ data: Record<string, unknown>[], total: number }>;\n fetchHistoryEntry(historyId: string): Promise<Record<string, unknown> | null>;\n}\n\nexport function createHistoryRoutes(params: {\n historyService: HistoryService;\n registry: BackendCollectionRegistry;\n driver: DataDriver;\n}): Hono<HonoEnv> {\n const { historyService, registry, driver } = params;\n const router = new Hono<HonoEnv>();\n router.onError(errorHandler);\n\n /**\n * GET /:slug/:id/history - List history entries for a entity\n *\n * Query params:\n * limit (default 20)\n * offset (default 0)\n */\n router.get(\"/:slug/:id/history\", async (c) => {\n const slug = c.req.param(\"slug\");\n const id = c.req.param(\"id\");\n const parsedLimit = parseInt(c.req.query(\"limit\") ?? \"20\", 10);\n const parsedOffset = parseInt(c.req.query(\"offset\") ?? \"0\", 10);\n const limit = Number.isNaN(parsedLimit) ? 20 : parsedLimit;\n const offset = Number.isNaN(parsedOffset) ? 0 : parsedOffset;\n\n // Resolve the collection to get the actual table name\n const collection = registry.getCollections().find(\n col => col.slug === slug || false\n );\n\n if (!collection) {\n throw ApiError.notFound(`Collection '${slug}' not found`);\n }\n\n if (!collection.history) {\n throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);\n }\n\n const tableName = collection.slug;\n\n const result = await historyService.fetchHistory(tableName, id, {\n limit: Math.min(limit, 100),\n offset: Math.max(offset, 0)\n });\n\n return c.json({\n data: result.data,\n meta: {\n total: result.total,\n limit,\n offset,\n hasMore: offset + result.data.length < result.total\n }\n });\n });\n\n /**\n * POST /:slug/:id/history/:historyId/revert - Revert entity to a historical version\n *\n * This goes through the normal save path, so it creates its own history entry.\n */\n router.post(\"/:slug/:id/history/:historyId/revert\", async (c) => {\n const slug = c.req.param(\"slug\");\n const id = c.req.param(\"id\");\n const historyId = c.req.param(\"historyId\");\n\n const collection = registry.getCollections().find(\n col => col.slug === slug || false\n );\n\n if (!collection) {\n throw ApiError.notFound(`Collection '${slug}' not found`);\n }\n\n if (!collection.history) {\n throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);\n }\n\n // Fetch the history entry\n const historyEntry = await historyService.fetchHistoryEntry(historyId);\n\n if (!historyEntry) {\n throw ApiError.notFound(`History entry '${historyId}' not found`);\n }\n\n // Verify the history entry belongs to this entity (prevent cross-entity revert)\n const tableName = collection.slug;\n if (historyEntry.entity_id !== String(id) || historyEntry.table_name !== tableName) {\n throw ApiError.badRequest(\"History entry does not belong to this entity\");\n }\n\n if (!historyEntry.values) {\n throw ApiError.badRequest(\"Cannot revert: history entry has no stored values\");\n }\n\n // Revert by saving through the normal driver path — this will\n // itself create another history entry, giving a full audit trail.\n const authDriver = c.get(\"driver\") || driver;\n const path = collection.slug;\n\n const savedEntity = await authDriver.save({\n path,\n id: String(id),\n values: historyEntry.values,\n collection,\n status: \"existing\"\n });\n\n return c.json({\n data: savedEntity,\n meta: { reverted_from: historyId }\n });\n });\n\n return router;\n}\n","import type { Transporter } from \"nodemailer\";\nimport { EmailConfig, EmailSendOptions, EmailService } from \"./types\";\nimport { logger } from \"../utils/logger\";\n\nlet _nodemailer: typeof import(\"nodemailer\") | undefined;\n\nasync function loadNodemailer() {\n if (!_nodemailer) {\n try {\n _nodemailer = await import(\"nodemailer\");\n } catch {\n throw new Error(\n \"nodemailer is required for SMTP email. \" +\n \"Install it: pnpm add nodemailer\"\n );\n }\n }\n return _nodemailer;\n}\n\n/**\n * Safely parse a hostname from a URL string\n */\nfunction getHostname(urlStr: string): string | undefined {\n try {\n const url = new URL(urlStr.includes(\"://\") ? urlStr : `https://${urlStr}`);\n return url.hostname;\n } catch {\n return undefined;\n }\n}\n\n/**\n * SMTP Email Service implementation using Nodemailer\n */\nexport class SMTPEmailService implements EmailService {\n private transporter: Transporter | null = null;\n private config: EmailConfig;\n private _initialized = false;\n\n constructor(config: EmailConfig) {\n this.config = config;\n }\n\n /**\n * Lazily initialize the SMTP transporter on first use\n */\n private async ensureTransporter(): Promise<void> {\n if (this._initialized) return;\n this._initialized = true;\n\n if (this.config.smtp) {\n const nodemailer = await loadNodemailer();\n\n let smtpName = this.config.smtp.name;\n if (!smtpName) {\n const urlsToTry = [\n process.env.FRONTEND_URL,\n this.config.resetPasswordUrl,\n this.config.verifyEmailUrl\n ];\n for (const urlStr of urlsToTry) {\n if (urlStr) {\n const hostname = getHostname(urlStr);\n if (hostname) {\n smtpName = hostname;\n break;\n }\n }\n }\n }\n\n this.transporter = nodemailer.createTransport({\n name: smtpName,\n host: this.config.smtp.host,\n port: this.config.smtp.port,\n secure: this.config.smtp.secure ?? (this.config.smtp.port === 465),\n auth: this.config.smtp.auth ? {\n user: this.config.smtp.auth.user,\n pass: this.config.smtp.auth.pass\n } : undefined\n });\n }\n }\n\n /**\n * Check if the email service is properly configured\n */\n isConfigured(): boolean {\n return !!(this.config.smtp || this.config.sendEmail);\n }\n\n /**\n * Send an email using SMTP or custom send function\n */\n async send(options: EmailSendOptions): Promise<void> {\n // Use custom send function if provided\n if (this.config.sendEmail) {\n await this.config.sendEmail(options);\n return;\n }\n\n // Use SMTP transporter\n await this.ensureTransporter();\n\n if (!this.transporter) {\n throw new Error(\"Email service not configured. Provide SMTP config or sendEmail function.\");\n }\n\n const to = Array.isArray(options.to) ? options.to.join(\", \") : options.to;\n\n try {\n await this.transporter.sendMail({\n from: this.config.from,\n to,\n subject: options.subject,\n html: options.html,\n text: options.text,\n replyTo: options.replyTo\n });\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(\"Failed to send email\", { detail: message });\n throw new Error(`Failed to send email: ${message}`);\n }\n }\n\n /**\n * Verify SMTP connection (useful for startup checks)\n */\n async verifyConnection(): Promise<boolean> {\n await this.ensureTransporter();\n\n if (!this.transporter) {\n return !!this.config.sendEmail;\n }\n\n try {\n await this.transporter.verify();\n return true;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(\"SMTP connection verification failed\", { detail: message });\n return false;\n }\n }\n}\n\n/**\n * Create an email service from configuration\n */\nexport function createEmailService(config: EmailConfig): EmailService {\n return new SMTPEmailService(config);\n}\n","import type { RebaseServerClient } from \"@rebasepro/types\";\n\n/**\n * The backing instance lives on a process-global slot, NOT in a module-local\n * variable — because more than one copy of this module can be loaded into one\n * process, and a module-local would leave every copy but the booting one dead.\n *\n * That is the normal layout under the managed runtime, not an edge case: the\n * image ships the framework at `/app/node_modules`, while a project's bundle\n * installs its own dependencies into `/bundle/node_modules` — and every custom\n * function imports `defineFunction` from `@rebasepro/server`, which resolves to\n * the bundle's transitively-installed copy. `initializeRebaseBackend()` then ran\n * against `/app`'s copy while every function held `/bundle`'s, so `rebase.data`,\n * `rebase.storage` and `rebase.dataAsAdmin` threw \"server not initialized yet\"\n * on EVERY request, forever, in an otherwise healthy process.\n *\n * `Symbol.for` is the fix because its registry is per-process rather than\n * per-module: whichever copy boots publishes here, and every other copy — same\n * version or not — reads the same live client.\n */\nconst INSTANCE_SLOT = Symbol.for(\"@rebasepro/server:singleton-instance\");\n\ntype GlobalWithInstance = typeof globalThis & {\n [INSTANCE_SLOT]?: RebaseServerClient | null;\n};\n\nfunction getInstance(): RebaseServerClient | null {\n return (globalThis as GlobalWithInstance)[INSTANCE_SLOT] ?? null;\n}\n\nfunction setInstance(client: RebaseServerClient | null): void {\n (globalThis as GlobalWithInstance)[INSTANCE_SLOT] = client;\n}\n\n/**\n * @internal Called once during server initialization to set the backing instance.\n * This is invoked by `initializeRebaseBackend()` — never call it manually.\n */\nexport function _initRebase(client: RebaseServerClient): void {\n setInstance(client);\n}\n\n/**\n * @internal Allows overriding the underlying instance for unit testing.\n * Throws an error if used in a non-test environment to prevent production abuse.\n */\nexport function _setRebaseMock(mockInstance: Partial<RebaseServerClient>): void {\n if (process.env.NODE_ENV !== \"test\") {\n throw new Error(\"_setRebaseMock can only be called in a test environment (NODE_ENV=test).\");\n }\n setInstance({ ...(getInstance() || {} as RebaseServerClient),\n...mockInstance } as RebaseServerClient);\n}\n\n/**\n * @internal Resets the singleton instance, useful for afterEach() in test suites.\n */\nexport function _resetRebaseMock(): void {\n if (process.env.NODE_ENV !== \"test\") {\n throw new Error(\"_resetRebaseMock can only be called in a test environment.\");\n }\n setInstance(null);\n}\n\n/**\n * The server-side Rebase singleton.\n *\n * Initialized automatically during server startup. Provides access to all\n * app-scoped services: **data**, **auth**, **storage**, and **email**.\n *\n * **Admin data plane** (`rebase.dataAsAdmin`):\n * Backed by the native DataDriver — calls go directly to the database without\n * JSON serialization, HTTP dispatch, or middleware overhead. The driver is\n * scoped as `{ uid: \"service\", roles: [\"admin\"] }`, so **every read and write\n * bypasses row-level-security policies**. No `REBASE_SERVICE_KEY` is required.\n *\n * ⚠️ Because it bypasses RLS, `rebase.dataAsAdmin` is for trusted background\n * work (cron jobs, migrations, service tasks) — **not** for serving user-facing\n * data. Inside a request handler, run user-scoped queries through the\n * request-scoped driver (`c.var.driver`), which carries the caller's identity\n * so RLS applies.\n *\n * `rebase.data` is **gone from the type**: `RebaseServerClient` omits it, so the\n * admin-scoped accessor has exactly one name and the privilege is visible at the\n * call site. The property still exists at runtime, aliasing `dataAsAdmin`, so an\n * untyped JavaScript caller keeps working rather than failing on `undefined`.\n *\n * **Control plane** (`rebase.auth`, `rebase.admin`, `rebase.storage`, etc.):\n * Routes through the Hono app's internal request handler. An internal per-boot\n * credential is generated automatically when `REBASE_SERVICE_KEY` is not set,\n * so control-plane calls always authenticate.\n *\n * @example\n * ```typescript\n * import { rebase } from \"@rebasepro/server\";\n *\n * // In a cron job, hook, or trusted service file (admin scope, bypasses RLS):\n * await rebase.email.send({ to: \"admin@co.com\", subject: \"Alert\", html: \"<p>Hi</p>\" });\n * const jobs = await rebase.dataAsAdmin.jobs.find({ limit: 10 });\n * ```\n */\nexport const rebase: RebaseServerClient = new Proxy({} as RebaseServerClient, {\n get(_, prop) {\n const instance = getInstance();\n if (!instance) {\n throw new Error(\n `rebase.${String(prop)}: server not initialized yet. ` +\n \"The singleton is available after Rebase starts — don't call it at import time.\"\n );\n }\n return instance[prop as keyof RebaseServerClient];\n },\n set(_, prop) {\n throw new Error(\n `Cannot set rebase.${String(prop)} directly. ` +\n \"The singleton is read-only. Use _initRebase() during server startup.\"\n );\n }\n});\n","import type { AuthAdapter } from \"@rebasepro/types\";\n// Type-only, so it is erased at compile time and creates no runtime cycle with\n// `init.ts` — which imports the two functions below.\nimport type { RebaseAuthConfig } from \"../init\";\n\n/**\n * Whether the `auth` config is an `AuthAdapter` (it can verify a request) or a\n * plain `RebaseAuthConfig`. Lives here rather than in `init.ts` so this module\n * stays free of it; `init.ts` re-exports it under its original name.\n */\nexport function isAuthAdapter(auth: RebaseAuthConfig | AuthAdapter): auth is AuthAdapter {\n return typeof auth === \"object\" && auth !== null && \"verifyRequest\" in auth\n && typeof (auth as AuthAdapter).verifyRequest === \"function\";\n}\n\n/**\n * Does this server require an authenticated caller?\n *\n * One predicate, because there are two enforcement points — the HTTP data\n * routes and the realtime socket — and they used to compute it separately. The\n * socket's copy read\n *\n * ```ts\n * authConfig?.requireAuth !== false && !!authConfig?.jwtSecret\n * ```\n *\n * which differs from this in two ways, both of them open. With no auth config\n * at all it returned `false` while the HTTP side returned `true`, so a server\n * that answered 401 to every `/api/data` read served the same rows over the\n * socket. And an explicit `requireAuth: true` was ANDed away whenever the\n * credential came from an adapter rather than a local `jwtSecret` — asking for\n * authentication was what switched it off.\n *\n * It is worth stating why that is worse than an ordinary missing check: the\n * socket seeds each session with `authenticated: !requireAuth`, so a `false`\n * here does not skip a gate, it marks every client that connects as already\n * past it.\n *\n * Its own module rather than a helper in `init.ts` so the drivers can import it\n * without pulling the backend entry point in behind it.\n *\n * - an `AuthAdapter` always implies auth is required (secure by default)\n * - a `RebaseAuthConfig` is honoured, and only an explicit `false` opens it\n * - no auth configuration at all defaults to required\n */\nexport function resolveRequireAuth(auth?: RebaseAuthConfig | AuthAdapter): boolean {\n if (!auth) return true;\n if (isAuthAdapter(auth)) return true;\n return (auth as RebaseAuthConfig).requireAuth !== false;\n}\n","import {\n AuthAdapter,\n BackendBootstrapper,\n BootstrappedAuth,\n DatabaseAdapter,\n DataDriver,\n DataSourceDefinition,\n CollectionCallbacks,\n AnyCollectionConfig,\n CollectionConfig,\n HealthCheckResult,\n HistoryConfig,\n InitializedDriver,\n isPostgresCollectionConfig,\n isSQLAdmin,\n RealtimeProvider,\n SecurityRule\n} from \"@rebasepro/types\";\nimport { createDataSourceRegistry, resolveDataSource, buildSdkData, buildRoutedRebaseData, getEffectiveSecurityRules } from \"@rebasepro/common\";\nimport { randomBytes } from \"node:crypto\";\nimport { BackendCollectionRegistry } from \"./collections/BackendCollectionRegistry\";\nimport { loadCollectionsFromDirectory } from \"./collections/loader\";\nimport { assertCollectionConfigs } from \"./collections/validate-config\";\nimport { DEFAULT_DRIVER_ID, DefaultDriverRegistry, DriverRegistry } from \"./services/driver-registry\";\nimport { createRoutedRealtimeService } from \"./services/routed-realtime-service\";\nimport { Server } from \"http\";\n\nimport { RestApiGenerator } from \"./api/rest/api-generator\";\nimport { createAuthMiddleware } from \"./auth/middleware\";\nimport { createAdapterAuthMiddleware } from \"./auth/adapter-middleware\";\nimport { scopeDataDriver } from \"./auth/rls-scope\";\nimport { createBuiltinAuthAdapter } from \"./auth/builtin-auth-adapter\";\nimport { errorHandler } from \"./api/errors\";\nimport { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { HonoEnv } from \"./api/types\";\nimport { configureLogLevel } from \"./utils/logging\";\nimport { logger } from \"./utils/logger\";\nimport { configureMiddlewares } from \"./init/middlewares\";\nimport { initializeStorage, assertStorageAccessControlConfigured } from \"./init/storage\";\nimport { mountOpenApiDocs } from \"./init/docs\";\nimport { createHealthCheck } from \"./init/health\";\nimport { createShutdown } from \"./init/shutdown\";\nimport { configureJwt, requireAdmin } from \"./auth\";\nimport {\n BackendStorageConfig,\n createStorageRoutes,\n StorageController,\n StorageRegistry\n} from \"./storage\";\nimport type { ApiKeyStore } from \"./auth/api-keys/api-key-store\";\nimport { createApiKeyStore } from \"./auth/api-keys/api-key-store\";\nimport { createApiKeyRoutes } from \"./auth/api-keys/api-key-routes\";\nimport { createApiKeyPreAuth, createFunctionApiKeyGuard, createStorageApiKeyGuard } from \"./auth/api-keys/api-key-middleware\";\nimport { createRequireAuth } from \"./auth/middleware\";\nimport { createDataRateLimiter, type DataRateLimitConfig } from \"./auth/rate-limiter\";\nimport { MemoryRateLimitStore } from \"./auth/rate-limit-store\";\nimport { warnOnAuthCollectionDataCallbacks } from \"./auth/collection-callback-warning\";\nimport { createRebaseClient } from \"@rebasepro/client\";\n\nimport { createHistoryRoutes } from \"./history\";\nimport type { EmailService } from \"./email\";\nimport { createEmailService, EmailConfig } from \"./email\";\nimport type { OAuthProvider } from \"./auth/interfaces\";\nimport type { AuthHooks } from \"./auth/auth-hooks\";\nimport { _initRebase } from \"./singleton\";\n\nexport interface RebaseAuthConfig {\n /**\n * The collection that represents auth users.\n *\n * When provided, this collection's underlying database table is used\n * for all auth operations (login, registration, password reset, etc.).\n *\n * Import the built-in default:\n * ```ts\n * import { defaultUsersCollection } from \"@rebasepro/common\";\n * auth: { collection: defaultUsersCollection, jwtSecret: \"...\" }\n * ```\n *\n * Or pass your own collection with the required auth fields\n * (email, passwordHash, displayName, etc.).\n */\n /**\n * Accepts a collection of any row type: `defineCollection` infers `M` from\n * the properties, and `CollectionConfig` is invariant in `M`, so a bare\n * `CollectionConfig` here rejects everything the builder returns.\n */\n collection?: AnyCollectionConfig;\n jwtSecret?: string;\n accessExpiresIn?: string;\n refreshExpiresIn?: string;\n requireAuth?: boolean;\n allowRegistration?: boolean;\n /**\n * Block self-registration outright — the hard kill switch.\n *\n * `allowRegistration: false` still admits the very first user on an empty\n * database, because otherwise a fresh deployment has no way to create its\n * own admin: `POST /admin/bootstrap` needs an authenticated caller. This\n * closes that window too, for operators who provision every account out of\n * band and never want a public first-come-first-admin race.\n *\n * With this set, an empty backend has no self-service path in at all —\n * create the first user with the CLI or a seed script.\n */\n disableSelfRegistration?: boolean;\n /**\n * Opt-in: expose `POST /auth/find-user` so an authenticated user can resolve\n * an email address to a minimal public profile (`uid`, `displayName`,\n * `photoURL` only). This powers invite-by-email flows without a custom\n * admin server function. Off by default because it enables user enumeration\n * by any signed-in user. Available on the client as `auth.findUserByEmail`.\n */\n allowUserLookup?: boolean;\n /**\n * A static secret key for server-to-server / script authentication.\n *\n * When a request includes `Authorization: Bearer <serviceKey>`, it is\n * granted admin-level access without JWT verification. This is the\n * Rebase equivalent of a Service Account key.\n *\n * Generate with: `node -e \"logger.info(require('crypto').randomBytes(48).toString('base64'))\"`\n *\n * Set via `REBASE_SERVICE_KEY` in your `.env`.\n * Must be at least 32 characters.\n */\n serviceKey?: string;\n email?: EmailConfig;\n // ── Convenience shortcuts ─────────────────────────────────────────\n // Each named field below is syntactic sugar that internally resolves\n // to an `OAuthProvider` via the corresponding `create*Provider`\n // factory at startup. They are equivalent to constructing the\n // provider manually and passing it in the `providers` array.\n //\n // For providers not listed here, or for full control over the\n // provider configuration, use the `providers` array directly.\n google?: { clientId: string; clientSecret?: string };\n linkedin?: { clientId: string; clientSecret: string };\n github?: { clientId: string; clientSecret: string };\n microsoft?: { clientId: string; clientSecret: string; tenantId?: string };\n apple?: { clientId: string; teamId: string; keyId: string; privateKey: string };\n facebook?: { clientId: string; clientSecret: string };\n twitter?: { clientId: string; clientSecret: string };\n discord?: { clientId: string; clientSecret: string };\n gitlab?: { clientId: string; clientSecret: string; baseUrl?: string };\n bitbucket?: { clientId: string; clientSecret: string };\n slack?: { clientId: string; clientSecret: string };\n spotify?: { clientId: string; clientSecret: string };\n defaultRole?: string;\n /**\n * Canonical array of OAuth providers.\n *\n * This is the primary extension point for **all** OAuth integrations.\n * Each entry is an `OAuthProvider<unknown>` constructed via one of\n * the `create*Provider` factories exported from `@rebasepro/server`\n * (e.g. `createGoogleProvider`, `createGitHubProvider`).\n *\n * The named convenience fields above (`google`, `github`, etc.) are\n * automatically resolved into this array at startup. You can mix both\n * approaches; named fields and explicit entries are merged (named\n * fields are appended after explicit entries).\n *\n * @example\n * ```ts\n * import { createGoogleProvider } from \"@rebasepro/server\";\n *\n * auth: {\n * providers: [\n * createGoogleProvider({ clientId: \"…\", clientSecret: \"…\" }),\n * ],\n * }\n * ```\n */\n providers?: OAuthProvider<unknown>[];\n /**\n * Override specific parts of the built-in auth implementation.\n *\n * Each override replaces one piece of the default behavior while\n * keeping everything else intact. Unset overrides fall through\n * to the built-in defaults (scrypt passwords, standard validation, etc.).\n *\n * @example bcrypt passwords with a custom hash\n * ```ts\n * import bcrypt from \"bcrypt\";\n *\n * hooks: {\n * hashPassword: (pw) => bcrypt.hash(pw, 12),\n * verifyPassword: (pw, hash) => bcrypt.compare(pw, hash),\n * }\n * ```\n */\n hooks?: AuthHooks;\n\n /**\n * Enable magic link (passwordless email) authentication.\n * Requires email to be configured.\n */\n magicLink?: boolean;\n /**\n * Opt-in httpOnly cookie mode for refresh tokens.\n *\n * When set, the refresh token is delivered as an `httpOnly`, `Secure`,\n * `SameSite` cookie instead of in the JSON response body. This\n * prevents XSS from stealing the long-lived refresh token.\n *\n * The access token remains in the JSON body so the client can use it\n * in `Authorization: Bearer` headers for API calls.\n *\n * **Requires** `credentials: \"include\"` on client-side fetch calls to\n * auth endpoints, and CORS must allow credentials (no `origin: \"*\"`).\n */\n cookieAuth?: import(\"./auth\").CookieAuthConfig;\n}\n\n/** @see RebaseBackendConfig.baas */\nexport interface BaasOptions {\n /**\n * What to do with introspected tables that have row-level security\n * disabled.\n *\n * Such a table carries no authorization model. Every authenticated request\n * runs as `rebase_user`, which is granted DML on the schema, so serving one\n * hands every row to every logged-in user — the API would be an open door\n * onto whatever the database happens to contain.\n *\n * - `\"exclude\"` (default) — do not serve it. Each excluded table is logged\n * with the SQL to protect it. Secure by default, consistent with the rest\n * of the driver, which fails a boot rather than serve unenforced requests.\n * - `\"serve\"` — serve it anyway. Only sensible when every caller is already\n * trusted, e.g. an internal service behind its own authorization.\n */\n unprotectedTables?: \"exclude\" | \"serve\";\n}\n\nexport interface RebaseBackendConfig {\n /** Invariance again — see the note on `RebaseAuthConfig.collection`. */\n collections?: AnyCollectionConfig[];\n collectionsDir?: string;\n server: Server;\n app: Hono<HonoEnv>;\n basePath?: string;\n\n /**\n * Rate limiting for the data API, per caller: an API key by its id, a\n * signed-in user by their uid, anyone else by IP.\n *\n * On by default with loose limits — a floor against a runaway client, not a\n * quota. Counts live in this process's memory unless you pass a `store`, so\n * N replicas enforce N times the limit between them; set real quotas at a\n * proxy or supply a shared store if that matters. `{ enabled: false }` for\n * a deployment whose edge already does this.\n */\n rateLimit?: DataRateLimitConfig;\n\n\n /**\n * Force the schema-editor routes on or off.\n *\n * Defaults to enabled when `collectionsDir` is set, outside production, in\n * `cms` mode. The editor rewrites collection files, so it needs a\n * `collectionsDir` to write to.\n */\n schemaEditor?: boolean;\n\n /** Options that only apply when collections are derived from the database. */\n baas?: BaasOptions;\n\n /**\n * Declared data sources, shared with the frontend `<Rebase dataSources>`.\n *\n * Used to resolve each collection's engine (capabilities) and transport.\n * Collections on a `direct`/`custom` transport are client-only: the backend\n * still owns their schema/registry but does **not** generate server data\n * routes for them. Server-mediated sources (the default) need no entry.\n */\n dataSources?: DataSourceDefinition[];\n\n /**\n * Database bootstrappers.\n */\n bootstrappers?: BackendBootstrapper[];\n /**\n * Database adapter.\n *\n * When set, this takes precedence over `bootstrappers`.\n *\n * @example\n * ```ts\n * import { createPostgresAdapter } from \"@rebasepro/server-postgres\";\n * database: createPostgresAdapter({ connection: db, schema }),\n * ```\n */\n database?: DatabaseAdapter;\n\n logging?: {\n level?: \"error\" | \"warn\" | \"info\" | \"debug\";\n };\n\n /**\n * Authentication configuration.\n *\n * Accepts **either**:\n * - `RebaseAuthConfig` — built-in configuration\n * - `AuthAdapter` — pluggable adapter for external auth (Clerk, Auth0, etc.)\n *\n * When a plain config object is provided, the built-in adapter is created\n * automatically from the bootstrapper's `initializeAuth()` result.\n */\n auth?: RebaseAuthConfig | AuthAdapter;\n\n /**\n * Storage configuration. Accepts:\n *\n * - A `BackendStorageConfig` object (`{ type: 'local' | 's3' | 'gcs', ... }`)\n * - A `StorageController` instance (for custom providers like Azure, etc.)\n * - A `Record<string, ...>` of either, for multi-backend setups\n */\n storage?: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController>;\n\n /**\n * Declared storage sources. Drives the client-side StorageSourceRegistry\n * and the transport distinction (server vs direct).\n *\n * Server-backed sources are auto-derived from the `storage` map — you\n * only need explicit entries for \"direct\" transport sources (e.g.\n * external storage) that the backend does not proxy.\n */\n storageSources?: import(\"@rebasepro/types\").StorageSourceDefinition[];\n\n /**\n * Per-object access control for storage — the analogue of a collection's\n * security rules, and the thing `requireAuth` / `publicRead` cannot\n * express because they are global switches.\n *\n * Called after authentication on every storage route with the key, bucket,\n * operation (`read` / `write` / `delete` / `list`) and resolved user.\n * Return false to deny with a 403; throwing denies too.\n *\n * ```ts\n * storageAuthorize: async ({ key, user, operation }) => {\n * if (!user) return false;\n * const [ownerId] = key.split(\"/\");\n * return ownerId === user.uid || operation === \"read\";\n * }\n * ```\n *\n * Without it, any authenticated caller may read any key they can name, so\n * multi-tenant apps should treat this as required rather than optional.\n *\n * In production, storage refuses to boot unless one of `storageAuthorize`,\n * {@link storagePublicRead}, or {@link storageInsecureAllowAnyAuthenticated}\n * is set — see `assertStorageAccessControlConfigured`.\n */\n storageAuthorize?: import(\"./storage/types\").StorageAuthorize;\n\n /**\n * Allow unauthenticated read access to stored files (default: false).\n *\n * Set this only when the bucket is genuinely a public, read-only CDN.\n * Writes, deletes and listing still require authentication. Because it is a\n * deliberate statement that reads are public, it also satisfies the\n * production storage boot guard (see {@link storageAuthorize}).\n */\n storagePublicRead?: boolean;\n\n /**\n * Opt out of the storage access-control boot guard, keeping the legacy\n * behaviour where **any** authenticated user can read, overwrite, delete or\n * list **any** key (storage keys share one flat namespace and are not under\n * RLS).\n *\n * Only safe for single-tenant apps where every signed-in user is trusted\n * with every file. Multi-tenant apps must use `storageAuthorize` instead.\n * Without one of these, storage refuses to boot in production.\n */\n storageInsecureAllowAnyAuthenticated?: boolean;\n\n /**\n * Entity history / audit-log configuration.\n *\n * - `true` — enable history with default settings\n * - `{ retention?: number }` — enable with optional retention period (days)\n */\n history?: HistoryConfig;\n enableSwagger?: boolean;\n functionsDir?: string;\n cronsDir?: string;\n /**\n * Enable/disable database persistence for cron job execution logs.\n * When set to false, cron jobs will run but logs will not be persisted to the database.\n * Default: true.\n */\n cronPersistence?: boolean;\n /**\n * Maximum request body size in bytes for API routes (default: 10MB).\n * Set to 0 to disable the global limit entirely.\n *\n * Note: Storage upload routes use their own limit from the storage config's\n * `maxFileSize` property (default: 50MB), which takes precedence over this.\n */\n maxBodySize?: number;\n /**\n * Response compression for API routes. **Enabled by default.**\n *\n * Compresses responses with gzip/deflate, negotiated from the request's\n * `Accept-Encoding`. Bodies that are already compressed (images, video),\n * streamed (`text/event-stream`), or explicitly marked\n * `Cache-Control: no-transform` are left untouched, so this is safe to\n * leave on — a large JSON list response typically drops by ~20x.\n *\n * Set to `false` when something in front of the app already compresses\n * (nginx, Cloudflare, or another reverse proxy / load balancer), to avoid\n * paying for it twice.\n */\n compression?: boolean;\n /**\n * CSRF protection configuration. **Opt-in** — disabled by default.\n *\n * BaaS APIs are consumed by mobile apps, SPAs on different domains,\n * and CLI tools, so CSRF is intentionally not enabled unless you\n * explicitly configure it with allowed origins.\n *\n * @example\n * ```ts\n * csrf: { origin: [\"https://myapp.com\", \"https://admin.myapp.com\"] }\n * ```\n */\n csrf?: {\n /** Allowed origins for CSRF validation. */\n origin: string | string[] | ((origin: string) => boolean);\n };\n /**\n * Global lifecycle callbacks applied to every collection.\n *\n * Same type as per-collection `callbacks` — fires on **every** data path\n * (REST API, WebSocket / realtime, server-side `rebase.data`).\n *\n * Execution order: global callbacks → collection callbacks → property callbacks.\n *\n * @example\n * ```ts\n * callbacks: {\n * afterRead({ row, collection }) {\n * console.log(`Read ${collection.slug}/${row.id}`);\n * return row;\n * }\n * }\n * ```\n */\n callbacks?: CollectionCallbacks;\n\n /**\n * Declare that this application installs its own CORS middleware.\n *\n * Suppresses the \"no CORS configuration detected\" warning, which exists for\n * hand-wired backends that genuinely have no origin policy.\n */\n corsHandled?: boolean;\n\n /**\n * The schema version this deployment serves, as recorded when it was built.\n *\n * Published by the contract endpoint so a client generated elsewhere can\n * tell whether it is current. Leave unset and the runtime computes one from\n * the live collections — correct, but it means the value moves whenever the\n * collections do, which is exactly right for `baas` mode and slightly less\n * useful for a built bundle that already knows its own answer.\n */\n schemaVersion?: string;\n\n /** Runtime version reported by the contract endpoint. Informational. */\n runtimeVersion?: string;\n}\n\n/**\n * Type guard to detect whether the `auth` config is an `AuthAdapter`\n * (has a `verifyRequest` method) vs a plain `RebaseAuthConfig` (plain object).\n *\n * Re-exported from `auth/require-auth`, which is where it now lives so the\n * drivers can reach `resolveRequireAuth` without importing this entry point.\n */\nimport { isAuthAdapter, resolveRequireAuth } from \"./auth/require-auth\";\nexport { isAuthAdapter } from \"./auth/require-auth\";\n\n/**\n * Type guard to detect whether `database` is a `DatabaseAdapter`.\n */\nexport function isDatabaseAdapter(db: unknown): db is DatabaseAdapter {\n return typeof db === \"object\" && db !== null && \"initializeDriver\" in db && \"type\" in db && !(\"initializeAuth\" in db);\n}\n\n\nexport interface RebaseBackendInstance {\n driverRegistry: DriverRegistry;\n driver: DataDriver;\n realtimeServices: Record<string, RealtimeProvider>;\n realtimeService: RealtimeProvider;\n auth?: BootstrappedAuth;\n history?: { historyService: import(\"./history/history-routes\").HistoryService };\n storageRegistry?: StorageRegistry;\n storageController?: StorageController;\n collectionRegistry: BackendCollectionRegistry;\n cronScheduler?: import(\"./cron\").CronScheduler;\n\n /**\n * Attach collection callbacks AFTER initialization.\n *\n * Use this instead of mutating `collectionRegistry.get(slug).callbacks`.\n * Every registry normalizes its collections through `{ ...c }`, so the\n * backend registry and each driver's registry hold **separate copies** of\n * the same collection — assigning callbacks to one is invisible to the\n * driver that actually invokes them, and the hooks silently never fire.\n * This writes to all of them.\n *\n * (Assignment, not `Object.defineProperty`: the driver resolves callbacks\n * with a spread, which copies only enumerable properties, and\n * defineProperty defaults `enumerable` to false.)\n */\n setCollectionCallbacks(slug: string, callbacks: import(\"@rebasepro/types\").CollectionCallbacks): void;\n\n /**\n * Deep health check that verifies database connectivity.\n * Returns latency and component status.\n */\n healthCheck(): Promise<HealthCheckResult>;\n\n /**\n * Graceful shutdown helper for the BaaS instance.\n * Stops the cron scheduler and closes the HTTP server, allowing\n * in-flight requests to drain within the given timeout.\n *\n * @param timeoutMs - Maximum time (ms) to wait for drain before force-exit (default: 15000).\n * Pass 0 to skip the force-exit timer (useful in tests).\n */\n shutdown(timeoutMs?: number): Promise<void>;\n}\n\n/**\n * Present a `DatabaseAdapter` as a `BackendBootstrapper`.\n *\n * The `config.database` convenience path — one adapter, no explicit source keys\n * — funnels through here. `adapterToBootstrapper` in `boot/driver.ts` does the\n * same job for the multi-source path, and the two stay separate because only\n * that one carries a registry id and a default flag; this path has exactly one\n * driver and needs neither.\n *\n * Extracted from the middle of `initializeRebaseBackend` so it can be tested.\n * Both wrappers rebuild the bootstrapper field by field, which means any\n * capability nobody remembers to list is dropped in silence — no type error,\n * because every one of them is optional, and no runtime error either, because\n * the caller's own fallback for \"driver does not implement this\" is to skip.\n * That is not hypothetical: `ensureCollectionSchema` was missing from both\n * wrappers for months, so every managed tenant booted with no collection tables\n * and 500'd on every data route. `bootstrapper-forwarding.test.ts` now asserts\n * both wrappers pass through the whole optional surface.\n */\nexport function wrapDatabaseAdapter(dbAdapter: DatabaseAdapter): BackendBootstrapper {\n return {\n type: dbAdapter.type,\n initializeDriver: (initConfig: unknown) =>\n dbAdapter.initializeDriver(initConfig as import(\"@rebasepro/types\").DatabaseAdapterInitConfig),\n initializeRealtime: dbAdapter.initializeRealtime\n ? (_config: unknown, driverResult: InitializedDriver) =>\n dbAdapter.initializeRealtime!(driverResult)\n : undefined,\n initializeAuth: dbAdapter.initializeAuth,\n initializeHistory: dbAdapter.initializeHistory,\n initializeWebsockets: dbAdapter.initializeWebsockets,\n ensureCollectionSchema: dbAdapter.ensureCollectionSchema\n ? (collections, driverResult, log) =>\n dbAdapter.ensureCollectionSchema!(collections, driverResult, log)\n : undefined,\n ensureCollectionPolicies: dbAdapter.ensureCollectionPolicies\n ? (collections, driverResult, log) =>\n dbAdapter.ensureCollectionPolicies!(collections, driverResult, log)\n : undefined,\n getAdmin: dbAdapter.getAdmin,\n mountRoutes: dbAdapter.mountRoutes\n };\n}\n\nexport async function initializeRebaseBackend(config: RebaseBackendConfig): Promise<RebaseBackendInstance> {\n // No try/catch: let init errors propagate to the caller.\n // The app entry point (e.g. startServer()) should catch and process.exit(1).\n // Returning a fake instance hides critical failures and leads to silent data loss.\n return await _initializeRebaseBackend(config);\n}\n\nasync function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<RebaseBackendInstance> {\n if (config.logging?.level) {\n configureLogLevel(config.logging.level);\n } else {\n configureLogLevel();\n }\n\n logger.info(\"Initializing Rebase Backend\");\n\n const basePath = config.basePath || \"/api\";\n const isProduction = process.env.NODE_ENV === \"production\";\n\n // Configure Hono middlewares (Request ID, body limit, CSRF, CORS warning, logging)\n configureMiddlewares(config.app, basePath, isProduction, config);\n\n const collectionRegistry = new BackendCollectionRegistry();\n // Declared data sources — drives engine resolution (capabilities) and the\n // server-vs-direct transport distinction. Set before collections register\n // so normalization can resolve each collection's engine.\n const dataSourceRegistry = createDataSourceRegistry(config.dataSources);\n collectionRegistry.setDataSources(dataSourceRegistry);\n\n // Global lifecycle callbacks — applied to every collection, on all data paths.\n if (config.callbacks) {\n collectionRegistry.setGlobalCallbacks(config.callbacks);\n }\n let activeCollections = config.collections || [];\n // Collections handed in directly never touch the loader, so its strict parse\n // has to be repeated here. Configs derived from the database schema below are\n // machine-generated and are deliberately not checked.\n if (activeCollections.length > 0) assertCollectionConfigs(activeCollections);\n if (config.collectionsDir && activeCollections.length === 0) {\n activeCollections = await loadCollectionsFromDirectory(config.collectionsDir);\n logger.info(\"Auto-discovered collections\", {\n count: activeCollections.length,\n dir: config.collectionsDir\n });\n }\n\n // Declared collections, or the database's own schema.\n //\n // This was a `mode` flag the caller set, which could disagree with the\n // collections it was set alongside — the server then warned and threw the\n // collections away. There is no such state now: declaring collections is\n // what makes them served.\n //\n // Derived from what actually RESOLVED, not from what was configured: a\n // `collectionsDir` pointing at nothing declares nothing, and treating that\n // as \"declared\" would serve an empty API and never look at the database.\n const introspectCollections = activeCollections.length === 0;\n logger.info(\n introspectCollections\n ? \"No collections declared — deriving them from the database schema\"\n : \"Serving declared collections\"\n );\n\n // Directory-level `defaultSecurityRules` are applied by the collection\n // loader, so the server and `db push` agree on what a collection's rules\n // are. They cannot be set here: the generators that write the actual\n // Postgres policies never see this config.\n\n const realtimeServices: Record<string, RealtimeProvider> = {};\n const delegates: Record<string, DataDriver> = {};\n\n // ─── Resolve bootstrappers ───────────────────────────────────────────\n let bootstrappers: BackendBootstrapper[] = config.bootstrappers || [];\n if (config.database) {\n const dbAdapter = config.database;\n logger.info(\"Using DatabaseAdapter\", { type: dbAdapter.type });\n bootstrappers = [wrapDatabaseAdapter(dbAdapter)];\n }\n\n if (bootstrappers.length === 0) {\n throw new Error(\"No bootstrappers or database adapter provided. Cannot initialize database drivers.\");\n }\n\n let defaultDriverId = DEFAULT_DRIVER_ID;\n\n let defaultDriverResult: InitializedDriver | undefined = undefined;\n\n // 1. Initialize all drivers\n for (const bootstrapper of bootstrappers) {\n const b = bootstrapper;\n logger.info(\"Running bootstrapper for driver\", { driverId: b.id || bootstrapper.type });\n if (b.isDefault) {\n defaultDriverId = b.id || bootstrapper.type;\n }\n\n const driverResult = await bootstrapper.initializeDriver({\n collections: activeCollections,\n collectionRegistry,\n introspectCollections,\n baas: config.baas\n });\n delegates[b.id || bootstrapper.type] = driverResult.driver;\n\n // In baas mode the driver reports what it found in the database.\n // `undefined` means it never looked — it has no introspection support,\n // so baas mode can only ever serve nothing. Say so at boot rather than\n // letting every request 404 against a server that claims to be healthy.\n if (introspectCollections) {\n const driverName = b.id || bootstrapper.type;\n if (!driverResult.collections) {\n throw new Error(\n `Driver \"${driverName}\" cannot derive collections from the database schema, ` +\n \"and this project declared none. Declare collections, or use a driver that \" +\n \"implements introspection (e.g. @rebasepro/server-postgres).\"\n );\n }\n if (driverResult.collections.length === 0) {\n logger.warn(\n `Driver \"${driverName}\" found no tables to serve. The data API will not be mounted. ` +\n \"Create tables (migrations, SQL, any tool) and restart.\"\n );\n }\n }\n\n // These never passed through the config-time steps above, so apply them\n // here — but only when the driver was asked to describe the schema. A\n // project that declared its own collections must not have more injected\n // into it by whatever the database happens to contain.\n if (introspectCollections && driverResult.collections?.length) {\n activeCollections = [...activeCollections, ...driverResult.collections];\n }\n\n if ((b.id || bootstrapper.type) === defaultDriverId || !defaultDriverResult) {\n defaultDriverResult = driverResult;\n }\n\n if (bootstrapper.initializeRealtime) {\n const realtime = await bootstrapper.initializeRealtime({}, driverResult);\n if (realtime) {\n realtimeServices[b.id || bootstrapper.type] = realtime;\n }\n }\n }\n\n const driverRegistry = DefaultDriverRegistry.create(delegates);\n activeCollections.forEach(collection => collectionRegistry.register(collection));\n\n const defaultDriver = driverRegistry.getOrDefault(defaultDriverId);\n if (!defaultDriver || !defaultDriverResult) {\n throw new Error(\"Default driver not initialized by bootstrappers\");\n }\n const defaultBootstrapper = bootstrappers.find(b => b.id === defaultDriverId || b.type === defaultDriverId) || bootstrappers[0];\n const defaultRealtimeService = defaultDriverResult.realtimeProvider;\n\n // Resolve a collection path (e.g. \"products\", \"authors/1/posts\") to its\n // data-source key — shared by the data-driver router and the realtime\n // router. Falls back to the default key for unknown paths.\n const keyForCollectionPath = (collectionPath: string): string => {\n const slug = collectionPath.replace(/^\\/+/, \"\").split(\"/\")[0]?.split(\"?\")[0];\n if (!slug) return DEFAULT_DRIVER_ID;\n const collection = collectionRegistry.get(slug) ?? collectionRegistry.getCollectionByPath(slug);\n if (!collection) return DEFAULT_DRIVER_ID;\n return resolveDataSource(collection, dataSourceRegistry).key;\n };\n\n // ── Data-source misconfiguration check ────────────────────────────────\n // A server-transport collection whose resolved data-source key has no\n // registered driver delegate would silently fall back to the default\n // driver — i.e. land in the wrong database. Warn loudly so this surfaces\n // at boot rather than as mysterious data going to the wrong engine.\n {\n const unresolved = new Map<string, string[]>();\n const nonRlsEngines = new Set<string>();\n for (const collection of activeCollections) {\n const ds = resolveDataSource(collection, dataSourceRegistry);\n if (ds.transport !== \"server\") continue; // direct/custom are client-only\n // Server engines without row-level security enforce authorization\n // only at the application layer — surface this so it isn't a\n // silent assumption. (The default Postgres engine supports RLS.)\n if (!ds.capabilities.supportsRLS) nonRlsEngines.add(ds.engine);\n if (ds.key === DEFAULT_DRIVER_ID) continue; // always maps to the default\n if (!driverRegistry.has(ds.key)) {\n const slugs = unresolved.get(ds.key) ?? [];\n slugs.push(collection.slug ?? collection.name ?? \"?\");\n unresolved.set(ds.key, slugs);\n }\n }\n for (const [key, slugs] of unresolved) {\n logger.warn(\n `[DataSource] No driver registered for data source \"${key}\" ` +\n `(used by: ${slugs.join(\", \")}). These collections will fall back to the ` +\n `default driver \"${defaultDriverId}\" — register a bootstrapper with this id, ` +\n `or mark the data source as a direct/custom transport in \\`dataSources\\`.`\n );\n }\n for (const engine of nonRlsEngines) {\n logger.warn(\n `[DataSource] Engine \"${engine}\" does not support row-level security; ` +\n `authorization for its collections is enforced only at the application layer ` +\n `(authentication still applies). Ensure app-level checks or engine-native rules are in place.`\n );\n }\n }\n\n // 2. Initialize Auth & History via the default driver's bootstrapper\n let authConfigResult: BootstrappedAuth | undefined = undefined;\n let serviceKey: string | undefined;\n let authAdapter: AuthAdapter | undefined;\n\n if (config.auth) {\n if (isAuthAdapter(config.auth)) {\n // ── New path: User provided an AuthAdapter directly ──────────\n authAdapter = config.auth;\n serviceKey = authAdapter.serviceKey;\n\n if (authAdapter.initialize) {\n await authAdapter.initialize();\n }\n\n logger.info(\"Using AuthAdapter\", { id: authAdapter.id });\n\n // Populate authConfigResult for backward compatibility\n // (the return type still exposes `auth?: BootstrappedAuth`)\n authConfigResult = {\n userService: authAdapter.userManagement ?? {}\n };\n } else {\n // ── RebaseAuthConfig — wrap in built-in adapter ──\n const safeAuthConfig = config.auth as RebaseAuthConfig;\n\n // Auto-discover the auth collection from activeCollections if not explicitly set\n if (!safeAuthConfig.collection) {\n const foundAuthCollection = activeCollections.find(c => {\n const isAuth = c.auth;\n return isAuth === true || (isAuth && typeof isAuth === \"object\" && isAuth.enabled === true);\n });\n if (foundAuthCollection) {\n safeAuthConfig.collection = foundAuthCollection;\n logger.info(\"Auto-discovered auth collection from collection definitions\", { slug: foundAuthCollection.slug });\n }\n }\n\n // The built-in auth subsystem (users, sessions, repository) is\n // bootstrapped on the DEFAULT driver. If the auth collection is\n // routed to a non-default data source, login would read/write the\n // default engine while the collection's data views hit another —\n // a split-brain user store. Warn loudly.\n if (safeAuthConfig.collection) {\n const authDs = resolveDataSource(safeAuthConfig.collection, dataSourceRegistry);\n if (authDs.key !== DEFAULT_DRIVER_ID) {\n logger.warn(\n `[Auth] The auth collection \"${safeAuthConfig.collection.slug}\" is on data source ` +\n `\"${authDs.key}\", but the built-in auth system always uses the default data source. ` +\n `Move the auth collection to the default data source, or replace auth with an AuthAdapter ` +\n `that manages users in \"${authDs.key}\".`\n );\n }\n }\n\n // The auth write path does not run the collection save pipeline, on\n // purpose — say so when the collection expects otherwise.\n warnOnAuthCollectionDataCallbacks(safeAuthConfig.collection as never);\n\n // Extract the collection-level auth config (if `auth` is an object, not just `true`)\n const collectionAuth = safeAuthConfig.collection ? safeAuthConfig.collection.auth : undefined;\n const collectionAuthConfig = (typeof collectionAuth === \"object\" && collectionAuth !== null) ? collectionAuth : undefined;\n if (safeAuthConfig.jwtSecret) {\n configureJwt({\n secret: safeAuthConfig.jwtSecret,\n accessExpiresIn: safeAuthConfig.accessExpiresIn || \"1h\",\n refreshExpiresIn: safeAuthConfig.refreshExpiresIn || \"30d\"\n });\n }\n\n // ── Service Key Validation ───────────────────────────────────\n if (safeAuthConfig.serviceKey) {\n if (safeAuthConfig.serviceKey.length < 32) {\n throw new Error(\n \"REBASE_SERVICE_KEY is too short. Must be at least 32 characters. \" +\n \"Generate one with: node -e \\\"logger.info(require('crypto').randomBytes(48).toString('base64'))\\\"\"\n );\n }\n serviceKey = safeAuthConfig.serviceKey;\n logger.info(\"Service key configured for script/server-to-server authentication\");\n }\n\n if (defaultBootstrapper.initializeAuth) {\n logger.info(\"Bootstrapping authentication via driver protocol\");\n authConfigResult = await defaultBootstrapper.initializeAuth(config.auth, defaultDriverResult);\n\n // The built-in auth adapter is created after OAuth providers\n // are resolved (below) so it only needs to be constructed once.\n\n logger.info(\"Authentication initialized\");\n } else {\n logger.warn(\"Auth requested but default bootstrapper does not support initializeAuth\");\n }\n }\n }\n\n let historyConfigResult: { historyService: import(\"./history/history-routes\").HistoryService } | undefined = undefined;\n if (config.history) {\n if (defaultBootstrapper.initializeHistory) {\n logger.info(\"Bootstrapping entity history via driver protocol\");\n historyConfigResult = await defaultBootstrapper.initializeHistory(config.history, defaultDriverResult) as { historyService: import(\"./history/history-routes\").HistoryService } | undefined;\n\n // Inject the historyService into the driver so save/delete can record history.\n // The driver was created during initializeDriver() (before history was initialized),\n // so we must set it retroactively here.\n if (historyConfigResult?.historyService && defaultDriverResult.internals) {\n const internals = defaultDriverResult.internals as Record<string, unknown>;\n const driver = internals.driver as Record<string, unknown> | undefined;\n if (driver && \"historyService\" in driver) {\n driver.historyService = historyConfigResult.historyService;\n }\n }\n\n logger.info(\"Entity history initialized\");\n } else {\n logger.warn(\"History requested but default bootstrapper does not support initializeHistory\");\n }\n }\n\n // ─── Internal per-process credential ───────────────────────────────────\n // When the user hasn't configured a REBASE_SERVICE_KEY, generate a random\n // per-boot key so the singleton's control-plane APIs (auth, admin, storage,\n // functions) can still authenticate against the server's own middleware.\n // This key never leaves the process and is never logged.\n //\n // Resolved BEFORE route mounting so every admin surface — including the\n // adapter-created admin routes, whose middleware captures the key at\n // creation time — gates on the same key.\n const internalServiceKey = serviceKey || randomBytes(48).toString(\"base64\");\n if (!serviceKey) {\n logger.info(\"No REBASE_SERVICE_KEY configured. Generated internal per-boot key for singleton control-plane APIs.\");\n }\n\n // For user-provided AuthAdapters (the built-in one receives the key at\n // creation below): expose the internal key so the adapter and the\n // websocket auth path recognize the singleton's control-plane requests.\n if (authAdapter && !authAdapter.serviceKey) {\n authAdapter.serviceKey = internalServiceKey;\n }\n\n // ─── API Key Store Bootstrap ──────────────────────────────────────────\n // Bootstrapped before route mounting so `rk_` pre-auth can be registered\n // in front of every admin surface (Hono runs middleware in registration\n // order — a `use()` after `route()` would never fire for that router).\n let apiKeyStore: ApiKeyStore | undefined;\n const apiKeyStoreResult = createApiKeyStore(defaultDriver);\n if (apiKeyStoreResult) {\n apiKeyStore = apiKeyStoreResult;\n await apiKeyStore.ensureTable();\n logger.info(\"Service API Keys initialized\");\n }\n\n // Authenticates `rk_` bearer tokens in front of the JWT-based admin gates,\n // so keys created with `admin: true` genuinely reach the admin surfaces\n // (users, roles, api-keys, cron, backups, logs, schema editor) — their\n // documented behavior. Non-admin keys still fail `requireAdmin` with 403.\n const apiKeyPreAuth = apiKeyStore\n ? createApiKeyPreAuth({ store: apiKeyStore, driver: defaultDriver })\n : undefined;\n if (apiKeyPreAuth) {\n config.app.use(`${basePath}/admin/*`, apiKeyPreAuth);\n }\n\n if (apiKeyStore) {\n // Mount API key admin routes\n const apiKeyRoutes = createApiKeyRoutes({\n store: apiKeyStore,\n serviceKey: internalServiceKey\n });\n config.app.route(`${basePath}/admin/api-keys`, apiKeyRoutes);\n logger.info(\"API key admin routes mounted\", { path: `${basePath}/admin/api-keys` });\n }\n\n // One rate-limit store shared by the data and functions limiters: the\n // budget is per caller, not per router — two private stores would\n // silently double every caller's allowance. An operator-provided store\n // is respected as-is.\n const rateLimitConfig: DataRateLimitConfig | undefined =\n config.rateLimit?.enabled !== false\n ? {\n ...config.rateLimit,\n store: config.rateLimit?.store\n ?? new MemoryRateLimitStore(config.rateLimit?.windowMs ?? 15 * 60 * 1000)\n }\n : undefined;\n\n // 3. Initialize Storage\n const { storageRegistry, storageController } = await initializeStorage(config.storage, isProduction);\n\n // basePath already resolved above\n\n // 4. Mount API Routes\n if (config.auth) {\n // ── Auth Capabilities Endpoint ───────────────────────────────────\n // Exposes adapter capabilities so the frontend knows what's available\n // (login form vs external redirect, OAuth providers, etc.)\n config.app.get(`${basePath}/auth/config`, async (c) => {\n const capabilities = await authAdapter!.getCapabilities();\n return c.json(capabilities);\n });\n\n if (!isAuthAdapter(config.auth)) {\n const safeAuthConfig = config.auth as RebaseAuthConfig;\n const oauthProviders: OAuthProvider<unknown>[] = [...(safeAuthConfig.providers || [])];\n\n // Resolve configured OAuth providers via data-driven registration.\n // Each entry maps a config key to its factory function name and required fields.\n const OAUTH_PROVIDERS: Array<{\n key: keyof RebaseAuthConfig;\n factory: string;\n requiredFields: string[];\n }> = [\n { key: \"google\", factory: \"createGoogleProvider\", requiredFields: [\"clientId\"] },\n { key: \"linkedin\", factory: \"createLinkedinProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"github\", factory: \"createGitHubProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"microsoft\", factory: \"createMicrosoftProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"apple\", factory: \"createAppleProvider\", requiredFields: [\"clientId\", \"teamId\", \"keyId\", \"privateKey\"] },\n { key: \"facebook\", factory: \"createFacebookProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"twitter\", factory: \"createTwitterProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"discord\", factory: \"createDiscordProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"gitlab\", factory: \"createGitLabProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"bitbucket\", factory: \"createBitbucketProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"slack\", factory: \"createSlackProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"spotify\", factory: \"createSpotifyProvider\", requiredFields: [\"clientId\", \"clientSecret\"] }\n ];\n\n for (const { key, factory, requiredFields } of OAUTH_PROVIDERS) {\n const providerConfig = safeAuthConfig[key] as Record<string, unknown> | undefined;\n if (providerConfig && requiredFields.every(f => Boolean(providerConfig[f]))) {\n const authModule = await import(\"./auth\");\n const createFn = (authModule as unknown as Record<string, (cfg: unknown) => OAuthProvider<unknown>>)[factory];\n oauthProviders.push(createFn(providerConfig));\n }\n }\n\n // Re-create the built-in adapter with all resolved OAuth providers\n const reCollectionAuth = safeAuthConfig.collection ? safeAuthConfig.collection.auth : undefined;\n const collectionAuthConfig = (typeof reCollectionAuth === \"object\" && reCollectionAuth !== null) ? reCollectionAuth : undefined;\n authAdapter = createBuiltinAuthAdapter({\n authRepository: authConfigResult!.authRepository as import(\"./auth/interfaces\").AuthRepository ?? authConfigResult!.userService as import(\"./auth/interfaces\").AuthRepository,\n emailService: authConfigResult!.emailService as import(\"./email\").EmailService,\n emailConfig: safeAuthConfig.email,\n allowRegistration: safeAuthConfig.allowRegistration ?? false,\n disableSelfRegistration: safeAuthConfig.disableSelfRegistration ?? false,\n allowUserLookup: safeAuthConfig.allowUserLookup ?? false,\n defaultRole: safeAuthConfig.defaultRole,\n oauthProviders,\n // The internal per-boot fallback is included so the closure the\n // adapter's routes capture recognizes the singleton's own\n // control-plane requests even without a configured key.\n serviceKey: serviceKey || internalServiceKey,\n authHooks: safeAuthConfig.hooks,\n collectionAuthConfig,\n enableMagicLink: safeAuthConfig.magicLink ?? false,\n cookieAuth: safeAuthConfig.cookieAuth\n });\n\n if (safeAuthConfig.cookieAuth) {\n if (!isProduction && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) {\n logger.warn(\n \"[Auth] Cookie authentication (cookieAuth) is enabled, but no CORS restrictions are detected. \" +\n \"Browser-based clients will require credentials: 'include' and the server MUST NOT use \" +\n \"Access-Control-Allow-Origin: '*'. Ensure CORS_ORIGINS is set to your frontend URL.\"\n );\n }\n }\n }\n\n // ── Mount auth & admin routes via the adapter ────────────────────\n if (authAdapter && authAdapter.createAuthRoutes) {\n const authRoutes = authAdapter.createAuthRoutes();\n if (authRoutes) {\n config.app.route(`${basePath}/auth`, authRoutes);\n logger.info(\"Auth routes mounted via adapter\", { adapter: authAdapter.id });\n }\n }\n\n if (authAdapter && authAdapter.createAdminRoutes) {\n const adminRoutes = authAdapter.createAdminRoutes();\n if (adminRoutes) {\n config.app.route(`${basePath}/admin`, adminRoutes);\n logger.info(\"Admin routes mounted via adapter\", { adapter: authAdapter.id });\n }\n }\n }\n\n // ─── Shared gate for admin-only surfaces ──────────────────────────────\n // Cron, backups, logs, and the schema editor previously gated on the\n // plain JWT-only `requireAuth`, which silently rejected both the service\n // key and admin API keys while other admin surfaces accepted them. One\n // gate, same acceptance everywhere: `rk_` admin keys (via pre-auth), the\n // service key, and admin JWTs.\n // Whether admin surfaces get a gate at all — global for this boot, so\n // computed once rather than per router.\n //\n // Deliberately NOT conditioned on `requireAuth`. That flag answers a\n // question about the *data plane* — \"must a caller present a token to read\n // /api/data, or does RLS alone decide?\" — and `false` is the answer this\n // very file recommends to anyone serving a public website from their own\n // backend (see the `publicSelect` notice below). Reusing it here meant\n // taking that advice silently unmounted the gate on the cron trigger, the\n // log reader and the backup routes: one flag deciding two unrelated things,\n // where the harmless-looking value of one is catastrophic for the other.\n // Whether anonymous callers may read your posts has no bearing on whether\n // they may run your cron jobs. If auth exists at all, admin surfaces use it.\n const adminSurfacesGated = !!authAdapter && (\n isAuthAdapter(config.auth!) || !!(config.auth as RebaseAuthConfig).jwtSecret\n );\n const applyAdminGate = (router: Hono<HonoEnv>, surface: string): void => {\n if (!adminSurfacesGated) {\n // No adapter and no `jwtSecret`: there is no credential this server\n // could check a caller against, so it cannot tell an admin from the\n // internet. These surfaces used to mount anyway, open, with this\n // warning as their only defence — which is to say they served the\n // cron trigger and the log reader to anyone, and told nobody but\n // whoever was reading stdout at boot.\n //\n // They answer 501 instead, and stay mounted to say why: an\n // unexplained 404 on `/api/cron` reads as a broken path or a failed\n // deploy, and gets debugged as one.\n logger.warn(\n `${surface} routes are mounted but DISABLED: no authentication is configured ` +\n \"(no auth adapter and no auth.jwtSecret), so there is no way to tell an admin \" +\n \"from an anonymous caller. They answer 501 until auth is configured.\"\n );\n router.use(\"/*\", async (c) => c.json({\n error: {\n code: \"ADMIN_SURFACE_UNAVAILABLE\",\n message: `${surface} is admin-only, and this server has no authentication ` +\n \"configured to identify an admin with. Set auth.jwtSecret (or pass an \" +\n \"AuthAdapter) to enable it.\"\n }\n }, 501));\n return;\n }\n if (apiKeyPreAuth) router.use(\"/*\", apiKeyPreAuth);\n router.use(\"/*\", createRequireAuth({ serviceKey: internalServiceKey }), requireAdmin);\n };\n\n // The schema editor rewrites collection files, so it needs a collectionsDir\n // to write to and is off in baas mode (no files) and in production.\n const schemaEditorEnabled =\n config.schemaEditor ?? (!!config.collectionsDir && !introspectCollections && process.env.NODE_ENV !== \"production\");\n\n /**\n * Why the editor is off, in the words the person staring at a greyed-out\n * \"Add collection\" button needs.\n *\n * The admin panel used to decide whether collections were editable from\n * its *own* build mode — `process.env.NODE_ENV` inside the browser bundle.\n * That is a different process from the one that decides whether the routes\n * exist, and the two disagree constantly: a dev frontend against a\n * deployed API, a `baas`-mode project, a project with no `collectionsDir`,\n * a server without `ts-morph`. In every one of those the editor offered\n * itself and each save came back as a bare 404. So the server says whether\n * it can write, and says why not, and the client asks instead of guessing.\n */\n const schemaEditorUnavailable = (): { code: string, message: string } | undefined => {\n if (config.schemaEditor === false) return {\n code: \"SCHEMA_EDITOR_DISABLED\",\n message: \"The schema editor is turned off for this server (`schemaEditor: false`).\"\n };\n if (!config.collectionsDir) return {\n code: \"SCHEMA_EDITOR_NO_COLLECTIONS_DIR\",\n message: \"This server has no `collectionsDir`, so the schema editor has no collection files to write to.\"\n };\n if (schemaEditorEnabled) return undefined;\n if (introspectCollections) return {\n code: \"SCHEMA_EDITOR_BAAS_MODE\",\n message: \"Collections are introspected from the database on this server, so there are no \" +\n \"collection source files to edit. Change the schema with a migration instead.\"\n };\n if (process.env.NODE_ENV === \"production\") return {\n code: \"SCHEMA_EDITOR_PRODUCTION\",\n message: \"The schema editor is off under NODE_ENV=production: it edits collection source \" +\n \"files, and a deployed server's files are rebuilt from your repository on every \" +\n \"deploy, so an edit here would be discarded. Edit collections in development and deploy.\"\n };\n return {\n code: \"SCHEMA_EDITOR_DISABLED\",\n message: \"The schema editor is not enabled on this server.\"\n };\n };\n\n if (schemaEditorEnabled && !config.collectionsDir) {\n logger.warn(\"schemaEditor is enabled but no collectionsDir is set — the schema editor has nowhere to write. Skipping.\");\n }\n\n let schemaEditorOff = schemaEditorUnavailable();\n let schemaEditorRoutes: Hono<HonoEnv> | undefined;\n\n if (!schemaEditorOff && config.collectionsDir) {\n // ts-morph is an optional peer dependency, so it can legitimately be\n // absent — run without the schema editor instead of failing startup.\n try {\n const editorModule = await import(\"./api/schema-editor-routes\");\n schemaEditorRoutes = editorModule.createSchemaEditorRoutes(config.collectionsDir);\n } catch (err) {\n if ((err as { code?: string })?.code === \"ERR_MODULE_NOT_FOUND\") {\n schemaEditorOff = {\n code: \"SCHEMA_EDITOR_MISSING_DEPENDENCY\",\n message: \"The schema editor needs `ts-morph`, which is not installed on this server. \" +\n // `pnpm`, not `npm`: a Rebase project is a pnpm workspace, and\n // running npm inside one rewrites node_modules into a hoisted\n // layout that pnpm then disagrees with. Advice that damages the\n // project is worse than no advice — see docs/bug-classes.md §5.\n \"Run `pnpm add -D ts-morph@28.0.0` to enable it.\"\n };\n logger.warn(`Schema Editor disabled: ${schemaEditorOff.message}`);\n } else {\n throw err;\n }\n }\n }\n\n {\n // Gate a *fresh* router, then mount the routes into it. Hono collects\n // matching handlers in registration order, so a `use(\"/*\")` appended to\n // an already-populated router runs after the handler it was meant to\n // guard — which is to say never, because the handler has already\n // answered. Gating `createSchemaEditorRoutes()`'s return value did\n // exactly that, leaving `POST /api/schema-editor/collection/save`\n // reachable with no credentials at all: unauthenticated rewrites of the\n // project's collection source on any reachable dev server. Every other\n // admin surface here already builds the router, gates it, and *then*\n // routes into it; this one is now the same shape.\n const schemaEditorRouter = new Hono<HonoEnv>();\n\n applyAdminGate(schemaEditorRouter, \"Schema editor\");\n\n schemaEditorRouter.get(\"/status\", (c) => c.json(\n schemaEditorOff\n ? { enabled: false, reason: schemaEditorOff.message, code: schemaEditorOff.code }\n : { enabled: true }\n ));\n\n if (schemaEditorRoutes) {\n schemaEditorRouter.route(\"/\", schemaEditorRoutes);\n } else {\n // Mounted-but-refusing, like the other admin surfaces: an\n // unexplained 404 on a route the UI just called reads as a broken\n // deploy and gets debugged as one.\n schemaEditorRouter.all(\"/*\", (c) => c.json({\n error: {\n code: schemaEditorOff!.code,\n message: schemaEditorOff!.message\n }\n }, 501));\n }\n\n config.app.route(`${basePath}/schema-editor`, schemaEditorRouter);\n if (schemaEditorRoutes) {\n logger.info(\"Schema Editor mounted\", { path: `${basePath}/schema-editor` });\n } else {\n logger.debug(\"Schema Editor unavailable\", {\n path: `${basePath}/schema-editor`,\n code: schemaEditorOff!.code\n });\n }\n }\n\n // Filled in once the native data plane exists (below). The storage\n // authorize hook needs trusted reads to answer \"who owns this object?\", and\n // it cannot import the server itself — it is declared in the project's\n // config package, which depends on `@rebasepro/types` alone.\n const storageAuthorizeData: { current?: import(\"@rebasepro/types\").StorageAuthorizeData } = {};\n\n if (storageController) {\n // Storage uploads get their own body limit, derived from the storage config's\n // maxFileSize (default 50MB), which overrides the global API body limit.\n const storageMaxSize = (\n config.storage && typeof config.storage === \"object\" && \"type\" in config.storage\n ? (config.storage as BackendStorageConfig).maxFileSize\n : undefined\n ) ?? 50 * 1024 * 1024;\n\n // Storage is not under RLS and its keys share one flat namespace, so an\n // allow-all default is a cross-user read/write/delete hole. Refuse to\n // boot in production unless the deployment has stated an access-control\n // intent (a hook, public-read, or the explicit insecure opt-out); warn\n // loudly in development.\n assertStorageAccessControlConfigured(\n {\n hasAuthorize: !!config.storageAuthorize,\n publicRead: config.storagePublicRead === true,\n allowAnyAuthenticated: config.storageInsecureAllowAnyAuthenticated === true\n },\n isProduction\n );\n\n const storageRoutes = createStorageRoutes({\n controller: storageController,\n registry: storageRegistry,\n sources: config.storageSources,\n requireAuth: resolveRequireAuth(config.auth),\n publicRead: config.storagePublicRead === true,\n authAdapter,\n authorize: config.storageAuthorize,\n // Resolved lazily: the admin data plane is built further down, well\n // after these routes are mounted, but always before a request runs.\n authorizeData: () => storageAuthorizeData.current\n });\n\n // Wrapper router: middleware must be registered BEFORE the routes it\n // guards — Hono composes handlers in registration order, so a `use()`\n // issued after `createStorageRoutes()` has registered its handlers\n // sits deeper than them and never runs. The previous\n // `storageRoutes.use(\"/upload\", bodyLimit)` was exactly that: dead\n // code, leaving uploads without any size cap.\n const storageRouter = new Hono<HonoEnv>();\n\n // API keys on storage: authenticate `rk_` tokens, then require a\n // \"storage\" (or \"*\") permission entry for the derived operation.\n if (apiKeyPreAuth) {\n storageRouter.use(\"/*\", apiKeyPreAuth, createStorageApiKeyGuard());\n }\n\n // Apply a permissive body limit specifically for the upload endpoint\n storageRouter.use(\"/upload\", bodyLimit({\n maxSize: storageMaxSize,\n onError: (c) => {\n return c.json({\n error: {\n message: `File too large. Maximum upload size is ${Math.round(storageMaxSize / 1024 / 1024)}MB.`,\n code: \"PAYLOAD_TOO_LARGE\"\n }\n }, 413);\n }\n }));\n\n storageRouter.route(\"/\", storageRoutes);\n config.app.route(`${basePath}/storage`, storageRouter);\n } else {\n // No storage backend: say so, instead of 404ing as if the route were a\n // typo. A bare 404 reads as \"wrong URL\" and sends people debugging\n // their client; this names the actual state of the deployment.\n //\n // 501, not 503: this is permanent until someone configures a bucket,\n // and the client's offline queue retries 503 forever (see\n // RETRYABLE_STATUSES in @rebasepro/client), which would silently pile\n // up uploads that can never land.\n const storageStub = new Hono<HonoEnv>();\n storageStub.all(\"/*\", (c) => c.json({\n error: {\n message: \"File storage is not configured on this deployment, so uploads and \" +\n \"downloads are disabled. Configure a storage backend (STORAGE_TYPE=s3 or \" +\n \"STORAGE_TYPE=gcs plus its bucket and credentials) and redeploy.\",\n code: \"STORAGE_NOT_CONFIGURED\"\n }\n }, 501));\n config.app.route(`${basePath}/storage`, storageStub);\n logger.info(\"Storage not configured — /storage returns 501 STORAGE_NOT_CONFIGURED\");\n }\n\n if (activeCollections.length > 0) {\n const dataRouter = new Hono<HonoEnv>();\n dataRouter.onError(errorHandler);\n\n // Secure by default: require auth when auth is configured.\n // Developers who intentionally want public data access (relying\n // entirely on Postgres RLS) must explicitly set `auth.requireAuth: false`.\n const dataRequireAuth = resolveRequireAuth(config.auth);\n\n if (!dataRequireAuth) {\n logger.warn(\n \"Data routes running WITHOUT authentication enforcement. \" +\n \"Access control is fully delegated to Postgres RLS policies. \" +\n \"If no RLS policies exist, data is publicly accessible. \" +\n \"Set auth.requireAuth to true (or remove it) to require authentication.\"\n );\n } else {\n // The other half of the same decision, and the one nobody sees.\n //\n // `{ operation: \"select\", access: \"public\" }` means \"no row filter\",\n // not \"no login\" — the API gate still answers 401 to a caller with no\n // token, whatever RLS would have allowed. Read on its own, a 401 from\n // a collection the author called public looks like broken RLS or a\n // missing table, and gets debugged as one (it has been). Say it once\n // at boot, where the operator is already reading, naming the switch.\n const publicSelect = activeCollections\n .filter(c => getEffectiveSecurityRules(c).some(rule =>\n \"access\" in rule && rule.access === \"public\" &&\n (rule.operation === \"select\" || rule.operation === \"all\" ||\n (Array.isArray(rule.operations) && rule.operations.includes(\"select\")))\n ))\n .map(c => c.slug);\n\n if (publicSelect.length > 0) {\n logger.info(\n `${publicSelect.length} collection(s) grant unfiltered reads (${publicSelect.join(\", \")}), ` +\n \"but every /api/data route still requires a token: `access: \\\"public\\\"` widens which ROWS a \" +\n \"caller sees, not who may call. An unauthenticated read answers 401 regardless. \" +\n \"To let RLS alone decide — the usual choice for a public website reading its own backend — \" +\n \"set AUTH_REQUIRE=false (or `auth.requireAuth: false`).\"\n );\n }\n }\n\n // Multi-data-source routing: when more than one database engine is\n // registered (e.g. Postgres + MongoDB in one instance), resolve the\n // delegate per request from the request's collection data source. The\n // auth middleware then scopes that delegate (RLS for Postgres, no-op\n // for engines without `withAuth()`) into the request context. For a\n // single-engine backend this is omitted — behaviour is unchanged.\n const dataPathMarker = `${basePath}/data/`;\n const resolveRequestDriver = (reqPath: string): DataDriver => {\n const i = reqPath.indexOf(dataPathMarker);\n const collectionPath = i >= 0 ? reqPath.slice(i + dataPathMarker.length) : reqPath;\n const key = keyForCollectionPath(collectionPath);\n // Use the authoritative default for the default key; otherwise the\n // named delegate, falling back to default if it isn't registered.\n if (!key || key === DEFAULT_DRIVER_ID) return defaultDriver;\n return driverRegistry.get(key) ?? defaultDriver;\n };\n const multiEngine = bootstrappers.length > 1;\n const resolveDriver = multiEngine ? ((c: { req: { path: string } }) => resolveRequestDriver(c.req.path)) : undefined;\n\n // Use adapter middleware when an AuthAdapter is available,\n // falling back to the built-in JWT middleware otherwise.\n if (authAdapter) {\n dataRouter.use(\"/*\", createAdapterAuthMiddleware({\n adapter: authAdapter,\n driver: defaultDriver,\n resolveDriver,\n requireAuth: dataRequireAuth,\n apiKeyStore\n }));\n } else {\n dataRouter.use(\"/*\", createAuthMiddleware({\n driver: defaultDriver,\n resolveDriver,\n requireAuth: dataRequireAuth,\n serviceKey: internalServiceKey,\n apiKeyStore\n }));\n }\n\n // Rate limiting, per caller: API key, else signed-in user, else IP.\n // Not gated on `apiKeyStore` any more — that made the limiter's\n // presence depend on a feature it does not need, so a deployment\n // without API keys had no limit at all on its data API.\n if (rateLimitConfig) {\n dataRouter.use(\"/*\", createDataRateLimiter(rateLimitConfig));\n }\n\n // Mount history routes BEFORE the REST API subcollection catch-all so\n // that /:slug/:id/history is matched by the dedicated handler first.\n if (historyConfigResult && historyConfigResult.historyService) {\n const historyRoutes = createHistoryRoutes({\n historyService: historyConfigResult.historyService,\n registry: collectionRegistry,\n driver: defaultDriver\n });\n dataRouter.route(\"/\", historyRoutes);\n }\n\n // Only generate server data routes for server-mediated collections.\n // Collections on a direct/custom transport are client-only — the\n // backend must not expose a (mis-engined) endpoint for them.\n const serverCollections = activeCollections.filter(\n (collection) => resolveDataSource(collection, dataSourceRegistry).transport === \"server\"\n );\n\n const restGenerator = new RestApiGenerator(\n serverCollections,\n defaultDriver,\n authAdapter\n );\n dataRouter.route(\"/\", restGenerator.generateRoutes());\n\n config.app.route(`${basePath}/data`, dataRouter);\n }\n\n // ── OpenAPI / Swagger ─────────────────────────────────────────────────\n await mountOpenApiDocs(config.app, basePath, config.enableSwagger, activeCollections, resolveRequireAuth(config.auth));\n\n // ─── Server-side singleton ────────────────────────────────────────────\n // Build the RebaseClient for control-plane APIs (auth, admin, storage,\n // functions, cron). These still route through the Hono app because they\n // genuinely need route dispatch + middleware.\n // `rebase.data` is replaced below with a native driver-backed data plane.\n const serverClient = createRebaseClient({\n baseUrl: \"http://localhost\",\n apiPath: basePath,\n websocketUrl: \"\",\n token: internalServiceKey,\n fetch: async (input: RequestInfo | URL, init?: RequestInit) => {\n return await config.app.request(input as string | Request | URL, init);\n }\n });\n\n // ─── Native data plane ────────────────────────────────────────────────\n // Replace the HTTP-transport data layer with a driver-backed RebaseData.\n // This eliminates JSON serialize → Hono dispatch → auth → deserialize for\n // every rebase.data call. RLS semantics are preserved: the driver is scoped\n // once as { uid: \"service\", roles: [\"admin\"] }, matching the identity the\n // service-key HTTP path produced.\n const serviceIdentity = { uid: \"service\", roles: [\"admin\"] as string[] };\n\n const scopedDefaultDriver = await scopeDataDriver(defaultDriver, serviceIdentity);\n const defaultData = buildSdkData(scopedDefaultDriver);\n\n // Hand the storage authorize hook its trusted reader. Scoped as the service\n // identity, so an ownership lookup is not itself filtered by the caller's\n // permissions — the hook IS the permission decision.\n storageAuthorizeData.current = defaultData as unknown as import(\"@rebasepro/types\").StorageAuthorizeData;\n\n // Multi-engine: scope and wrap each non-default delegate so\n // rebase.data on a non-default-engine collection reaches the correct driver.\n const dataSourcesByKey: Record<string, import(\"@rebasepro/types\").RebaseSdkData> = {};\n for (const driverKey of driverRegistry.list()) {\n if (driverKey === DEFAULT_DRIVER_ID) continue;\n const delegate = driverRegistry.get(driverKey);\n if (!delegate) continue;\n const scopedDelegate = await scopeDataDriver(delegate, serviceIdentity);\n dataSourcesByKey[driverKey] = buildSdkData(scopedDelegate);\n }\n\n const serverData = buildRoutedRebaseData({\n defaultData,\n sources: dataSourcesByKey,\n resolveKey: (slugOrPath: string) => keyForCollectionPath(slugOrPath)\n });\n\n // Overwrite the HTTP-transport data proxy with the native driver-backed one.\n // The rest of the client (auth, admin, cron, functions, storage) keeps using\n // the HTTP transport, which is fine — they are low-frequency control-plane ops.\n //\n // `dataAsAdmin` is the admin accessor, and the only one `RebaseServerClient`\n // declares — `data` is `Omit`ted from the type so the privilege has to be\n // named at the call site.\n //\n // It is still assigned here on purpose. `createRebaseClient` above already\n // put an HTTP-transport `data` on this object, so *not* overwriting it would\n // leave `rebase.data` working in plain JS while quietly routing through the\n // loop this native plane exists to skip — a silent performance and identity\n // change instead of the compile error TypeScript now gives. Both names point\n // at the same admin-scoped, RLS-bypassing object.\n Object.assign(serverClient, { data: serverData, dataAsAdmin: serverData });\n logger.info(\"Native data plane attached to singleton (bypasses HTTP loop)\");\n\n // Same treatment for storage: server-side `rebase.storage` must talk to the\n // controller directly, not loop back through `POST /api/storage/upload`. The\n // loopback carried the service key but still 403'd (the storage route's auth\n // is written for real user/session requests, not the internal self-call), so\n // every backend-initiated write — e.g. the deploy build-context upload —\n // failed at ~2ms with \"Request failed with status 403\". The controller\n // exposes the same StorageSource surface (putObject/getObject/…).\n if (storageController) {\n Object.assign(serverClient, { storage: storageController });\n logger.info(\"Native storage attached to singleton (bypasses HTTP loop)\");\n }\n\n // Attach email service to the server client when configured.\n // The email service may come from the auth bootstrapper or from the auth config directly.\n let emailService: EmailService | undefined;\n if (authConfigResult?.emailService) {\n emailService = authConfigResult.emailService as EmailService;\n } else if (config.auth && !isAuthAdapter(config.auth) && (config.auth as RebaseAuthConfig).email) {\n emailService = createEmailService((config.auth as RebaseAuthConfig).email!);\n }\n\n if (emailService) {\n Object.assign(serverClient, { email: emailService });\n logger.info(\"Email service attached to singleton\", { configured: emailService.isConfigured() });\n\n if (emailService.isConfigured() && typeof emailService.verifyConnection === \"function\") {\n emailService.verifyConnection().then((success) => {\n if (!success) {\n logger.warn(\"Warning: SMTP connection verification failed. Email delivery may fail.\");\n } else {\n logger.info(\"SMTP connection verified successfully.\");\n }\n }).catch((err) => {\n logger.warn(\"Warning: SMTP connection verification failed. Email delivery may fail.\", { error: err });\n });\n }\n }\n\n // Attach raw SQL capability when the driver supports it (Postgres, MySQL).\n // Document databases (MongoDB, Firestore) won't have this.\n const driverAdmin = defaultBootstrapper.getAdmin?.(defaultDriverResult);\n if (isSQLAdmin(driverAdmin)) {\n Object.assign(serverClient, {\n sql: (query: string, options?: { database?: string; role?: string; params?: unknown[] }) =>\n driverAdmin.executeSql(query, options)\n });\n logger.info(\"SQL capability attached to singleton\");\n }\n\n // The server client is assembled dynamically above (native data plane,\n // dataAsAdmin, email, sql attached via Object.assign), so TS can't see the\n // full RebaseServerClient shape statically — cast at the boundary.\n _initRebase(serverClient as unknown as import(\"@rebasepro/types\").RebaseServerClient);\n logger.info(\"Rebase singleton initialized\");\n\n // Retroactively inject the server client into the driver so that\n // entity callbacks receive `context.client` at runtime.\n // The driver is created before the client (which depends on the mounted\n // Hono app), so we set it here, mirroring the historyService injection above.\n if (defaultDriverResult.internals) {\n const internals = defaultDriverResult.internals as Record<string, unknown>;\n const driver = internals.driver as Record<string, unknown> | undefined;\n if (driver && \"client\" in driver) {\n driver.client = serverClient;\n }\n }\n\n // 5. Mount Custom Functions\n if (config.functionsDir) {\n const { loadFunctionsFromDirectory } = await import(\"./functions/function-loader\");\n const { createFunctionRoutes } = await import(\"./functions/function-routes\");\n\n const loadedFunctions = await loadFunctionsFromDirectory(config.functionsDir);\n\n if (loadedFunctions.length > 0) {\n const functionsRouter = new Hono<HonoEnv>();\n functionsRouter.onError(errorHandler);\n\n // Custom functions do NOT require authentication at the global level by default.\n // This allows custom functions to define public endpoints (like webhooks).\n // Per-route auth can be further refined inside individual functions using `requireAuth`.\n const functionsRequireAuth = false;\n\n // Use adapter middleware when available, fallback to built-in\n if (authAdapter) {\n functionsRouter.use(\"/*\", createAdapterAuthMiddleware({\n adapter: authAdapter,\n driver: defaultDriver,\n requireAuth: functionsRequireAuth,\n apiKeyStore\n }));\n } else {\n functionsRouter.use(\"/*\", createAuthMiddleware({\n driver: defaultDriver,\n requireAuth: functionsRequireAuth,\n serviceKey: internalServiceKey,\n apiKeyStore\n }));\n }\n\n // API-key requests must hold a \"functions\"/\"functions/<name>\"\n // permission (or the \"*\" wildcard). Without this, any valid key —\n // however narrowly scoped — could invoke every custom function.\n functionsRouter.use(\"/*\", createFunctionApiKeyGuard(`${basePath}/functions`));\n\n // Same per-caller rate limiting as the data API, sharing its\n // store so one caller has one budget. Previously only /api/data\n // was limited, so a key's rate_limit did not bound its function\n // traffic at all.\n //\n // The anonymous bucket is disabled here: functions default to\n // public access precisely for webhook receivers (Stripe, GitHub),\n // whose bursts come from a handful of provider IPs — an IP-keyed\n // 300/window cap would 429 them. Anonymous function traffic was\n // never limited before; keys and signed-in users now are.\n if (rateLimitConfig) {\n functionsRouter.use(\"/*\", createDataRateLimiter({ ...rateLimitConfig, anonymous: null }));\n }\n\n const fnRoutes = createFunctionRoutes(loadedFunctions);\n functionsRouter.route(\"/\", fnRoutes);\n config.app.route(`${basePath}/functions`, functionsRouter);\n logger.info(\"Mounted custom functions\", {\n count: loadedFunctions.length,\n path: `${basePath}/functions`\n });\n }\n }\n\n // 6. Mount Cron Jobs\n let cronScheduler: import(\"./cron\").CronScheduler | undefined;\n if (config.cronsDir) {\n const { loadCronJobsFromDirectory } = await import(\"./cron/cron-loader\");\n const { CronScheduler } = await import(\"./cron/cron-scheduler\");\n const { createCronRoutes } = await import(\"./cron/cron-routes\");\n const { createCronStore } = await import(\"./cron/cron-store\");\n\n const loadedCronJobs = await loadCronJobsFromDirectory(config.cronsDir);\n\n cronScheduler = new CronScheduler();\n\n // The cron scheduler uses the same serverClient as the singleton.\n // ctx.client inside cron handlers IS the same `rebase` instance.\n cronScheduler.setClient(serverClient);\n\n if (loadedCronJobs.length > 0) {\n cronScheduler.registerJobs(loadedCronJobs);\n\n // Attach database persistence if the driver supports SQL and persistence is enabled\n const admin = defaultBootstrapper.getAdmin?.(defaultDriverResult);\n const store = (admin && config.cronPersistence !== false) ? createCronStore(defaultDriver) : undefined;\n if (store) {\n await store.ensureTable();\n cronScheduler.setStore(store);\n }\n }\n\n // Mounted for the directory, not for the jobs in it. Mounting only when\n // something loaded meant a single unparseable file — a syntax error, an\n // import that throws, a module the loader could not read — took the\n // whole cron surface with it: `/api/cron` 404ed, the Studio panel broke,\n // and the only trace was one line in the boot log. An empty list is the\n // honest answer, and it is a debuggable one.\n const cronRouter = new Hono<HonoEnv>();\n\n // Cron admin routes require authentication + admin role\n applyAdminGate(cronRouter, \"Cron\");\n\n cronRouter.route(\"/\", createCronRoutes(cronScheduler));\n config.app.route(`${basePath}/cron`, cronRouter);\n\n if (loadedCronJobs.length > 0) {\n cronScheduler.start();\n logger.info(\"Mounted cron jobs\", {\n count: loadedCronJobs.length,\n path: `${basePath}/cron`\n });\n } else {\n logger.warn(\n `Cron routes mounted at ${basePath}/cron, but no jobs loaded from ${config.cronsDir}. ` +\n \"Nothing is scheduled — check the messages above for files that failed to load.\"\n );\n }\n }\n\n // 6b. Mount Backup admin routes (for the Studio Backups panel).\n // Read the destination lazily from env so config changes don't need a\n // rebuild. Only enabled when BACKUP_DESTINATION is set.\n {\n const { createBackupRoutes, parseBackupDestination } = await import(\"./backup\");\n const backupRouter = new Hono<HonoEnv>();\n\n applyAdminGate(backupRouter, \"Backup\");\n\n backupRouter.route(\"/\", createBackupRoutes({\n getDestination: () => {\n const out = process.env.BACKUP_DESTINATION?.trim();\n return out ? parseBackupDestination(out) : null;\n },\n storage: storageController\n }));\n config.app.route(`${basePath}/admin/backups`, backupRouter);\n logger.info(\"Backup admin routes mounted\", { path: `${basePath}/admin/backups` });\n }\n\n // 6c. Mount Logs routes (for the Studio Logs Explorer). Request logs expose\n // paths, status codes and correlation IDs, so they are admin-only — the same\n // posture as the cron and backup admin routes above.\n {\n const { default: logsRoutes } = await import(\"./api/logs-routes\");\n const logsRouter = new Hono<HonoEnv>();\n\n applyAdminGate(logsRouter, \"Logs\");\n\n logsRouter.route(\"/\", logsRoutes);\n config.app.route(`${basePath}/logs`, logsRouter);\n logger.info(\"Logs routes mounted\", { path: `${basePath}/logs` });\n }\n\n // 6d. Mount the project contract — what lets a repository that does *not*\n // contain the collections still generate a typed client against them. This\n // is the backbone of frontends, second web apps and mobile apps living in\n // their own repositories.\n //\n // Mounted here rather than by the bundle runtime so a project with a\n // hand-written entrypoint gets it too: ejecting should cost you the stock\n // runtime, not the API surface.\n {\n const { createContractRoutes } = await import(\"./api/contract-routes\");\n const contractRouter = new Hono<HonoEnv>();\n\n // Only `/contract` is gated: it is a full map of the schema, including\n // tables no security rule would ever expose. Its sibling\n // `/schema-version` returns a bare version string that stands for the\n // schema without describing it, and is deliberately reachable by a CI\n // job holding no credentials.\n //\n // With no way to gate it, `/contract` is not served at all — the same\n // answer `applyAdminGate` gives the other admin surfaces, which refuse\n // rather than open when there is no credential to check. It differs only\n // in status: this one is 404 because it is not an operation someone\n // tried to perform, it is a document that is not there. Configure auth\n // and it returns.\n if (adminSurfacesGated) {\n if (apiKeyPreAuth) contractRouter.use(\"/contract\", apiKeyPreAuth);\n contractRouter.use(\n \"/contract\",\n createRequireAuth({ serviceKey: internalServiceKey }),\n requireAdmin\n );\n } else {\n contractRouter.all(\"/contract\", (c) => c.json({\n error: {\n code: \"CONTRACT_UNAVAILABLE\",\n message: \"The project contract is only served when authentication is configured, \" +\n \"because it describes every table and relation in the project.\"\n }\n }, 404));\n logger.warn(\n \"Contract endpoint disabled: no auth is configured (no adapter or no jwtSecret), \" +\n \"and it would otherwise expose the full collection schema to anyone. \" +\n \"`/api/meta/schema-version` is still served.\"\n );\n }\n\n contractRouter.route(\"/\", createContractRoutes({\n collectionRegistry,\n schemaVersion: config.schemaVersion,\n runtimeVersion: config.runtimeVersion\n }));\n\n config.app.route(`${basePath}/meta`, contractRouter);\n logger.info(\"Contract routes mounted\", { path: `${basePath}/meta` });\n }\n\n // With multiple realtime-capable engines, route subscriptions to the\n // provider owning each collection (the realtime counterpart of the data\n // router). The single WebSocket server is driven by this composite.\n // Single-engine setups use the default provider unchanged.\n const effectiveRealtimeService: RealtimeProvider = Object.keys(realtimeServices).length > 1\n ? createRoutedRealtimeService({\n providers: realtimeServices,\n defaultKey: defaultDriverId,\n resolveKey: keyForCollectionPath\n })\n : defaultRealtimeService as RealtimeProvider;\n\n if (defaultBootstrapper.initializeWebsockets && effectiveRealtimeService) {\n await defaultBootstrapper.initializeWebsockets(config.server, effectiveRealtimeService, defaultDriver, config.auth, authAdapter);\n }\n\n logger.info(\"Rebase Backend Initialized\");\n\n // ── Deep Health Check ─────────────────────────────────────────────────\n // The auth probe is only available when a driver bootstrapped auth — an\n // AuthAdapter or a deployment without auth leaves it undefined, and the\n // health check falls back to the database probe alone.\n const authSchemaCheck = authConfigResult?.schemaHealthCheck;\n const healthCheck = createHealthCheck(\n defaultDriver,\n authSchemaCheck ? () => authSchemaCheck.call(authConfigResult) : undefined\n );\n\n // ── Graceful Shutdown ─────────────────────────────────────────────────\n const shutdown = createShutdown({\n server: config.server,\n cronScheduler,\n realtimeServices\n });\n\n /**\n * Every registry a driver might resolve callbacks from, plus the backend's\n * own. Each holds its own normalized copy of a collection, so callbacks have\n * to be written to all of them.\n */\n const callbackTargets = (): Array<{ get(slug: string): unknown }> => {\n const targets: Array<{ get(slug: string): unknown }> = [collectionRegistry];\n for (const key of [DEFAULT_DRIVER_ID, ...driverRegistry.list()]) {\n const d = driverRegistry.get(key) as unknown as { registry?: { get(slug: string): unknown } };\n if (d?.registry && typeof d.registry.get === \"function\" && !targets.includes(d.registry)) {\n targets.push(d.registry);\n }\n }\n return targets;\n };\n\n const setCollectionCallbacks = (\n slug: string,\n callbacks: import(\"@rebasepro/types\").CollectionCallbacks\n ): void => {\n let attached = 0;\n for (const registry of callbackTargets()) {\n const collection = registry.get(slug) as { callbacks?: unknown } | undefined;\n if (collection) {\n collection.callbacks = callbacks;\n attached++;\n }\n }\n if (attached === 0) {\n logger.warn(`[callbacks] Collection \"${slug}\" not found in any registry — callbacks not attached.`);\n }\n };\n\n return {\n driverRegistry,\n driver: defaultDriver,\n setCollectionCallbacks,\n realtimeServices,\n realtimeService: effectiveRealtimeService,\n auth: authConfigResult,\n history: historyConfigResult,\n storageRegistry,\n storageController,\n collectionRegistry,\n cronScheduler,\n healthCheck,\n shutdown\n };\n}\n","import { Hono } from \"hono\";\nimport type { RebaseServerClient } from \"@rebasepro/types\";\nimport type { HonoEnv } from \"../api/types\";\nimport { rebase } from \"../singleton\";\n\n/**\n * Typed context injected into a function authored with {@link defineFunction}.\n *\n * Surfaces the app-scoped Rebase singleton so handlers don't need to reach\n * for the global `rebase` import. Request-scoped values (the authenticated\n * `user`, the RLS-scoped `driver`, the `apiKey`, the `requestId`) are typed\n * on the Hono context via {@link HonoEnv} — read them with `c.get(\"user\")`\n * / `c.var.driver` inside a handler.\n */\nexport interface RebaseFunctionContext {\n /**\n * The server-side Rebase singleton (`dataAsAdmin`, `auth`, `storage`,\n * `email`, `sql`).\n *\n * `rebase.dataAsAdmin` runs with **admin privileges and bypasses RLS** — use\n * it only for trusted admin work. For user-scoped queries inside a handler,\n * use the request `driver` (`c.var.driver`), which carries the caller's\n * identity so RLS applies. (`rebase.data` no longer exists on this type —\n * `dataAsAdmin` is the only name for the admin-scoped accessor.)\n */\n rebase: RebaseServerClient;\n}\n\n/**\n * Typed authoring contract for a custom backend function.\n *\n * A custom function is a file in the `functionsDir` that default-exports a\n * Hono app; the loader mounts it at `/<filename>`. `defineFunction` is the\n * typed opt-in for that contract: it hands you a pre-typed `Hono<HonoEnv>`\n * app (so `c.var.user` / `c.var.driver` are typed) plus a\n * {@link RebaseFunctionContext}, and returns exactly the Hono app the loader\n * already accepts — so it is fully interchangeable with a plain\n * `export default new Hono()`.\n *\n * @example\n * ```ts\n * import { defineFunction, requireAuth } from \"@rebasepro/server\";\n *\n * export default defineFunction((app, { rebase }) => {\n * app.use(\"/*\", requireAuth);\n * app.get(\"/home\", async (c) => {\n * const [stats] = await rebase.sql!(`SELECT count(*) AS n FROM orders`);\n * return c.json({ orders: Number(stats.n) });\n * });\n * });\n * ```\n *\n * @param definition Receives the function's Hono app and the typed context.\n * Register routes on the provided `app` and return nothing, or return your\n * own `Hono<HonoEnv>` app to use instead.\n * @returns The Hono app to default-export from the function file.\n */\nexport function defineFunction(\n definition: (app: Hono<HonoEnv>, ctx: RebaseFunctionContext) => void | Hono<HonoEnv>\n): Hono<HonoEnv> {\n const app = new Hono<HonoEnv>();\n const returned = definition(app, { rebase });\n return returned instanceof Hono ? returned : app;\n}\n","import type { CronJobDefinition } from \"@rebasepro/types\";\n\n/**\n * Typed authoring helper for a cron job file. Identity at runtime —\n * a plain default-exported {@link CronJobDefinition} works identically;\n * this adds type inference and autocomplete.\n *\n * @see {@link defineFunction} for the equivalent custom-functions helper.\n *\n * @example\n * ```ts\n * import { defineCron } from \"@rebasepro/server\";\n *\n * export default defineCron({\n * name: \"Nightly cleanup\",\n * schedule: \"0 3 * * *\",\n * async handler({ client, log }) {\n * const { data: expired } = await client.data.sessions.find({\n * where: { expired: [\"==\", true] },\n * });\n * for (const session of expired) {\n * await client.data.sessions.delete(session.id);\n * }\n * log(`Deleted ${expired.length} expired sessions`);\n * },\n * });\n * ```\n */\nexport function defineCron(definition: CronJobDefinition): CronJobDefinition {\n return definition;\n}\n","import { sql, SQL } from \"drizzle-orm\";\n\n/**\n * Returns a SQL chunk calling `auth.uid()` — the current user's ID.\n * This is a PostgreSQL RLS helper function created in the `auth` schema\n * that reads `app.uid` set per-transaction by `withAuth()`.\n *\n * @example\n * sql`${table.uid} = ${authUid()}`\n */\nexport const authUid = (): SQL => {\n return sql`auth.uid()`;\n};\n\n/**\n * Returns a SQL chunk calling `auth.roles()` — the current user's roles\n * as a comma-separated string.\n * Reads `app.user_roles` set per-transaction by `withAuth()`.\n *\n * @example\n * sql`auth.roles() ~ 'admin'`\n */\nexport const authRoles = (): SQL => {\n return sql`auth.roles()`;\n};\n\n/**\n * Returns a SQL chunk calling `auth.jwt()` — the full JWT claims as JSONB.\n * Reads `app.jwt` set per-transaction by `withAuth()`.\n *\n * @example\n * sql`auth.jwt()->>'sub'`\n */\nexport const authJwt = (): SQL => {\n return sql`auth.jwt()`;\n};\n\n\n","import { z } from \"zod\";\nimport * as crypto from \"crypto\";\nimport { logger } from \"./utils/logger\";\n\n/**\n * Generate a cryptographically secure random secret (hex-encoded).\n * Used as a fallback when secrets are not explicitly configured —\n * avoids the need for hardcoded dev secrets.\n */\nfunction generateSecret(bytes = 48): string {\n return crypto.randomBytes(bytes).toString(\"hex\");\n}\n\n/**\n * Zod coercion helper: transforms `\"true\"` → `true`, everything else → `false`.\n */\nconst boolString = z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\");\n\n/**\n * Zod coercion helper for optional boolean strings.\n */\nconst optionalBoolString = z.enum([\"true\", \"false\", \"\"]).optional().transform(v => v === \"true\");\n\n/**\n * Helper to determine if a string is a localhost or loopback address/URL.\n */\nfunction isLocalhostOrLoopback(value: string): boolean {\n const trimmed = value.trim();\n if (!trimmed) return false;\n\n // 1. Try parsing as URL\n try {\n const parsed = new URL(trimmed);\n const host = parsed.hostname.toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host.startsWith(\"127.\")\n ) {\n return true;\n }\n } catch {\n // Not a standard URL, or custom protocol that URL class fails to parse\n }\n\n // 2. Custom protocol parser fallback (e.g. postgres://, mongodb://, etc.)\n const protocolMatch = trimmed.match(/^[a-zA-Z0-9+-.]+:\\/\\/(?:[^@/]+@)?(?:\\[([^\\]]+)\\]|([^:/]+))/);\n if (protocolMatch) {\n const host = (protocolMatch[1] || protocolMatch[2] || \"\").toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host.startsWith(\"127.\")\n ) {\n return true;\n }\n }\n\n // 3. Plain hostname / host:port checker (e.g. \"localhost\", \"127.0.0.1:5432\", \"[::1]:6379\")\n let plainHost = trimmed.toLowerCase();\n if (plainHost.startsWith(\"[\") && plainHost.includes(\"]\")) {\n const endBracket = plainHost.indexOf(\"]\");\n plainHost = plainHost.slice(1, endBracket);\n } else {\n const colonIndex = plainHost.lastIndexOf(\":\");\n if (colonIndex !== -1 && plainHost.indexOf(\":\") === colonIndex) {\n plainHost = plainHost.substring(0, colonIndex);\n }\n }\n\n if (\n plainHost === \"localhost\" ||\n plainHost === \"127.0.0.1\" ||\n plainHost === \"::1\" ||\n plainHost.startsWith(\"127.\")\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * The full set of environment variables recognized by a Rebase backend.\n */\nconst rebaseEnvSchema = z.object({\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n PORT: z.string().default(\"3001\").transform(Number),\n DATABASE_URL: z.string().url(\"DATABASE_URL must be a valid URL\"),\n ADMIN_CONNECTION_STRING: z.string().url().optional(),\n JWT_SECRET: z.string().min(32, \"JWT_SECRET must be at least 32 characters long\"),\n JWT_ACCESS_EXPIRES_IN: z.string().default(\"1h\"),\n // Sliding: every rotation re-ups it, so this governs how long a session\n // survives INACTIVITY, not how long it survives. 400d is the ceiling any\n // browser will honour on the cookie that carries it.\n JWT_REFRESH_EXPIRES_IN: z.string().default(\"400d\"),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n REBASE_SERVICE_KEY: z.string().optional(),\n ALLOW_REGISTRATION: boolString,\n // The kill switch, which also closes the empty-database bootstrap window\n // that ALLOW_REGISTRATION=false deliberately leaves open. Optional so an\n // unset variable means \"not configured\" rather than an explicit false.\n DISABLE_SELF_REGISTRATION: optionalBoolString,\n ALLOW_LOCALHOST_IN_PRODUCTION: optionalBoolString,\n CORS_ORIGINS: z.string().optional(),\n FRONTEND_URL: z.string().optional(),\n DB_POOL_MAX: z.string().default(\"20\").transform(Number),\n DB_POOL_IDLE_TIMEOUT: z.string().default(\"30000\").transform(Number),\n DB_POOL_CONNECT_TIMEOUT: z.string().default(\"10000\").transform(Number),\n DATABASE_DIRECT_URL: z.string().url().optional(),\n DATABASE_READ_URL: z.string().url().optional(),\n FORCE_LOCAL_STORAGE: optionalBoolString,\n // `gcs` is a first-class storage backend (GCSStorageController) and a valid\n // `type` in BackendStorageConfig, so it must validate here too — otherwise\n // an app that selects GCS from this variable dies in loadEnv before its own\n // config code ever runs.\n STORAGE_TYPE: z.enum([\"local\", \"s3\", \"gcs\"]).default(\"local\"),\n STORAGE_PATH: z.string().optional(),\n S3_BUCKET: z.string().optional(),\n S3_REGION: z.string().optional(),\n S3_ACCESS_KEY_ID: z.string().optional(),\n S3_SECRET_ACCESS_KEY: z.string().optional(),\n S3_ENDPOINT: z.string().url().optional(),\n S3_FORCE_PATH_STYLE: optionalBoolString,\n // The GCS counterparts of the S3 set above. Without them `STORAGE_TYPE=gcs`\n // validated but there was no way to say *which* bucket, so an app whose\n // config only branched on \"s3\" fell through to local disk — i.e. straight\n // into the ephemeral-storage trap. Credentials stay optional: on GKE\n // Workload Identity supplies them through ADC and a key file is the\n // exception, not the rule.\n GCS_BUCKET: z.string().optional(),\n GCS_PROJECT_ID: z.string().optional(),\n GCS_KEY_FILENAME: z.string().optional()\n});\n\n/** Inferred type of the validated environment. */\nexport type RebaseEnv = z.infer<typeof rebaseEnvSchema>;\n\n/**\n * Load and validate the Rebase environment configuration from `process.env`.\n *\n * Call this **after** your `.env` file has been loaded (via `dotenv`, `--env-file`,\n * container injection, etc.). This function does not load `.env` files itself —\n * that is a deployment concern, not a framework concern.\n *\n * Behavior:\n * - Auto-generates ephemeral `JWT_SECRET` and `REBASE_SERVICE_KEY` in\n * non-production mode so developers can start without manual setup.\n * - Blocks auto-generated secrets in production.\n * - Returns a fully typed, validated env object.\n *\n * Use `extend` to add your own typed env variables on top of the base Rebase schema:\n *\n * @example\n * ```ts\n * import dotenv from \"dotenv\";\n * import { z } from \"zod\";\n * import { loadEnv } from \"@rebasepro/server\";\n *\n * dotenv.config({ path: \"../../.env\" });\n *\n * // Basic — just Rebase env vars:\n * export const env = loadEnv();\n *\n * // Extended — add your own typed vars:\n * export const env = loadEnv({\n * extend: z.object({\n * SMTP_HOST: z.string().optional(),\n * SMTP_PORT: z.string().default(\"587\").transform(Number),\n * STRIPE_SECRET_KEY: z.string(),\n * })\n * });\n * // env.SMTP_HOST → string | undefined (fully typed)\n * // env.STRIPE_SECRET_KEY → string (validated, required)\n * ```\n */\nexport function loadEnv(): RebaseEnv;\nexport function loadEnv<E extends z.ZodObject<z.ZodRawShape>>(options: { extend: E }): RebaseEnv & z.infer<E>;\nexport function loadEnv(options?: { extend?: z.ZodObject<z.ZodRawShape> }): Record<string, unknown> {\n // Auto-generate dev secrets before validation so the Zod schema sees valid values.\n const isProduction = process.env.NODE_ENV === \"production\";\n const autoGeneratedSecrets: string[] = [];\n\n if (!isProduction) {\n if (!process.env.JWT_SECRET) {\n process.env.JWT_SECRET = generateSecret();\n autoGeneratedSecrets.push(\"JWT_SECRET\");\n }\n if (!process.env.REBASE_SERVICE_KEY) {\n process.env.REBASE_SERVICE_KEY = generateSecret();\n autoGeneratedSecrets.push(\"REBASE_SERVICE_KEY\");\n }\n }\n\n // Merge base schema with user extensions (if provided).\n const combinedSchema = options?.extend\n ? rebaseEnvSchema.merge(options.extend)\n : rebaseEnvSchema;\n\n // Validate with production-specific refinements.\n const schema = combinedSchema.superRefine((data, ctx) => {\n const d = data as RebaseEnv & Record<string, unknown>;\n if (d.NODE_ENV === \"production\" && !d.CORS_ORIGINS && !d.FRONTEND_URL) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"CORS_ORIGINS or FRONTEND_URL must be set in production to secure the API.\",\n path: [\"CORS_ORIGINS\"]\n });\n }\n if (d.NODE_ENV === \"production\" && autoGeneratedSecrets.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${autoGeneratedSecrets.join(\", \")} must be explicitly set in production. ` +\n \"Do not rely on auto-generated secrets outside development.\",\n path: [autoGeneratedSecrets[0]]\n });\n }\n if (d.NODE_ENV === \"production\" && !d.ALLOW_LOCALHOST_IN_PRODUCTION) {\n for (const [key, value] of Object.entries(data)) {\n if (key === \"CORS_ORIGINS\") continue;\n if (typeof value === \"string\" && isLocalhostOrLoopback(value)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n // The value is deliberately not echoed: these variables\n // routinely carry credentials (DATABASE_URL, SMTP_PASS,\n // OAuth secrets), and a failed production boot is logged\n // wherever the container's stdout goes.\n message: `Environment variable ${key} points at a local/loopback host. Deployed instances must not connect to localhost.`,\n path: [key]\n });\n }\n }\n }\n });\n\n const env = schema.parse(process.env);\n\n // Warn after successful parse so the server still starts in dev.\n if (autoGeneratedSecrets.length > 0) {\n logger.warn(\n `⚠️ Auto-generated secrets for: ${autoGeneratedSecrets.join(\", \")}. ` +\n \"These are ephemeral — existing tokens will be invalidated on restart. \" +\n \"Set them explicitly in .env for persistent sessions.\"\n );\n }\n\n return env as Record<string, unknown>;\n}\n","import { createHmac, randomUUID } from \"crypto\";\n\nexport interface WebhookConfig {\n id: string;\n url: string;\n secret?: string;\n headers?: Record<string, string>;\n events: string[];\n table: string;\n enabled: boolean;\n}\n\nexport interface WebhookDeliveryResult {\n webhookId: string;\n event: string;\n payload: Record<string, unknown>;\n statusCode: number;\n responseBody: string;\n success: boolean;\n attemptNumber: number;\n}\n\nexport class WebhookDispatcher {\n private webhooks: WebhookConfig[] = [];\n private maxRetries = 3;\n private retryDelays = [1000, 5000, 15000]; // Exponential backoff\n\n /** Register webhooks to watch */\n setWebhooks(webhooks: WebhookConfig[]): void {\n this.webhooks = webhooks.filter(w => w.enabled);\n }\n\n /** Called when a entity changes — checks if any webhook matches */\n async onEntityChange(\n table: string,\n event: \"INSERT\" | \"UPDATE\" | \"DELETE\",\n id: string,\n entity: Record<string, unknown> | null,\n previousEntity?: Record<string, unknown> | null\n ): Promise<WebhookDeliveryResult[]> {\n const matchingWebhooks = this.webhooks.filter(\n w => w.table === table && w.events.includes(event)\n );\n\n if (matchingWebhooks.length === 0) return [];\n\n const results: WebhookDeliveryResult[] = [];\n\n for (const webhook of matchingWebhooks) {\n const payload: Record<string, unknown> = {\n type: event,\n table,\n record: entity,\n old_record: event === \"UPDATE\" ? previousEntity : undefined,\n schema: \"public\",\n timestamp: new Date().toISOString()\n };\n\n const result = await this.deliverWithRetry(webhook, event, payload);\n results.push(result);\n }\n\n return results;\n }\n\n private async deliverWithRetry(\n webhook: WebhookConfig,\n event: string,\n payload: Record<string, unknown>\n ): Promise<WebhookDeliveryResult> {\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n const result = await this.deliver(webhook, event, payload, attempt);\n if (result.success) return result;\n\n if (attempt < this.maxRetries) {\n await new Promise(r => setTimeout(r, this.retryDelays[attempt - 1]));\n } else {\n return result; // Final failure\n }\n }\n\n // Should never reach here, but satisfies TypeScript\n return {\n webhookId: webhook.id,\n event,\n payload,\n statusCode: 0,\n responseBody: \"Max retries exceeded\",\n success: false,\n attemptNumber: this.maxRetries\n };\n }\n\n private async deliver(\n webhook: WebhookConfig,\n event: string,\n payload: Record<string, unknown>,\n attemptNumber: number\n ): Promise<WebhookDeliveryResult> {\n const body = JSON.stringify(payload);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-Webhook-Id\": webhook.id,\n \"X-Webhook-Event\": event,\n \"X-Webhook-Delivery\": randomUUID(),\n \"X-Webhook-Attempt\": String(attemptNumber),\n ...(webhook.headers || {})\n };\n\n // HMAC signature\n if (webhook.secret) {\n const signature = createHmac(\"sha256\", webhook.secret).update(body).digest(\"hex\");\n headers[\"X-Webhook-Signature\"] = `sha256=${signature}`;\n }\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10000); // 10s timeout\n\n const response = await fetch(webhook.url, {\n method: \"POST\",\n headers,\n body,\n signal: controller.signal\n });\n\n clearTimeout(timeout);\n\n const responseBody = await response.text().catch(() => \"\");\n const success = response.status >= 200 && response.status < 300;\n\n return {\n webhookId: webhook.id,\n event,\n payload,\n statusCode: response.status,\n responseBody: responseBody.slice(0, 1000), // Truncate\n success,\n attemptNumber\n };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n webhookId: webhook.id,\n event,\n payload,\n statusCode: 0,\n responseBody: message.slice(0, 1000),\n success: false,\n attemptNumber\n };\n }\n }\n}\n","/**\n * Dev-mode port resolution utilities.\n *\n * Provides a `listen` wrapper that automatically retries the next port when\n * the requested one is already in use, and writes the resolved port to a\n * well-known temp file so the CLI / frontend can discover it.\n *\n * Port affinity: when a port file already exists (e.g. after a tsx watch\n * restart), the saved port is tried FIRST so the backend stays on the same\n * port the frontend was configured with.\n *\n * This module is dev-only and should never run in production.\n */\nimport type { Server } from \"http\";\nimport path from \"path\";\nimport fs from \"fs\";\n\nconst MAX_PORT_ATTEMPTS = 20;\n\n/** Filename written next to the project `.env` so the CLI can read it. */\nexport const DEV_PORT_FILENAME = \".rebase-dev-port\";\n\n/**\n * Try to `listen` on `startPort`. If the port is busy (`EADDRINUSE`), increment\n * and retry up to `maxAttempts` times.\n *\n * When a port file written by a previous run exists *and that run asked for the\n * same `startPort`*, the port it landed on is tried first, so tsx watch restarts\n * keep the address the frontend was configured with. A different `startPort` means\n * the configuration changed and the file is ignored — an explicitly requested port\n * is never overridden by a stale one.\n *\n * Resolves with the port that was actually bound.\n *\n * @internal Not part of the stable public API. Exported only because the\n * official app template (`packages/cli/templates/template/backend/src/index.ts`\n * and `app/backend/src/index.ts`) calls it directly in dev mode. Its dev-only\n * port-affinity behavior is an implementation detail and may change without\n * a major version bump.\n */\nexport function listenWithPortRetry(\n server: Server,\n startPort: number,\n options?: {\n host?: string;\n maxAttempts?: number;\n /** Absolute path to write the resolved port file into. Defaults to `process.cwd()`. */\n portFileDir?: string;\n /** Service key to include in the state file for MCP server auto-discovery. */\n serviceKey?: string;\n }\n): Promise<number> {\n const host = options?.host ?? \"0.0.0.0\";\n const maxAttempts = options?.maxAttempts ?? MAX_PORT_ATTEMPTS;\n const portFileDir = options?.portFileDir;\n\n const isProd = process.env.NODE_ENV === \"production\";\n if (isProd) {\n return new Promise<number>((resolve, reject) => {\n const onError = (err: Error) => {\n reject(err);\n };\n server.once(\"error\", onError);\n server.listen(startPort, host, () => {\n server.removeListener(\"error\", onError);\n resolve(startPort);\n });\n });\n }\n\n // Read affinity port from a previous run's port file.\n // This ensures tsx watch restarts land on the same port the frontend was\n // configured with, even if the CLI-computed port was different.\n //\n // It applies only when the port being *asked for* has not changed since that\n // file was written, which is why the file records both. Affinity used to win\n // outright, so a stale file silently overrode an explicit port: set `PORT=4000`\n // in `.env` and the server would keep binding whatever the last run happened to\n // land on, reporting the old number. `resolvePort` in the CLI has always ranked\n // these correctly — explicit `--port`, then `PORT`, then affinity — and this is\n // the server agreeing with it.\n //\n // The e2e suite is what surfaced it: it assigns each backend a fresh free port,\n // and the second boot in a project ignored it and re-bound the first one.\n let affinityPort: number | null = null;\n if (portFileDir) {\n try {\n const portFile = path.join(portFileDir, DEV_PORT_FILENAME);\n if (fs.existsSync(portFile)) {\n // \"<bound> <requested>\" — `parseInt` stops at the space, so older\n // readers that expect a bare number still read the bound port.\n const [savedRaw, requestedRaw] = fs.readFileSync(portFile, \"utf-8\").trim().split(/\\s+/);\n const saved = parseInt(savedRaw, 10);\n const requestedThen = requestedRaw === undefined ? NaN : parseInt(requestedRaw, 10);\n const sameRequest = Number.isNaN(requestedThen) || requestedThen === startPort;\n if (saved > 0 && saved < 65536 && saved !== startPort && sameRequest) {\n affinityPort = saved;\n }\n }\n } catch { /* ignore */ }\n }\n\n return new Promise<number>((resolve, reject) => {\n let attempt = 0;\n // Build the ordered list of ports to try:\n // 1. The affinity port (if different from startPort)\n // 2. startPort, startPort+1, startPort+2, ...\n const portsToTry: number[] = [];\n if (affinityPort) portsToTry.push(affinityPort);\n for (let i = 0; i < maxAttempts; i++) {\n const p = startPort + i;\n if (p !== affinityPort) portsToTry.push(p);\n }\n\n function tryNext(index: number) {\n if (index >= portsToTry.length) {\n reject(new Error(\n \"All attempted ports are in use. \" +\n \"Stop other Rebase instances or specify a different port with --port.\"\n ));\n return;\n }\n\n const port = portsToTry[index];\n attempt++;\n\n // Both listeners are removed on either outcome.\n //\n // This used to pass the success handler as `server.listen(port, host, cb)`,\n // and that form registers `cb` as a one-shot `listening` listener which a\n // *failed* attempt never removes. So after an EADDRINUSE, the next attempt's\n // success ran both handlers, and the earliest one won the promise: the\n // function resolved with — and wrote into the port file — the port it had\n // just failed to bind.\n //\n // What that looked like: with something already on 3001, the server bound\n // 3002 and announced \"API running at http://localhost:3001\". Every caller\n // that trusted the banner reached the *other* process, which answered\n // normally from its own database. No error was logged anywhere. It cost the\n // templates e2e six failures that blamed registration, and it would hand a\n // developer running two projects a URL that silently serves the wrong app.\n const onListening = () => {\n cleanup();\n\n // Write the port file so the CLI can pick it up\n if (portFileDir) {\n try {\n const portFile = path.join(portFileDir, DEV_PORT_FILENAME);\n // Bound port first so `parseInt` still yields it, then the\n // port that was requested — that is what makes the affinity\n // above conditional rather than absolute.\n fs.writeFileSync(portFile, `${port} ${startPort}`, \"utf-8\");\n } catch {\n // Non-fatal — the CLI will fall back to parsing stdout\n }\n\n // Write .rebase/state.json so external scripts can discover\n // the running server port, URL, etc.\n writeStateFile(portFileDir, port, options?.serviceKey);\n }\n\n resolve(port);\n };\n\n const onError = (err: NodeJS.ErrnoException) => {\n cleanup();\n if (err.code === \"EADDRINUSE\") {\n tryNext(index + 1);\n } else {\n reject(err);\n }\n };\n\n function cleanup() {\n server.removeListener(\"listening\", onListening);\n server.removeListener(\"error\", onError);\n }\n\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen(port, host);\n }\n\n tryNext(0);\n });\n}\n\n/**\n * Clean up the dev port file and state file (call on graceful shutdown).\n *\n * @internal Not part of the stable public API. See {@link listenWithPortRetry}.\n */\nexport function cleanupDevPortFile(dir: string): void {\n try {\n const portFile = path.join(dir, DEV_PORT_FILENAME);\n if (fs.existsSync(portFile)) {\n fs.unlinkSync(portFile);\n }\n } catch {\n // ignore\n }\n try {\n const stateFile = path.join(dir, \".rebase\", \"state.json\");\n if (fs.existsSync(stateFile)) {\n fs.unlinkSync(stateFile);\n }\n } catch {\n // ignore\n }\n}\n\n/**\n * Write `.rebase/state.json` with runtime info for external scripts.\n *\n * Scripts can read this file to discover:\n * - `port` — the actual port the backend is listening on\n * - `baseUrl` — full URL including protocol and port\n * - `pid` — the backend process ID\n * - `startedAt` — ISO timestamp of when the server started\n * - `serviceKey` — (dev only) the REBASE_SERVICE_KEY for MCP auto-discovery\n *\n * @example Reading from a script:\n * ```ts\n * const state = JSON.parse(fs.readFileSync('.rebase/state.json', 'utf-8'));\n * const apiUrl = state.baseUrl; // \"http://localhost:3519\"\n * ```\n */\nfunction writeStateFile(projectRoot: string, port: number, serviceKey?: string): void {\n try {\n const rebaseDir = path.join(projectRoot, \".rebase\");\n if (!fs.existsSync(rebaseDir)) {\n fs.mkdirSync(rebaseDir, { recursive: true });\n }\n const stateFile = path.join(rebaseDir, \"state.json\");\n const state: Record<string, unknown> = {\n port,\n baseUrl: `http://localhost:${port}`,\n pid: process.pid,\n startedAt: new Date().toISOString()\n };\n if (serviceKey) {\n state.serviceKey = serviceKey;\n }\n // Owner-only: the file can carry the dev service key. `mode` only\n // applies on create, so chmod covers a pre-existing file.\n fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), { encoding: \"utf-8\", mode: 0o600 });\n fs.chmodSync(stateFile, 0o600);\n } catch {\n // Non-fatal\n }\n}\n","import { Hono } from \"hono\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\nimport fsp from \"node:fs/promises\";\nimport { responseCompression } from \"./utils/compression.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * Configuration for serving a Single Page Application\n */\nexport interface ServeSPAConfig {\n /**\n * Absolute path to the frontend build directory\n * @example path.join(__dirname, \"../../frontend/dist\")\n */\n frontendPath: string;\n\n /**\n * Public base path this app is served under (default: \"/\").\n *\n * No trailing slash unless it *is* \"/\". Several apps run in one process,\n * each under its own prefix — a site at \"/\" and an admin at \"/admin\" — so\n * both the asset middleware and the SPA fallback are scoped here rather\n * than claiming \"/*\" globally.\n *\n * The assets must have been *built* for this path too; see\n * `assertBuiltForPath` in the CLI.\n */\n basePath?: string;\n\n /**\n * Base path for API routes (default: \"/api\")\n * Requests to this path will be passed through to API handlers\n */\n apiBasePath?: string;\n\n /**\n * Additional paths to exclude from SPA handling\n * These paths will be passed through to other handlers\n *\n * When several apps share a process, the \"/\"-rooted one must list its\n * siblings here. Mount order alone is not enough: a request to \"/admin/x\"\n * that misses the admin's files would otherwise fall through to the root\n * app's catch-all and be answered with the *site's* index.html under the\n * admin's URL — which reads as an admin bug for a long time.\n *\n * Each entry excludes a path *segment*, not a string prefix: \"/admin\"\n * excludes \"/admin\" and \"/admin/x\" but not \"/administrators\", which is an\n * ordinary route of the app rooted at \"/\".\n *\n * @example [\"/health\", \"/ws\", \"/metrics\", \"/admin\"]\n */\n excludePaths?: string[];\n\n /**\n * Index file to serve for SPA routes (default: \"index.html\")\n */\n indexFile?: string;\n\n /**\n * Serve index.html for unmatched paths under `basePath` (default: true).\n *\n * `false` registers the asset middleware only, for a static *site* whose\n * generator emitted a real file per route.\n */\n spa?: boolean;\n}\n\n/**\n * Is `requestPath` the excluded path `prefix`, or something beneath it?\n *\n * Segment-aware on purpose. A plain `startsWith` reads \"/api\" as excluding\n * \"/apidocs\", and \"/admin\" as excluding \"/administrators\" — both ordinary\n * client-side routes of the app rooted at \"/\", both then answered with a 404\n * because the SPA fallback declined them and nothing else claims the path.\n * `apiBasePath` is always in the exclusion list, so this reached single-app\n * setups too, not just the multi-app ones the list was added for.\n */\nfunction isUnderPath(requestPath: string, prefix: string): boolean {\n // \"/\" would exclude everything below it, which is every request.\n const trimmed = prefix.replace(/\\/+$/, \"\");\n if (trimmed === \"\") return true;\n return requestPath === trimmed || requestPath.startsWith(`${trimmed}/`);\n}\n\n/**\n * Serve a Single Page Application from an Hono app.\n *\n * @internal Not part of the stable public API. Exported only because the\n * official app template (`packages/cli/templates/template/backend/src/index.ts`\n * and `app/backend/src/index.ts`) calls it to serve the built frontend in\n * production. Its request-handling behavior is an implementation detail and\n * may change without a major version bump.\n */\nexport function serveSPA<E extends import(\"hono\").Env>(app: Hono<E>, config: ServeSPAConfig): void {\n const {\n frontendPath,\n apiBasePath = \"/api\",\n excludePaths = [],\n indexFile = \"index.html\",\n spa = true\n } = config;\n\n // \"/admin/\" and \"/admin\" must not be two different mounts.\n const rawBase = config.basePath ?? \"/\";\n const basePath = rawBase !== \"/\" ? rawBase.replace(/\\/+$/, \"\") : \"/\";\n const isRoot = basePath === \"/\";\n\n // Validate frontend path exists.\n //\n // NOTE: this warns and disables itself rather than throwing, so a wrong path\n // leaves the API answering perfectly while the site 404s. Verify a mount by\n // fetching it, never by reading the logs.\n if (!fs.existsSync(frontendPath)) {\n logger.warn(`⚠️ Frontend build path does not exist: ${frontendPath}`);\n logger.warn(\" SPA serving is disabled. Build your frontend first.\");\n return;\n }\n\n // Scoped to this app's prefix. Registering at \"/*\" would mean one process\n // could serve exactly one SPA — and, worse, the first one registered would\n // silently answer for every app mounted after it.\n const scope = isRoot ? \"/*\" : `${basePath}/*`;\n\n // Compress the bundle. The API is compressed by `configureMiddlewares`, but\n // that is scoped to the API base path — static assets are served here, and\n // the JS bundle is the single largest thing most apps ship.\n //\n // Registered before serveStatic so it wraps it. `precompressed` takes\n // priority where the build emitted .br/.gz siblings: those cost no CPU and\n // give brotli, and set Content-Encoding themselves, which makes the\n // compression middleware skip them.\n app.use(scope, responseCompression());\n app.use(scope, serveStatic({\n root: path.relative(process.cwd(), frontendPath),\n precompressed: true,\n // The prefix is a serving concern, not a directory: `/admin/assets/x.js`\n // lives at `<adminBuild>/assets/x.js`.\n ...(isRoot ? {} : { rewriteRequestPath: (p: string) => p.slice(basePath.length) || \"/\" })\n }));\n\n if (!spa) {\n logger.info(`✅ Static serving enabled at ${basePath} from: ${frontendPath}`);\n return;\n }\n\n // Build list of paths to exclude from SPA handling\n const allExcludePaths = [apiBasePath, ...excludePaths];\n\n // Cache the index.html content to avoid re-reading from disk on every navigation request.\n let cachedHtml: string | null = null;\n\n // SPA fallback - serve index.html for all non-excluded routes under basePath\n app.get(scope, async (c, next) => {\n // Skip excluded paths (API, health checks, sibling apps).\n if (allExcludePaths.some(p => isUnderPath(c.req.path, p))) {\n return next();\n }\n\n const indexPath = path.join(frontendPath, indexFile);\n\n if (!cachedHtml) {\n try {\n cachedHtml = await fsp.readFile(indexPath, \"utf-8\");\n } catch {\n logger.warn(`⚠️ Index file not found: ${indexPath}`);\n return next();\n }\n }\n\n return c.html(cachedHtml);\n });\n\n logger.info(`✅ SPA serving enabled at ${basePath} from: ${frontendPath}`);\n}\n\n","import fs from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport {\n BUNDLE_FORMAT_VERSION,\n RUNTIME_CONTRACT_VERSION,\n type CollectionConfig,\n type CollectionCallbacks,\n type DataSourceDefinition,\n type RebaseBundleManifest,\n type StorageSourceDefinition\n} from \"@rebasepro/types\";\nimport type { StorageAuthorize } from \"../storage/types\";\nimport { logger } from \"../utils/logger\";\n\n/** Thrown when a bundle cannot be read, or claims a contract this runtime cannot honour. */\nexport class BundleError extends Error {\n constructor(message: string, readonly hint?: string) {\n super(message);\n this.name = \"BundleError\";\n }\n}\n\n/** A bundle that has been located and whose manifest has been validated. */\nexport interface LoadedBundle {\n dir: string;\n manifest: RebaseBundleManifest;\n /** Absolute path to the compiled collections directory, when present. */\n collectionsDir?: string;\n functionsDir?: string;\n cronsDir?: string;\n /**\n * Built static apps to serve from this process, in mount order.\n *\n * A list, not a single directory: one process serves a site at `/` and an\n * admin at `/admin`. Entries whose directory is missing are dropped with a\n * warning, so a partially-built bundle still boots its API.\n */\n staticApps: LoadedStaticApp[];\n}\n\n/** One built static app inside a loaded bundle, with an absolute directory. */\nexport interface LoadedStaticApp {\n /** Public base path, e.g. `/` or `/admin`. */\n path: string;\n /** Absolute path to the built assets. */\n dir: string;\n /** Serve `index.html` for unmatched paths under `path`. */\n spa: boolean;\n}\n\nconst MANIFEST_FILENAME = \"manifest.json\";\n\n/**\n * Bring a format-1 manifest up to the shape the rest of this runtime expects.\n *\n * Old bundles booting on a new runtime is the case the format version exists to\n * protect, so this is not a courtesy — it is the contract. A project built\n * before the rename ships `mode` and a single `entry.static` directory string,\n * and without this it would boot with no `kind` (so every gate keyed on\n * `kind === \"backend\"` would skip) and an `entry.static` the loader would try to\n * iterate as a list.\n *\n * In place, and only ever filling in what is absent, so a format-2 manifest\n * passes through untouched.\n */\nfunction upgradeLegacyManifest(manifest: RebaseBundleManifest): void {\n const legacy = manifest as RebaseBundleManifest & {\n mode?: string;\n entry?: { static?: unknown; admin?: unknown };\n };\n\n if (!legacy.kind) {\n // `cms` and `baas` were both backends — the distinction between them is\n // derived from `entry.config` now.\n legacy.kind = legacy.mode === \"static\" ? \"static\" : \"backend\";\n }\n\n const entry = legacy.entry;\n if (!entry) return;\n\n if (typeof entry.static === \"string\") {\n entry.static = [{ path: \"/\",\ndir: entry.static,\nspa: true }];\n } else if (!entry.static && typeof entry.admin === \"string\") {\n // A format-1 bundled admin panel was served at the root, exactly as a\n // static app was — `staticDir ?? adminDir`, one or the other.\n entry.static = [{ path: \"/\",\ndir: entry.admin,\nspa: true }];\n }\n delete entry.admin;\n}\n\n/**\n * Read and validate a bundle's manifest.\n *\n * The checks here are the runtime half of the compatibility contract, and they\n * all fail loudly at boot rather than at the first request. A container that\n * refuses to start is a deploy that rolls back; a container that starts and then\n * misbehaves is an incident.\n */\nexport function readBundleManifest(bundleDir: string): RebaseBundleManifest {\n const manifestPath = path.join(bundleDir, MANIFEST_FILENAME);\n\n if (!fs.existsSync(manifestPath)) {\n throw new BundleError(\n `No ${MANIFEST_FILENAME} found in ${bundleDir}`,\n \"Build the project with `rebase build` and point the runtime at the output directory.\"\n );\n }\n\n let manifest: RebaseBundleManifest;\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as RebaseBundleManifest;\n } catch (err) {\n throw new BundleError(\n `${manifestPath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n if (typeof manifest.bundleFormat !== \"number\") {\n throw new BundleError(`${manifestPath} is missing \"bundleFormat\".`);\n }\n\n // Newer format on an older runtime: the layout may have fields this code\n // does not know how to read, so refuse rather than half-load it. The reverse\n // — an older bundle on a newer runtime — is the case that must keep working,\n // and does.\n if (manifest.bundleFormat > BUNDLE_FORMAT_VERSION) {\n throw new BundleError(\n `This bundle uses format ${manifest.bundleFormat}, but this runtime understands up to ${BUNDLE_FORMAT_VERSION}.`,\n \"Upgrade the runtime image, or rebuild the bundle with a matching CLI.\"\n );\n }\n\n upgradeLegacyManifest(manifest);\n\n const contract = manifest.runtime?.contract;\n if (typeof contract === \"number\" && contract !== RUNTIME_CONTRACT_VERSION) {\n throw new BundleError(\n `This bundle targets runtime contract v${contract}, but this runtime implements v${RUNTIME_CONTRACT_VERSION}.`,\n contract > RUNTIME_CONTRACT_VERSION\n ? \"Upgrade the runtime image to a version that implements the newer contract.\"\n : \"Rebuild the bundle against the current runtime (`rebase build`), or run a runtime image from the previous major.\"\n );\n }\n\n return manifest;\n}\n\n/**\n * Locate a bundle and resolve every directory the runtime needs from it.\n *\n * Entry paths in the manifest are bundle-relative and are resolved here, once,\n * so nothing downstream has to know the layout. A declared directory that does\n * not exist is dropped with a warning rather than failing the boot: an empty\n * `functions/` is a perfectly ordinary project, and refusing to start over one\n * would be the runtime inventing a requirement the developer never stated.\n */\n/**\n * Resolve a bundle-relative entry, refusing anything that escapes the bundle.\n *\n * Applied to the entries that are `import()`ed — the schema, the config index,\n * the users collection — and not only to the ones that are merely scanned. Those\n * three *execute code*, so they are precisely the ones a malformed or hostile\n * manifest would target, and leaving them unchecked while guarding the read-only\n * paths would be defending the wrong door.\n */\nexport function resolveBundlePath(\n bundleDir: string,\n entry: string,\n label: string\n): string {\n const resolved = path.resolve(bundleDir, entry);\n const relative = path.relative(bundleDir, resolved);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new BundleError(\n `Bundle entry \"${label}\" points outside the bundle: ${entry}`\n );\n }\n return resolved;\n}\n\nexport function loadBundle(bundleDir: string): LoadedBundle {\n const dir = path.resolve(bundleDir);\n\n if (!fs.existsSync(dir)) {\n throw new BundleError(\n `Bundle directory not found: ${dir}`,\n \"Run `rebase build` first, or pass the correct path (e.g. `rebase-server ./dist-bundle`).\"\n );\n }\n\n const manifest = readBundleManifest(dir);\n\n const resolveEntry = (entry: string | undefined, label: string): string | undefined => {\n if (!entry) return undefined;\n // A manifest is a build artifact, but it is also a file a deploy\n // pipeline moves around — keep every entry inside the bundle so a\n // malformed one cannot point the runtime at arbitrary paths.\n const resolved = resolveBundlePath(dir, entry, label);\n if (!fs.existsSync(resolved)) {\n logger.warn(`Bundle declares ${label} at \"${entry}\", but that path does not exist — skipping.`);\n return undefined;\n }\n return resolved;\n };\n\n const entry = manifest.entry ?? {};\n\n // Collections live under the config package unless stated otherwise.\n const collectionsDir = entry.collections\n ? resolveEntry(entry.collections, \"collections\")\n : entry.config\n ? resolveEntry(path.join(entry.config, \"collections\"), \"collections\")\n : undefined;\n\n return {\n dir,\n manifest,\n collectionsDir,\n functionsDir: resolveEntry(entry.functions, \"functions\"),\n cronsDir: resolveEntry(entry.crons, \"crons\"),\n staticApps: (entry.static ?? [])\n .map(item => {\n const resolved = resolveEntry(item.dir, `static app \"${item.path}\"`);\n return resolved ? { path: item.path,\ndir: resolved,\nspa: item.spa !== false } : undefined;\n })\n .filter((item): item is LoadedStaticApp => item !== undefined)\n // Longest path first, \"/\" last: the root app's catch-all would\n // otherwise claim every sibling's URLs.\n .sort((a, b) => b.path.length - a.path.length)\n };\n}\n\n/**\n * The Drizzle schema a bundle ships: tables, enums and relations, as generated\n * from the project's collections.\n */\nexport interface BundleSchemaExports {\n tables?: Record<string, unknown>;\n enums?: Record<string, unknown>;\n relations?: Record<string, unknown>;\n}\n\n/**\n * Import the bundle's Drizzle schema module.\n *\n * Returns `undefined` when the bundle declares none — `baas` mode introspects the\n * live database instead of shipping a schema.\n */\nexport async function loadBundleSchema(bundle: LoadedBundle): Promise<BundleSchemaExports | undefined> {\n const entry = bundle.manifest.entry?.schema;\n if (!entry) return undefined;\n\n const schemaPath = resolveBundlePath(bundle.dir, entry, \"schema\");\n if (!fs.existsSync(schemaPath)) {\n logger.warn(`Bundle declares a schema at \"${entry}\", but that file does not exist — continuing without it.`);\n return undefined;\n }\n\n const mod = await import(pathToFileURL(schemaPath).href) as BundleSchemaExports;\n return {\n tables: mod.tables,\n enums: mod.enums,\n relations: mod.relations\n };\n}\n\n/**\n * Build a bundle view over a project's **source** directories.\n *\n * `rebase dev` runs TypeScript directly through tsx, so there is no compiled\n * bundle to load — but everything downstream of loading (drivers, storage, auth,\n * routes) should be identical, or development stops predicting production. This\n * produces the same {@link LoadedBundle} shape from source paths, so the one boot\n * path serves both.\n *\n * The schema version is left empty deliberately: nothing has been built, so\n * there is no build-time answer, and the runtime computes one from the live\n * collections instead.\n */\nexport function createSourceBundle(options: {\n projectRoot: string;\n config?: string;\n collections?: string;\n functions?: string;\n crons?: string;\n schema?: string;\n app?: string;\n}): LoadedBundle {\n const dir = path.resolve(options.projectRoot);\n const resolve = (entry: string | undefined): string | undefined => {\n if (!entry) return undefined;\n const full = path.resolve(dir, entry);\n return fs.existsSync(full) ? full : undefined;\n };\n\n const configDir = options.config ?? \"config\";\n const collectionsDir = options.collections\n ?? (options.config !== undefined || fs.existsSync(path.join(dir, configDir))\n ? path.join(configDir, \"collections\")\n : undefined);\n\n const manifest: RebaseBundleManifest = {\n bundleFormat: BUNDLE_FORMAT_VERSION,\n runtime: {\n range: `^${RUNTIME_CONTRACT_VERSION}`,\n builtAgainst: \"source\",\n contract: RUNTIME_CONTRACT_VERSION\n },\n schemaVersion: \"\",\n app: options.app ?? \"backend\",\n kind: \"backend\",\n entry: {\n config: options.config ?? configDir,\n collections: collectionsDir,\n functions: options.functions,\n crons: options.crons,\n schema: options.schema\n },\n hooks: { native: false },\n deps: { declared: {} },\n build: { cli: \"source\",\nnode: process.versions.node.split(\".\")[0],\ncreatedAt: new Date().toISOString() }\n };\n\n return {\n dir,\n manifest,\n collectionsDir: resolve(collectionsDir),\n functionsDir: resolve(options.functions),\n cronsDir: resolve(options.crons),\n staticApps: []\n };\n}\n\n/**\n * Declarations a bundle's config package exports alongside its collections.\n *\n * These describe *topology* — which databases and which buckets exist — so they\n * belong to the project rather than to the environment. The environment then\n * supplies credentials for each declared key. Splitting it this way is what lets\n * a deploy be validated before it runs: the set of things needing configuration\n * is known from the bundle, without reading anyone's secrets.\n */\nexport interface BundleConfigExports {\n dataSources?: DataSourceDefinition[];\n storageSources?: StorageSourceDefinition[];\n /**\n * Per-object storage access control.\n *\n * A function, so it can only come from the project's own code — there is no\n * environment variable that could express \"this user may read this key\".\n * Without a way to supply it, a production deployment with a bucket would be\n * forced to choose between `STORAGE_PUBLIC_READ` (world-readable) and\n * `STORAGE_ALLOW_ANY_AUTHENTICATED` (every signed-in user can read, overwrite\n * and delete every other user's files) — the runtime would be making an\n * insecure choice on the developer's behalf.\n */\n storageAuthorize?: StorageAuthorize;\n /** Lifecycle callbacks applied to every collection. */\n callbacks?: CollectionCallbacks;\n}\n\n/**\n * Read the config package's `index` for declarations.\n *\n * Absent, empty or unreadable all mean the same thing: a single default database\n * and a single default bucket. That is the overwhelmingly common project, and it\n * must not be required to say so. A malformed export is reported and ignored\n * rather than fatal — a typo in an optional declaration should not take down a\n * server whose collections are fine.\n */\nexport async function loadBundleConfigExports(bundle: LoadedBundle): Promise<BundleConfigExports> {\n const configEntry = bundle.manifest.entry?.config;\n if (!configEntry) return {};\n\n const configDir = resolveBundlePath(bundle.dir, configEntry, \"config\");\n // `.ts` for a source boot (`rebase dev` runs under tsx, which imports\n // TypeScript directly); `.js` for a built bundle.\n const indexPath = [\".js\", \".ts\"]\n .map(ext => path.join(configDir, `index${ext}`))\n .find(candidate => fs.existsSync(candidate));\n if (!indexPath) return {};\n\n let mod: Record<string, unknown>;\n try {\n mod = await import(pathToFileURL(indexPath).href) as Record<string, unknown>;\n } catch (err) {\n logger.warn(\n `Could not import the config index at ${indexPath}: ` +\n `${err instanceof Error ? err.message : String(err)}. ` +\n \"Continuing with a single default data source and storage source.\"\n );\n return {};\n }\n\n const readArray = <T>(name: string): T[] | undefined => {\n const value = mod[name];\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) {\n logger.warn(`Config exports \"${name}\" but it is not an array — ignoring.`);\n return undefined;\n }\n return value as T[];\n };\n\n const readFunction = <T>(name: string): T | undefined => {\n const value = mod[name];\n if (value === undefined) return undefined;\n if (typeof value !== \"function\") {\n logger.warn(`Config exports \"${name}\" but it is not a function — ignoring.`);\n return undefined;\n }\n return value as T;\n };\n\n const callbacks = mod.callbacks;\n\n return {\n dataSources: readArray<DataSourceDefinition>(\"dataSources\"),\n storageSources: readArray<StorageSourceDefinition>(\"storageSources\"),\n storageAuthorize: readFunction<StorageAuthorize>(\"storageAuthorize\"),\n callbacks: callbacks && typeof callbacks === \"object\"\n ? callbacks as CollectionCallbacks\n : undefined\n };\n}\n\n/**\n * Import the collection that backs authentication.\n *\n * Auth needs to know which table holds users. The bundle names the module; the\n * convention (`collections/users`) covers every project that did not rename it.\n * Returning `undefined` is valid — a `baas`-mode project has no config package,\n * and the auth bootstrapper falls back to its own default users table.\n */\nexport async function loadUsersCollection(bundle: LoadedBundle): Promise<CollectionConfig | undefined> {\n const entry = bundle.manifest.entry;\n const configDir = entry?.config\n ? resolveBundlePath(bundle.dir, entry.config, \"config\")\n : undefined;\n\n const candidates: string[] = [];\n if (entry?.usersCollection) {\n const declared = resolveBundlePath(bundle.dir, entry.usersCollection, \"usersCollection\");\n candidates.push(declared, `${declared}.js`, `${declared}.ts`);\n }\n for (const dir of [configDir && path.join(configDir, \"collections\"), bundle.collectionsDir]) {\n if (!dir) continue;\n candidates.push(path.join(dir, \"users.js\"), path.join(dir, \"users.ts\"));\n }\n\n for (const candidate of candidates) {\n if (!/\\.(js|ts)$/.test(candidate) || !fs.existsSync(candidate)) continue;\n try {\n const mod = await import(pathToFileURL(candidate).href) as { default?: CollectionConfig };\n if (mod.default) return mod.default;\n logger.warn(`Users collection module ${candidate} has no default export — ignoring.`);\n } catch (err) {\n logger.warn(\n `Failed to import users collection from ${candidate}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n\n return undefined;\n}\n","import { z } from \"zod\";\nimport { loadEnv, type RebaseEnv } from \"../env\";\nimport { BundleError } from \"./bundle\";\n\n/**\n * The environment a bundle-booted runtime understands.\n *\n * This extends the base {@link loadEnv} schema with the variables an application\n * used to declare for itself in its own `env.ts`. They live here now because the\n * runtime, not the application, is what reads them: a project ships a bundle and\n * a set of environment variables, and everything either side needs to agree on\n * has to be part of the contract rather than a convention each project reinvents.\n */\nconst bootEnvExtension = z.object({\n // ── Email ────────────────────────────────────────────────────────────────\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default(\"587\").transform(Number),\n SMTP_SECURE: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n SMTP_NAME: z.string().optional(),\n APP_NAME: z.string().default(\"Rebase\"),\n\n // ── Runtime behaviour ────────────────────────────────────────────────────\n /**\n * Serve the bundle's static/admin assets from this process.\n *\n * Default on, because a self-hosted single-container deployment is the case\n * that needs it and the assets are simply absent when there is nothing to\n * serve. A platform putting a CDN in front turns it off.\n */\n REBASE_SERVE_STATIC: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n /**\n * What the runtime may do to the database schema at boot.\n *\n * - `none` (default in production) — touch nothing. Schema changes are a\n * deliberate, reviewable step, not a side effect of a restart.\n * - `ensure` — create the auth/system tables if missing, never touch\n * collection tables. The default outside production.\n * - `push` — reconcile collection tables with the bundle's schema. Convenient\n * for a local compose stack; in production it means a container restart can\n * rewrite the schema, so it must be asked for explicitly.\n */\n REBASE_MIGRATE_ON_BOOT: z.enum([\"none\", \"ensure\", \"push\", \"\"]).optional(),\n /** Expose Prometheus metrics at `/metrics`. Off unless asked for. */\n REBASE_METRICS: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n /**\n * Bearer token guarding `/metrics`. When unset the endpoint is open to\n * anyone who can reach the port, which is fine on a private network and not\n * fine on a public one — hence the boot-time warning rather than a silent\n * default.\n */\n REBASE_METRICS_TOKEN: z.string().optional(),\n LOG_LEVEL: z.enum([\"error\", \"warn\", \"info\", \"debug\", \"\"]).optional(),\n\n // ── Storage access control ───────────────────────────────────────────────\n /** Serve stored objects to unauthenticated readers. */\n STORAGE_PUBLIC_READ: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n /**\n * Opt out of the storage access-control boot guard, restoring the behaviour\n * where any authenticated user may read, overwrite, delete or list any key.\n * Only defensible when every signed-in user is trusted with every file.\n */\n STORAGE_ALLOW_ANY_AUTHENTICATED: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n\n // ── Auth ─────────────────────────────────────────────────────────────────\n AUTH_REQUIRE: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n AUTH_ALLOW_USER_LOOKUP: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n AUTH_COOKIE_SAME_SITE: z.enum([\"Strict\", \"Lax\", \"None\", \"\"]).optional(),\n AUTH_DEFAULT_ROLE: z.string().optional(),\n GITHUB_CLIENT_ID: z.string().optional(),\n GITHUB_CLIENT_SECRET: z.string().optional(),\n MICROSOFT_CLIENT_ID: z.string().optional(),\n MICROSOFT_CLIENT_SECRET: z.string().optional(),\n\n // ── API surface ──────────────────────────────────────────────────────────\n REBASE_BASE_PATH: z.string().default(\"/api\"),\n /**\n * The OpenAPI surface: `/api/docs` (the spec) and `/api/swagger` (the UI).\n *\n * Deliberately tri-state, and resolved against NODE_ENV by\n * {@link resolveEnableSwagger} rather than defaulted here. Unset means \"on\n * in development, off in production\" — an explicit `true` or `false` always\n * wins in both.\n *\n * It used to default to `\"false\"` outright, which reads as a safe default\n * and was not one: the runtime is how every scaffolded project boots, so\n * the docs disappeared from projects that never asked for that. `rebase\n * init` prints \"docs are at /api/swagger\" on completion, the headless\n * README repeats it, and the console's API Explorer fetches `/api/docs` —\n * all three 404'd against a project running the runtime, and the baas e2e\n * failed on exactly that.\n */\n REBASE_ENABLE_SWAGGER: z.enum([\"true\", \"false\", \"\"]).optional()\n .transform(v => (v === undefined || v === \"\" ? undefined : v === \"true\")),\n /**\n * Maximum request body size, in **bytes**.\n *\n * Validated as a number rather than coerced loosely: `Number(\"10MB\")` is\n * `NaN`, which is not nullish, so it would slip past the downstream default\n * and then fail a `> 0` check — silently removing every body limit from the\n * API. A boot failure naming the variable is the only safe reading of a\n * value nobody can interpret.\n */\n REBASE_MAX_BODY_SIZE: z.coerce\n .number({ message: \"REBASE_MAX_BODY_SIZE must be a number of bytes (e.g. 10485760)\" })\n .int()\n .nonnegative()\n .optional(),\n REBASE_COMPRESSION: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n REBASE_HISTORY: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n /** Comma-separated origins allowed to make credentialed cross-origin calls. */\n CORS_ORIGINS: z.string().optional()\n});\n\nexport type RebaseBootEnv = RebaseEnv & z.infer<typeof bootEnvExtension>;\n\n/**\n * Load and validate the environment for a bundle boot.\n *\n * Does not read `.env` files — that is the deployment's job (a container gets\n * real environment variables; `rebase dev` and `rebase start` load dotenv before\n * calling in).\n */\nexport function loadBootEnv(): RebaseBootEnv {\n try {\n return loadEnv({ extend: bootEnvExtension }) as RebaseBootEnv;\n } catch (err) {\n // A raw ZodError prints a JSON dump and a stack trace through the\n // validator — several screens of noise whose actual content is \"you did\n // not set DATABASE_URL\". Restate it as the list of variables to fix.\n const issues = (err as { issues?: { path?: (string | number)[]; message?: string }[] }).issues;\n if (!Array.isArray(issues)) throw err;\n\n const lines = issues.map(issue => {\n const name = Array.isArray(issue.path) ? issue.path.join(\".\") : \"\";\n const detail = issue.message === \"Invalid input\" ? \"is required\" : issue.message;\n return name ? ` ${name}: ${detail}` : ` ${detail}`;\n });\n\n throw new BundleError(\n `The environment is not valid:\\n${lines.join(\"\\n\")}`,\n \"See https://rebase.pro/docs/deployment/self-hosting/ for the variables a deployment needs.\"\n );\n }\n}\n\n/**\n * Whether an origin is a loopback address.\n *\n * In development the runtime reflects only localhost origins. It cannot reflect\n * an arbitrary `Origin`, because credentials are enabled: any site the developer\n * happened to visit could otherwise make credentialed requests against the dev\n * server with the developer's session and read the responses.\n */\nexport function isLocalhostOrigin(origin: string): boolean {\n try {\n const { hostname } = new URL(origin);\n return hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\";\n } catch {\n return false;\n }\n}\n\n/** A CORS origin resolver of the shape Hono's `cors()` middleware expects. */\n/**\n * Whether this process serves the OpenAPI docs.\n *\n * An explicit `REBASE_ENABLE_SWAGGER` wins in either direction. Left unset, the\n * docs follow the environment: on in development, where they are part of how a\n * scaffolded project is meant to be explored, and off in production, where the\n * spec enumerates every collection and field to anyone who asks for it.\n *\n * Returning `undefined` for development is the point rather than an oversight —\n * it hands the decision to the server's own policy in `init/docs.ts`, which also\n * knows to withhold the Swagger UI while still serving the spec. Two defaults\n * that can disagree about the same route is the bug this replaces.\n */\nexport function resolveEnableSwagger(env: RebaseBootEnv): boolean | undefined {\n if (env.REBASE_ENABLE_SWAGGER !== undefined) return env.REBASE_ENABLE_SWAGGER;\n return env.NODE_ENV === \"production\" ? false : undefined;\n}\n\nexport type CorsOriginResolver = (origin: string) => string | null;\n\n/**\n * Build the CORS origin policy.\n *\n * Production serves an explicit allow-list and nothing else. `loadEnv` already\n * refuses to start a production process with neither `CORS_ORIGINS` nor\n * `FRONTEND_URL`, so an empty list here can only mean the values were blank\n * strings — still worth failing on, because the alternative is an API that\n * quietly rejects its own frontend.\n */\nexport function resolveCorsOrigin(env: RebaseBootEnv): CorsOriginResolver {\n const isProduction = env.NODE_ENV === \"production\";\n\n if (!isProduction) {\n return (origin: string) => {\n if (!origin) return \"*\";\n return isLocalhostOrigin(origin) ? origin : null;\n };\n }\n\n const raw = env.CORS_ORIGINS || env.FRONTEND_URL || \"\";\n const allowed = raw.split(\",\").map(s => s.trim()).filter(Boolean);\n\n if (allowed.length === 0) {\n throw new Error(\n \"CORS_ORIGINS or FRONTEND_URL must be set in production. \" +\n \"Example: CORS_ORIGINS=https://yourdomain.com\"\n );\n }\n\n const wildcard = allowed.includes(\"*\");\n if (wildcard) {\n // `*` with credentials is rejected by every browser, so a config that\n // asks for it is a misconfiguration that would present as an opaque CORS\n // failure at runtime. Say so at boot instead.\n throw new Error(\n \"CORS_ORIGINS cannot be \\\"*\\\" — the API sends credentials, and browsers \" +\n \"refuse a wildcard origin on credentialed requests. List the exact origins.\"\n );\n }\n\n return (origin: string) => (allowed.includes(origin) ? origin : null);\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport {\n DEFAULT_DATA_SOURCE_KEY,\n DEFAULT_STORAGE_SOURCE_KEY,\n findStorageSuffixCollision,\n normalizeStorageSources,\n storageEnvSuffix,\n type DataSourceDefinition,\n type DeclaredStorageSources,\n type StorageSourceDefinition\n} from \"@rebasepro/types\";\nimport type { BackendStorageConfig } from \"../storage/types\";\nimport { logger } from \"../utils/logger\";\nimport { BundleError } from \"./bundle\";\n\n/**\n * Resolving *named* data and storage sources from the environment.\n *\n * A project is not required to have one database and one bucket. Collections\n * already route by `collection.dataSource`, storage properties already route by\n * `storageSource`, and the backend already registers one driver per source key —\n * so the only piece missing was a way to *configure* the second, third and fourth\n * of each without hand-writing an entrypoint.\n *\n * The naming rule is mechanical, and deliberately derives the variable name from\n * the declared key rather than trying to discover keys by scanning the\n * environment. Scanning would have to guess how `DATABASE_URL_READ_REPLICA` splits\n * into a key; deriving cannot be ambiguous, and a typo shows up as a missing\n * source at boot instead of a silently ignored variable.\n *\n * ```\n * <BASE> the default source DATABASE_URL, S3_BUCKET\n * <BASE>__<KEY> a named source DATABASE_URL__ANALYTICS, S3_BUCKET__MEDIA\n * ```\n *\n * The double underscore matters: single-underscore suffixes collide with real\n * variable names (`S3_BUCKET_NAME` would parse as bucket \"name\").\n */\n\n/** Environment lookup, injectable so tests need not mutate `process.env`. */\nexport type EnvBag = Record<string, string | undefined>;\n\n/**\n * Convert a source key into the suffix used in environment variable names.\n *\n * The default key maps to no suffix at all, which is what keeps every existing\n * single-database deployment working untouched.\n *\n * The rule itself lives in `@rebasepro/types` so the CLI and any control plane\n * derive identical names from identical keys; this wrapper exists only to raise\n * it as a `BundleError`, which is what the rest of boot reports failures as.\n */\nexport function envSuffixForKey(key: string, defaultKey: string): string {\n try {\n return storageEnvSuffix(key, defaultKey);\n } catch (err) {\n throw new BundleError(\n `Source key \"${key}\" cannot be turned into an environment variable name.`,\n \"Use a key containing at least one letter or digit.\"\n );\n }\n}\n\n/** Read `<base>` for the default source, `<base>__<KEY>` for a named one. */\nfunction readVar(env: EnvBag, base: string, suffix: string): string | undefined {\n const value = env[`${base}${suffix}`];\n return value === \"\" ? undefined : value;\n}\n\nfunction readBool(env: EnvBag, base: string, suffix: string): boolean | undefined {\n const raw = readVar(env, base, suffix);\n if (raw === undefined) return undefined;\n return raw === \"true\";\n}\n\n/**\n * Guard against two distinct keys collapsing onto the same variable name.\n *\n * `media-cdn` and `media_cdn` are different source keys but the same suffix, and\n * without this check one of them would silently read the other's configuration.\n */\nexport function assertDistinctSuffixes(\n definitions: { key: string }[],\n defaultKey: string,\n what: string\n): void {\n const collision = findStorageSuffixCollision(definitions.map(d => d.key), defaultKey);\n if (collision) {\n throw new BundleError(\n `${what} keys \"${collision.a}\" and \"${collision.b}\" both map to the same environment ` +\n `variable suffix \"${collision.suffix || \"(none)\"}\".`,\n \"Rename one of them so each source has its own configuration.\"\n );\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Data sources\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Which driver package backs a given engine, before env overrides. */\nconst ENGINE_DRIVERS: Record<string, string> = {\n postgres: \"@rebasepro/server-postgres\",\n postgresql: \"@rebasepro/server-postgres\",\n mongodb: \"@rebasepro/server-mongo\",\n mongo: \"@rebasepro/server-mongo\"\n};\n\n/** A data source resolved to everything needed to build a driver for it. */\nexport interface ResolvedDataSourceConfig {\n /** Data-source key — becomes the driver-registry id collections route by. */\n key: string;\n engine: string;\n /** npm package implementing the driver. */\n driverPackage: string;\n connectionString: string;\n adminConnectionString?: string;\n readConnectionString?: string;\n isDefault: boolean;\n poolConfig?: Record<string, number>;\n}\n\n/**\n * Resolve every server-transport data source to a connection.\n *\n * `direct` and `custom` transports are skipped: the client talks to those\n * itself, so the backend holds no connection for them and must not demand one.\n *\n * A declared source with no connection string is an error rather than a warning.\n * The alternative — starting without it — means every collection routed to that\n * source silently falls back to the default database, which is data landing in\n * the wrong place with a healthy-looking server in front of it.\n */\nexport function resolveDataSources(\n env: EnvBag,\n definitions: DataSourceDefinition[] | undefined\n): ResolvedDataSourceConfig[] {\n const declared = definitions ?? [];\n assertDistinctSuffixes(declared, DEFAULT_DATA_SOURCE_KEY, \"Data source\");\n\n // A project that declares nothing still has one database: the default.\n const hasDefault = declared.some(d => d.key === DEFAULT_DATA_SOURCE_KEY);\n const serverSide = declared.filter(d => (d.transport ?? \"server\") === \"server\");\n const effective: DataSourceDefinition[] = hasDefault\n ? serverSide\n : [{ key: DEFAULT_DATA_SOURCE_KEY,\nengine: \"postgres\" }, ...serverSide];\n\n const resolved: ResolvedDataSourceConfig[] = [];\n\n for (const definition of effective) {\n const suffix = envSuffixForKey(definition.key, DEFAULT_DATA_SOURCE_KEY);\n const connectionString = readVar(env, \"DATABASE_URL\", suffix);\n\n if (!connectionString) {\n throw new BundleError(\n `Data source \"${definition.key}\" has no connection string — ` +\n `set ${`DATABASE_URL${suffix}`}.`,\n \"Every declared server-transport data source needs its own connection; \" +\n \"collections routed to it would otherwise silently use the default database.\"\n );\n }\n\n const engine = definition.engine || \"postgres\";\n const driverPackage =\n readVar(env, \"REBASE_DRIVER\", suffix) ||\n ENGINE_DRIVERS[engine.toLowerCase()];\n\n if (!driverPackage) {\n throw new BundleError(\n `No driver package is known for engine \"${engine}\" (data source \"${definition.key}\") — ` +\n `set ${`REBASE_DRIVER${suffix}`} to the npm package implementing it.`\n );\n }\n\n const poolConfig = resolvePoolConfig(env, suffix);\n\n resolved.push({\n key: definition.key,\n engine,\n driverPackage,\n connectionString,\n adminConnectionString: readVar(env, \"ADMIN_CONNECTION_STRING\", suffix),\n readConnectionString: readVar(env, \"DATABASE_READ_URL\", suffix),\n isDefault: definition.key === DEFAULT_DATA_SOURCE_KEY,\n poolConfig\n });\n }\n\n if (!resolved.some(r => r.isDefault)) {\n // A default declared as `direct` still fails here, and must: the driver\n // registry promotes whatever driver it has to be the default, so a\n // project in that shape would route every collection that names no data\n // source into some *other* project database. Refusing is the only\n // outcome that cannot silently write to the wrong place.\n const directDefault = declared.some(\n d => d.key === DEFAULT_DATA_SOURCE_KEY && (d.transport ?? \"server\") !== \"server\"\n );\n throw new BundleError(\n directDefault\n ? `The default data source is declared with a non-server transport, so the backend ` +\n \"holds no connection for it — but collections that name no data source still need one.\"\n : \"No default data source is configured.\",\n directDefault\n ? `Give \"${DEFAULT_DATA_SOURCE_KEY}\" a server transport and set DATABASE_URL, or point ` +\n \"every collection at an explicit dataSource.\"\n : `Declare a data source with key \"${DEFAULT_DATA_SOURCE_KEY}\", or set DATABASE_URL.`\n );\n }\n\n return resolved;\n}\n\nfunction resolvePoolConfig(env: EnvBag, suffix: string): Record<string, number> | undefined {\n const entries: Record<string, number> = {};\n const max = readVar(env, \"DB_POOL_MAX\", suffix);\n const idle = readVar(env, \"DB_POOL_IDLE_TIMEOUT\", suffix);\n const connect = readVar(env, \"DB_POOL_CONNECT_TIMEOUT\", suffix);\n\n if (max !== undefined) entries.max = Number(max);\n if (idle !== undefined) entries.idleTimeoutMillis = Number(idle);\n if (connect !== undefined) entries.connectionTimeoutMillis = Number(connect);\n\n for (const [name, value] of Object.entries(entries)) {\n if (!Number.isFinite(value)) {\n throw new BundleError(`Pool setting \"${name}\" for suffix \"${suffix || \"(default)\"}\" is not a number.`);\n }\n }\n\n return Object.keys(entries).length > 0 ? entries : undefined;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Storage sources\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Build one storage configuration from the variables for a single source.\n *\n * Returns `undefined` when the source has no configuration at all, so an\n * optional bucket that was never set does not fail a boot. The production\n * \"local storage is off\" rule deliberately does *not* live here — it is enforced\n * once, in `initializeStorage`, which logs precisely why storage is disabled.\n * Duplicating it would mean two places to keep in agreement.\n */\nexport function resolveStorageBackend(\n env: EnvBag,\n key: string,\n engineHint: string | undefined,\n defaultBasePath: string\n): BackendStorageConfig | undefined {\n const suffix = envSuffixForKey(key, DEFAULT_STORAGE_SOURCE_KEY);\n const declaredType = readVar(env, \"STORAGE_TYPE\", suffix);\n const type = (declaredType || engineHint || \"\").toLowerCase();\n // Whether the *environment* named this backend, as opposed to inheriting it\n // from a declaration. It decides what a missing bucket means:\n //\n // STORAGE_TYPE__MEDIA=s3 with no bucket → someone configured this and got\n // it wrong. Refuse.\n // `rebase.json` declares media: s3, and\n // the environment says nothing → the bucket has not been\n // attached yet. Not an error.\n //\n // Declaring a source is how a project states its topology, often long before\n // anyone attaches a bucket to it — the console's whole \"declared, not\n // configured\" state. Treating that as a fatal misconfiguration would make\n // the act of declaring a bucket crash-loop the backend until someone\n // configured it, which is precisely the unreadable failure the manifest\n // declaration exists to prevent.\n const explicit = Boolean(declaredType);\n\n if (type === \"s3\") {\n const bucket = readVar(env, \"S3_BUCKET\", suffix);\n if (!bucket) {\n if (!explicit) return undefined;\n throw new BundleError(\n `Storage source \"${key}\" is set to s3 but has no bucket — ` +\n `set ${`S3_BUCKET${suffix}`}.`\n );\n }\n const accessKeyId = readVar(env, \"S3_ACCESS_KEY_ID\", suffix);\n const secretAccessKey = readVar(env, \"S3_SECRET_ACCESS_KEY\", suffix);\n // A bucket with no credentials cannot work, and failing here is far\n // clearer than what it does otherwise: `S3StorageController` passes an\n // explicit `credentials: { accessKeyId: \"\", secretAccessKey: \"\" }` to the\n // AWS SDK, which suppresses the SDK's own credential chain — so this\n // never silently falls back to an instance profile or IRSA. It signs\n // every request with nothing and fails each one separately, at upload\n // time, with an opaque signing error.\n //\n // Same rule the control plane applies when it classifies a tenant's\n // environment for the build log, so the log and the runtime agree on\n // what this configuration is.\n if (!accessKeyId || !secretAccessKey) {\n if (!explicit) return undefined;\n const missing = [\n !accessKeyId && `S3_ACCESS_KEY_ID${suffix}`,\n !secretAccessKey && `S3_SECRET_ACCESS_KEY${suffix}`\n ].filter(Boolean).join(\" and \");\n throw new BundleError(\n `Storage source \"${key}\" is set to s3 with a bucket but no credentials — set ${missing}.`,\n \"A bucket without credentials cannot be reached: every upload fails when the request is signed.\"\n );\n }\n\n return {\n type: \"s3\",\n bucket,\n region: readVar(env, \"S3_REGION\", suffix) || \"auto\",\n accessKeyId,\n secretAccessKey,\n endpoint: readVar(env, \"S3_ENDPOINT\", suffix),\n forcePathStyle: readBool(env, \"S3_FORCE_PATH_STYLE\", suffix)\n };\n }\n\n if (type === \"gcs\") {\n const bucket = readVar(env, \"GCS_BUCKET\", suffix);\n if (!bucket) {\n if (!explicit) return undefined;\n throw new BundleError(\n `Storage source \"${key}\" is set to gcs but has no bucket — ` +\n `set ${`GCS_BUCKET${suffix}`}.`\n );\n }\n return {\n type: \"gcs\",\n bucket,\n projectId: readVar(env, \"GCS_PROJECT_ID\", suffix),\n keyFilename: readVar(env, \"GCS_KEY_FILENAME\", suffix)\n };\n }\n\n if (type === \"local\" || type === \"\") {\n return {\n type: \"local\",\n basePath: readVar(env, \"STORAGE_PATH\", suffix) || defaultBasePath\n };\n }\n\n throw new BundleError(\n `Storage source \"${key}\" has unsupported type \"${type}\".`,\n \"Supported types are local, s3 and gcs. For anything else, pass a StorageController.\"\n );\n}\n\n/**\n * Resolve every server-transport storage source into a controller config map.\n *\n * The returned shape is the `Record<key, config>` the backend already accepts,\n * so multiple buckets need nothing new downstream — they were always supported,\n * they just had no way to be configured from the environment.\n */\nexport function resolveStorageSources(\n env: EnvBag,\n definitions: StorageSourceDefinition[] | undefined,\n defaultBasePath: string\n): Record<string, BackendStorageConfig> | undefined {\n const declared = definitions ?? [];\n assertDistinctSuffixes(declared, DEFAULT_STORAGE_SOURCE_KEY, \"Storage source\");\n\n const serverSide = declared.filter(d => (d.transport ?? \"server\") === \"server\");\n\n // Synthesize the default bucket only when the project declared *nothing*.\n //\n // Inventing one alongside explicitly declared sources is actively harmful.\n // The synthesized default falls through to local disk; production drops local\n // backends (files written there die with the container); the storage registry\n // then promotes whichever backend remains to be the default. So a project\n // declaring only a \"media\" bucket would put its default uploads on local disk\n // in development and in the media bucket in production. Two different\n // destinations either side of a deploy is worse than having no default\n // bucket, which at least fails the same way in both.\n const effective: { key: string; engine?: string }[] = declared.length === 0\n ? [{ key: DEFAULT_STORAGE_SOURCE_KEY,\nengine: undefined }]\n : serverSide;\n\n const result: Record<string, BackendStorageConfig> = {};\n for (const definition of effective) {\n const config = resolveStorageBackend(\n env,\n definition.key,\n definition.engine,\n defaultBasePath\n );\n if (config) result[definition.key] = config;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Read a project's declared storage sources from its `rebase.json`.\n *\n * A managed bundle carries its topology in `manifest.json`, resolved at build\n * time. A **custom** runtime has no manifest — it builds its own image and its\n * own entrypoint — so without this it would have to re-declare in code what\n * `rebase.json` already says, and the two would drift. Since a custom image\n * contains the repository anyway, reading the file it already ships is what\n * keeps one declaration authoritative for both runtimes.\n *\n * Walks up from `startDir` because an entrypoint lives at `backend/src` in the\n * scaffolded layout and somewhere else in a hand-rolled one. A missing,\n * unreadable or malformed file means \"declared nothing\" — one default source —\n * which is the correct reading of every project that predates this and must\n * never be an error: a storage declaration is optional, and failing to boot a\n * whole backend over an absent optional file would be the worse bug.\n */\nexport function loadDeclaredStorageSources(\n startDir: string,\n levels = 5\n): StorageSourceDefinition[] {\n let dir = startDir;\n for (let i = 0; i <= levels; i++) {\n const candidate = path.join(dir, \"rebase.json\");\n if (fs.existsSync(candidate)) {\n // Only the read and the parse degrade quietly. What the file *says*\n // is validated outside this catch on purpose: a collision between two\n // source keys is precisely the failure this loader exists to prevent,\n // and swallowing it would turn \"these two buckets would read each\n // other's credentials\" into \"this project declared nothing\" — the\n // silent wrong answer instead of the loud right one.\n let declared: DeclaredStorageSources | undefined;\n try {\n declared = (JSON.parse(fs.readFileSync(candidate, \"utf8\")) as {\n storage?: DeclaredStorageSources;\n })?.storage;\n } catch (err) {\n logger.warn(\n `Could not read storage sources from ${candidate}: ` +\n `${err instanceof Error ? err.message : String(err)}. ` +\n \"Continuing with a single default storage source.\"\n );\n return [];\n }\n const sources = normalizeStorageSources(declared, undefined);\n assertDistinctSuffixes(sources, DEFAULT_STORAGE_SOURCE_KEY, \"Storage source\");\n return sources;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return [];\n}\n","/**\n * Telling a *stale* driver apart from a driver that never had the feature.\n *\n * The managed runtime is two halves that version independently. The image\n * supplies `@rebasepro/server` — `docker/entrypoint.mjs` symlinks it over\n * whatever the bundle installed, so the boot harness is always the image's. The\n * **driver** is not redirected: `@rebasepro/server-postgres` comes from the\n * bundle's `deps.declared`, pinned to whatever the project's `package.json`\n * asked npm for. Shipping a new image therefore does not ship a new driver, and\n * a fix that spans both packages reaches a tenant only after an npm publish AND\n * a rebuild.\n *\n * That split has a nasty failure mode, and it has already burned a day. Boot\n * looks for an optional capability, does not find it, and reports the honest\n * local fact — \"this driver does not implement collection-table creation\" —\n * which is exactly what a schemaless driver looks like. But a driver that is\n * merely *older than the runtime asking* looks identical, and the two want\n * opposite responses: one is \"this database is not managed by Rebase, carry on\",\n * the other is \"your tables were never created and every data route is about to\n * 500\". Naming the versions is what separates them, so these helpers exist to\n * put both numbers in front of whoever reads the log.\n */\nimport fs from \"fs\";\nimport path from \"path\";\n\n/** The package whose version defines \"the runtime\" for skew purposes. */\nconst RUNTIME_PACKAGE = \"@rebasepro/server\";\n\n/**\n * Locate a package by walking `node_modules` up from a directory.\n *\n * Lives here rather than in `driver.ts` because both the driver loader and the\n * version check need it, and `driver.ts` already imports this module.\n */\nexport function findPackageDir(fromDir: string, packageName: string): string | undefined {\n let dir = path.resolve(fromDir);\n for (;;) {\n const candidate = path.join(dir, \"node_modules\", ...packageName.split(\"/\"));\n if (fs.existsSync(path.join(candidate, \"package.json\"))) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\ninterface ParsedVersion {\n parts: number[];\n /** `canary.g7f1150f` in `0.12.1-canary.g7f1150f`, absent on a release. */\n prerelease?: string;\n}\n\n/**\n * Parse the subset of semver the workspace actually publishes.\n *\n * Deliberately lenient: an unparseable version yields `undefined` and every\n * comparison then declines to judge, because a wrong \"your driver is old\"\n * warning on a fork's custom version string is worse than no warning at all.\n */\nfunction parseVersion(version: string): ParsedVersion | undefined {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(.+))?$/.exec(version.trim());\n if (!match) return undefined;\n return {\n parts: [Number(match[1]), Number(match[2]), Number(match[3])],\n prerelease: match[4]\n };\n}\n\n/**\n * Compare two versions, or `undefined` when either cannot be parsed.\n *\n * Follows semver on the one rule that matters here: a prerelease sorts *below*\n * the release it leads to, so `0.12.1-canary.g7f1150f` < `0.12.1`. Without that\n * rule every canary would read as newer than the stable it precedes, and the\n * canaries are precisely where fixes land first.\n */\nexport function compareVersions(a: string, b: string): number | undefined {\n const left = parseVersion(a);\n const right = parseVersion(b);\n if (!left || !right) return undefined;\n\n for (let i = 0; i < 3; i++) {\n if (left.parts[i] !== right.parts[i]) return left.parts[i] < right.parts[i] ? -1 : 1;\n }\n if (left.prerelease === right.prerelease) return 0;\n if (left.prerelease === undefined) return 1;\n if (right.prerelease === undefined) return -1;\n return left.prerelease < right.prerelease ? -1 : 1;\n}\n\nexport interface DriverSkew {\n /** True only when both versions parsed AND the driver is genuinely older. */\n stale: boolean;\n /**\n * A clause naming both versions, ready to append to a sentence. Present\n * whenever both versions are known — including when they agree, because\n * \"the driver is current\" is the fact that redirects an investigation away\n * from staleness and toward the real cause.\n */\n detail?: string;\n}\n\n/**\n * Describe how a driver's version relates to the runtime asking it for work.\n *\n * Returns `stale: false` whenever it cannot tell — an unknown version, an\n * unparseable one, a driver that is newer. Silence beats a confident wrong\n * diagnosis, and the caller still prints its own local fact either way.\n */\nexport function describeDriverSkew(\n driverVersion: string | undefined,\n runtimeVersion: string | undefined\n): DriverSkew {\n if (!driverVersion || !runtimeVersion) return { stale: false };\n const order = compareVersions(driverVersion, runtimeVersion);\n if (order === undefined) return { stale: false };\n if (order < 0) {\n return {\n stale: true,\n detail:\n `The driver is at ${driverVersion} while this runtime is ${runtimeVersion} — ` +\n \"the driver is OLDER, so this is very likely a stale pin rather than a driver \" +\n \"that never had the capability.\"\n };\n }\n return {\n stale: false,\n detail: `Driver ${driverVersion}, runtime ${runtimeVersion}.`\n };\n}\n\n/**\n * How to get a project's schema applied, written once and owned by the runtime.\n *\n * This text lives in `@rebasepro/server` on purpose. The equivalent guidance in\n * the Postgres driver's schema-drift warning can only ever be as current as the\n * driver a tenant pinned — so the tenants who most need to be told \"your driver\n * is too old\" are exactly the ones whose driver still prints the old advice.\n * The image's copy of this package is never stale, so guidance printed from\n * here always reflects the platform as it is today.\n *\n * Both audiences get a line because the runtime cannot reliably tell which one\n * it is serving, and naming only the pnpm scripts — as this once did everywhere\n * — tells a managed operator to run a command that structurally cannot reach\n * their in-cluster database.\n */\nexport function schemaRecoveryGuidance(options: { staleDriver?: boolean } = {}): string {\n const lines = [\n \" To apply this project's schema:\",\n \" • Managed cloud: the runtime applies tables and RLS at boot (unless\",\n \" REBASE_MIGRATE_ON_BOOT=none). `rebase db push` cannot reach a tenant's\",\n \" in-cluster database — redeploy instead.\"\n ];\n if (options.staleDriver) {\n lines.push(\n \" Because the driver is pinned by your bundle, bump the\",\n \" `@rebasepro/server-postgres` version in your project's package.json\",\n \" and redeploy — a newer platform image alone will NOT update it.\"\n );\n }\n lines.push(\" • Self-host: run `rebase db push` (dev) or `rebase db migrate` (prod).\");\n return lines.join(\"\\n\");\n}\n\n/**\n * The installed version of a package, read from its `package.json`.\n *\n * Returns `undefined` rather than throwing for every failure — a missing or\n * malformed manifest degrades the diagnosis, and must never take down a boot\n * that would otherwise have served.\n */\nexport function readPackageVersion(packageDir: string): string | undefined {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(packageDir, \"package.json\"), \"utf8\")) as {\n version?: unknown;\n };\n return typeof pkg.version === \"string\" ? pkg.version : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The version of `@rebasepro/server` this deployment is actually running.\n *\n * Resolved from the same roots the drivers are, and that is the point rather\n * than a convenience. In a managed container `docker/entrypoint.mjs` replaces\n * `/bundle/node_modules/@rebasepro/server` with a link to the image's copy, so\n * reading the manifest *through the bundle* reports the version that will\n * really execute — which is exactly the number the driver has to be compared\n * against. Reading this package's own manifest by module path would report the\n * same thing in the happy case and quietly lie in the case that matters: a\n * bundle whose link did not happen.\n *\n * Returns `undefined` when the package cannot be found; every caller treats\n * that as \"cannot judge\" and stays quiet.\n */\nexport function readRuntimeVersion(roots: string[]): string | undefined {\n for (const root of roots) {\n const dir = findPackageDir(root, RUNTIME_PACKAGE);\n const version = dir ? readPackageVersion(dir) : undefined;\n if (version) return version;\n }\n return undefined;\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport type {\n BackendBootstrapper,\n DatabaseAdapter,\n DatabaseAdapterInitConfig,\n InitializedDriver\n} from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\nimport { BundleError } from \"./bundle\";\nimport type { ResolvedDataSourceConfig } from \"./sources\";\nimport { findPackageDir, readPackageVersion } from \"./version-skew\";\n\n/**\n * Database drivers are loaded by name at runtime rather than imported.\n *\n * They have to be: every driver package depends on this one (it implements the\n * adapter interfaces defined here), so a static import would be a cycle. Loading\n * by name also keeps the runtime honestly database-agnostic — the image has no\n * opinion about Postgres, it resolves whichever driver each data source declares.\n */\n\n/** What a driver package must export to be bootable. */\ninterface DriverModule {\n createDatabaseConnection?: DriverConnectionFactory;\n createPostgresDatabaseConnection?: DriverConnectionFactory;\n createAdapter?: DriverAdapterFactory;\n createPostgresAdapter?: DriverAdapterFactory;\n}\n\ntype DriverConnectionFactory = (\n connectionString: string,\n schema?: Record<string, unknown>,\n poolConfig?: Record<string, unknown>\n) => DriverConnection;\n\ntype DriverAdapterFactory = (config: Record<string, unknown>) => DatabaseAdapter;\n\n/**\n * The connection handle a driver hands back at boot: the client object, the\n * pool to close on shutdown, and how to probe it.\n *\n * Named `DatabaseConnection` until that collided with `DatabaseConnection` in\n * `@rebasepro/types` — an abstract `{ type, isConnected, close() }` that\n * `MongoDBConnection` implements. The two share no field, and both are public:\n * one is re-exported from `@rebasepro/server`'s index, the other from\n * `@rebasepro/types`, packages that are installed together.\n */\nexport interface DriverConnection {\n db: unknown;\n /**\n * Present for pool-based drivers. Closed during shutdown, and used to probe\n * the source for health — `query` lives here, not on the connection itself.\n */\n pool?: {\n end: () => Promise<void>;\n query?: (sql: string) => Promise<unknown>;\n };\n /** Some drivers expose a query directly instead of via a pool. */\n query?: (sql: string) => Promise<unknown>;\n connectionString?: string;\n}\n\n/**\n * Run a trivial query against a source, to see whether it answers.\n *\n * Returns `undefined` when the driver exposes no way to ask — a driver that\n * cannot be probed must not be reported as unhealthy, only as unknown.\n */\nexport async function probeDataSource(\n source: InitializedDataSource\n): Promise<{ healthy: boolean; error?: string } | undefined> {\n const query = source.connection.query ?? source.connection.pool?.query;\n if (typeof query !== \"function\") return undefined;\n\n try {\n await query.call(source.connection.pool ?? source.connection, \"SELECT 1\");\n return { healthy: true };\n } catch (err) {\n return {\n healthy: false,\n error: err instanceof Error ? err.message : String(err)\n };\n }\n}\n\n/** One initialized data source: its bootstrapper plus the handle to close. */\nexport interface InitializedDataSource {\n key: string;\n engine: string;\n driverPackage: string;\n /**\n * The driver's installed version, when it could be read.\n *\n * Carried so a boot that finds a capability missing can say whether the\n * driver is *old* or merely *different* — see `version-skew.ts`. Optional\n * because a driver resolved from outside a `node_modules` tree (a linked\n * workspace, a bare specifier) has no manifest to read, and that must not\n * be fatal.\n */\n driverVersion?: string;\n bootstrapper: BackendBootstrapper;\n connection: DriverConnection;\n}\n\nexport interface BundleSchema {\n tables?: Record<string, unknown>;\n enums?: Record<string, unknown>;\n relations?: Record<string, unknown>;\n}\n\n/**\n * Where to look for packages a bundle brought with it.\n *\n * A driver has to be resolved relative to the **bundle**, not to this package.\n * A bare `import(\"@rebasepro/server-postgres\")` resolves from wherever the\n * runtime itself is installed, which on a real deployment is somewhere else\n * entirely — the runtime image holds the server, the bundle holds the project's\n * dependencies. Resolving from the bundle is also the honest semantics: the\n * project declares which driver it uses, so the project's tree is where to look.\n *\n * Several roots, because a driver is installed wherever the project keeps its\n * dependencies: beside a built bundle, but inside the backend package in a\n * workspace running from source.\n */\nexport function bundleResolutionRoots(bundleDir: string): string[] {\n return [\n bundleDir,\n path.join(bundleDir, \"backend\"),\n path.join(bundleDir, \"config\")\n ];\n}\n\n/** The ESM entry a package declares, preferring `exports` over the legacy fields. */\nfunction resolvePackageEntry(packageDir: string): string | undefined {\n let pkg: {\n exports?: unknown;\n module?: string;\n main?: string;\n };\n try {\n pkg = JSON.parse(fs.readFileSync(path.join(packageDir, \"package.json\"), \"utf8\"));\n } catch {\n return undefined;\n }\n\n const fromExports = (value: unknown): string | undefined => {\n if (typeof value === \"string\") return value;\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n // Import first: this is an ESM runtime, and a driver's `require` entry\n // may not exist at all.\n for (const condition of [\"import\", \"module\", \"default\", \"node\"]) {\n const resolved = fromExports(record[condition]);\n if (resolved) return resolved;\n }\n return undefined;\n };\n\n const candidate = (pkg.exports && typeof pkg.exports === \"object\"\n ? fromExports((pkg.exports as Record<string, unknown>[\".\"]) ?? pkg.exports)\n : fromExports(pkg.exports))\n ?? pkg.module\n ?? pkg.main;\n\n if (!candidate) return undefined;\n const entry = path.resolve(packageDir, candidate);\n return fs.existsSync(entry) ? entry : undefined;\n}\n\n/**\n * Import a driver package, resolving its factories under either naming scheme.\n *\n * The generic names are the contract going forward; the Postgres-specific ones\n * are still accepted so a bundle can run against a driver release that predates\n * the generic aliases.\n */\nasync function importDriver(packageName: string, resolveFrom: string[] = []): Promise<{\n createConnection: DriverConnectionFactory;\n createAdapter: DriverAdapterFactory;\n /** Where the driver was found, when it resolved from a `node_modules` tree. */\n packageDir?: string;\n}> {\n let specifier = packageName;\n let resolvedDir: string | undefined;\n\n for (const root of resolveFrom) {\n const packageDir = findPackageDir(root, packageName);\n const entry = packageDir ? resolvePackageEntry(packageDir) : undefined;\n if (entry) {\n specifier = pathToFileURL(entry).href;\n resolvedDir = packageDir;\n break;\n }\n }\n\n let mod: DriverModule;\n try {\n mod = await import(specifier) as DriverModule;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new BundleError(\n `Could not load the database driver \"${packageName}\": ${message}`,\n `Install it alongside the runtime (e.g. \\`npm install ${packageName}\\`), ` +\n \"or point the data source at a different driver with REBASE_DRIVER.\"\n );\n }\n\n const createConnection = mod.createDatabaseConnection || mod.createPostgresDatabaseConnection;\n const createAdapter = mod.createAdapter || mod.createPostgresAdapter;\n\n if (!createConnection || !createAdapter) {\n throw new BundleError(\n `\"${packageName}\" does not look like a Rebase database driver.`,\n \"A driver must export `createDatabaseConnection` and `createAdapter`.\"\n );\n }\n\n return { createConnection, createAdapter, packageDir: resolvedDir };\n}\n\n/**\n * Wrap a `DatabaseAdapter` as a `BackendBootstrapper` carrying a registry id.\n *\n * `initializeRebaseBackend` does this internally for its single-adapter\n * convenience path, but that path hardcodes one anonymous driver. Multiple\n * sources need an explicit `id` per adapter, because the id is exactly what\n * `collection.dataSource` routes against.\n */\nexport function adapterToBootstrapper(\n adapter: DatabaseAdapter,\n id: string,\n isDefault: boolean\n): BackendBootstrapper {\n return {\n type: adapter.type,\n id,\n isDefault,\n initializeDriver: (initConfig: unknown) =>\n adapter.initializeDriver(initConfig as DatabaseAdapterInitConfig),\n initializeRealtime: adapter.initializeRealtime\n ? (_config: unknown, driverResult: InitializedDriver) =>\n adapter.initializeRealtime!(driverResult)\n : undefined,\n initializeAuth: adapter.initializeAuth,\n initializeHistory: adapter.initializeHistory,\n initializeWebsockets: adapter.initializeWebsockets,\n // Load-bearing for a managed boot: the runtime creates a fresh tenant's\n // tables and RLS through these at boot. Dropping them here (the previous\n // shape did) left the schema-ensure feature dead on the real adapter\n // path — `boot.ts` saw no method and skipped, so every data route 500'd\n // on a missing relation with only a \"driver does not implement\" warning.\n ensureCollectionSchema: adapter.ensureCollectionSchema\n ? (collections, driverResult, log) =>\n adapter.ensureCollectionSchema!(collections, driverResult, log)\n : undefined,\n ensureCollectionPolicies: adapter.ensureCollectionPolicies\n ? (collections, driverResult, log) =>\n adapter.ensureCollectionPolicies!(collections, driverResult, log)\n : undefined,\n getAdmin: adapter.getAdmin,\n mountRoutes: adapter.mountRoutes\n };\n}\n\n/**\n * Build a driver for one data source.\n *\n * Only the default source receives the bundle's Drizzle schema: the schema\n * describes the tables generated from this project's collections, which live in\n * the default database. Handing it to a secondary source would tell that\n * driver's adapter about tables it does not have.\n */\nexport async function initializeDataSource(\n source: ResolvedDataSourceConfig,\n schema: BundleSchema | undefined,\n resolveFrom: string[] = []\n): Promise<InitializedDataSource> {\n const { createConnection, createAdapter, packageDir } = await importDriver(source.driverPackage, resolveFrom);\n const driverVersion = packageDir ? readPackageVersion(packageDir) : undefined;\n\n // Every in-tree caller passes `undefined` for the connection's own schema —\n // drizzle only needs it for the relational query API, which the drivers do\n // not use, and passing the grouped bundle schema here would register\n // \"tables\"/\"enums\"/\"relations\" as if they were table names.\n const connection = createConnection(source.connectionString, undefined, source.poolConfig);\n\n const adapter = createAdapter({\n connection: connection.db,\n connectionString: connection.connectionString ?? source.connectionString,\n adminConnectionString: source.adminConnectionString || source.connectionString,\n readConnectionString: source.readConnectionString,\n ...(source.isDefault && schema ? { schema } : {})\n });\n\n logger.info(\"Initialized data source\", {\n key: source.key,\n engine: source.engine,\n driver: source.driverPackage,\n driverVersion\n });\n\n return {\n key: source.key,\n engine: source.engine,\n driverPackage: source.driverPackage,\n driverVersion,\n bootstrapper: adapterToBootstrapper(adapter, source.key, source.isDefault),\n connection\n };\n}\n\n/**\n * Build drivers for every resolved data source.\n *\n * Sequential on purpose: a failure on the second source should not leave a\n * half-opened pool from a third racing behind it, and the log then reads in the\n * order a human would expect.\n */\nexport async function initializeDataSources(\n sources: ResolvedDataSourceConfig[],\n schema: BundleSchema | undefined,\n resolveFrom: string[] = []\n): Promise<InitializedDataSource[]> {\n const initialized: InitializedDataSource[] = [];\n try {\n for (const source of sources) {\n initialized.push(await initializeDataSource(source, schema, resolveFrom));\n }\n } catch (err) {\n // Close whatever did open, so a failed boot does not hold connections\n // against the database while the container restarts.\n await Promise.allSettled(\n initialized.map(s => s.connection.pool?.end())\n );\n throw err;\n }\n return initialized;\n}\n","import type { CollectionConfig } from \"@rebasepro/types\";\nimport type { RebaseAuthConfig } from \"../init\";\nimport type { EmailConfig } from \"../email\";\nimport type { RebaseBootEnv } from \"./env\";\n\n/**\n * Build the email configuration, or `undefined` when no SMTP host is set.\n *\n * Without it the auth adapter still works; password-reset and verification mail\n * simply has nowhere to go, which the auth routes report for themselves.\n */\nexport function resolveEmailOptions(env: RebaseBootEnv): EmailConfig | undefined {\n if (!env.SMTP_HOST) return undefined;\n\n return {\n from: env.SMTP_FROM || `${env.APP_NAME} <noreply@rebase.pro>`,\n smtp: {\n host: env.SMTP_HOST,\n port: env.SMTP_PORT,\n secure: env.SMTP_SECURE,\n auth: env.SMTP_USER\n ? { user: env.SMTP_USER,\npass: env.SMTP_PASS ?? \"\" }\n : undefined,\n name: env.SMTP_NAME\n },\n appName: env.APP_NAME,\n resetPasswordUrl: env.FRONTEND_URL\n };\n}\n\n/**\n * Build the auth configuration from the environment and the bundle's users\n * collection.\n *\n * OAuth providers are included only when both halves of a credential pair are\n * present. Google is the exception the template already made: a client id alone\n * is enough, because the ID-token flow needs no secret.\n */\nexport function resolveAuthOptions(\n env: RebaseBootEnv,\n usersCollection: CollectionConfig | undefined\n): RebaseAuthConfig {\n const auth: RebaseAuthConfig = {\n collection: usersCollection,\n jwtSecret: env.JWT_SECRET,\n accessExpiresIn: env.JWT_ACCESS_EXPIRES_IN,\n refreshExpiresIn: env.JWT_REFRESH_EXPIRES_IN,\n serviceKey: env.REBASE_SERVICE_KEY,\n requireAuth: env.AUTH_REQUIRE,\n allowRegistration: env.ALLOW_REGISTRATION,\n disableSelfRegistration: env.DISABLE_SELF_REGISTRATION,\n allowUserLookup: env.AUTH_ALLOW_USER_LOOKUP,\n email: resolveEmailOptions(env),\n // Cookie auth keeps the refresh token in an httpOnly cookie rather than\n // localStorage, putting it out of reach of XSS. Enabling it costs a\n // token-flow client nothing — the client opts in via `authFlowMode` —\n // so the safer flow is simply always available.\n cookieAuth: { sameSite: env.AUTH_COOKIE_SAME_SITE || \"Lax\" }\n };\n\n if (env.AUTH_DEFAULT_ROLE) {\n auth.defaultRole = env.AUTH_DEFAULT_ROLE;\n }\n\n if (env.GOOGLE_CLIENT_ID) {\n auth.google = {\n clientId: env.GOOGLE_CLIENT_ID,\n clientSecret: env.GOOGLE_CLIENT_SECRET\n };\n }\n if (env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET) {\n auth.github = {\n clientId: env.GITHUB_CLIENT_ID,\n clientSecret: env.GITHUB_CLIENT_SECRET\n };\n }\n if (env.MICROSOFT_CLIENT_ID && env.MICROSOFT_CLIENT_SECRET) {\n auth.microsoft = {\n clientId: env.MICROSOFT_CLIENT_ID,\n clientSecret: env.MICROSOFT_CLIENT_SECRET\n };\n }\n\n return auth;\n}\n","import { Hono } from \"hono\";\nimport type { MiddlewareHandler } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\nimport { safeCompare } from \"../auth/crypto-utils\";\nimport { extractBearerToken } from \"../auth/bearer-token\";\n\n/**\n * Runtime metrics, in Prometheus text format.\n *\n * The point of emitting these from the runtime rather than scraping the\n * container is that only the runtime knows what a request *was*. A pod-level CPU\n * graph cannot tell you that auth is slow while data is fine, or that one app is\n * generating all the traffic. Surface by surface is the difference between a\n * chart that looks like observability and one you can act on.\n *\n * Self-hosters get the same endpoint — this is a plain Prometheus target, not a\n * hook into a hosted platform.\n */\n\n/** Which part of the API served a request. */\nexport type MetricSurface = \"data\" | \"auth\" | \"storage\" | \"functions\" | \"admin\" | \"meta\" | \"other\";\n\nconst LATENCY_BUCKETS_MS = [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000];\n\n/**\n * Separators for the composite map keys used internally.\n *\n * ASCII unit/record separators, which cannot appear in a Prometheus metric name\n * and are vanishingly unlikely in a label value. They are written as escape\n * sequences rather than literal control characters so the source stays greppable\n * and diffable.\n */\nconst LABEL_SEP = \"\\u001f\";\nconst NAME_SEP = \"\\u001e\";\n\ninterface HistogramState {\n counts: number[];\n sum: number;\n total: number;\n}\n\n/**\n * In-process metric store.\n *\n * Counters reset when the process does, which is exactly what Prometheus\n * expects — it handles resets natively, and a restart is a real event a\n * dashboard should be able to see.\n */\n/**\n * Ceiling on distinct label combinations per metric family.\n *\n * Label values that vary without bound are the classic way to take down a\n * Prometheus — and, before that, the process emitting them, since every distinct\n * combination allocates a permanent series. The label set here is derived partly\n * from request paths, so it is reachable by anyone who can send a request.\n * Beyond the cap, series collapse into a single `(other)` bucket: the totals stay\n * correct and memory stops growing.\n */\nconst MAX_SERIES = 512;\n\nexport class MetricsRegistry {\n private requests = new Map<string, number>();\n private latency = new Map<string, HistogramState>();\n private gauges = new Map<string, number>();\n private counters = new Map<string, number>();\n readonly startedAt = Date.now();\n\n private static labelKey(labels: Record<string, string>): string {\n return Object.entries(labels)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([k, v]) => `${k}=${v}`)\n .join(LABEL_SEP);\n }\n\n private static parseLabels(key: string): Record<string, string> {\n if (!key) return {};\n return Object.fromEntries(\n key.split(LABEL_SEP).filter(Boolean).map(pair => {\n const index = pair.indexOf(\"=\");\n return [pair.slice(0, index), pair.slice(index + 1)];\n })\n );\n }\n\n /**\n * Key a named series.\n *\n * Concatenating a name and its labels without a separator would let metric\n * `rebase_x` with label `y=1` collide with a metric literally named\n * `rebase_xy=1`.\n */\n private static namedKey(name: string, labels: Record<string, string>): string {\n return `${name}${NAME_SEP}${MetricsRegistry.labelKey(labels)}`;\n }\n\n private static splitNamedKey(key: string): [string, string] {\n const index = key.indexOf(NAME_SEP);\n if (index === -1) return [key, \"\"];\n return [key.slice(0, index), key.slice(index + NAME_SEP.length)];\n }\n\n recordRequest(labels: Record<string, string>, durationMs: number): void {\n let key = MetricsRegistry.labelKey(labels);\n\n if (!this.requests.has(key) && this.requests.size >= MAX_SERIES) {\n // Only the collection label can grow without bound, so only it is\n // collapsed — rewriting a request that never had one would invent a\n // `collection=\"(other)\"` on, say, an auth request and make the\n // output misleading rather than merely coarser.\n const { collection: _dropped, ...rest } = labels;\n key = MetricsRegistry.labelKey(\n \"collection\" in labels ? { ...rest,\n collection: \"(other)\" } : rest\n );\n }\n\n this.requests.set(key, (this.requests.get(key) ?? 0) + 1);\n\n let hist = this.latency.get(key);\n if (!hist) {\n hist = { counts: new Array(LATENCY_BUCKETS_MS.length + 1).fill(0),\nsum: 0,\ntotal: 0 };\n this.latency.set(key, hist);\n }\n hist.sum += durationMs;\n hist.total += 1;\n let bucket = LATENCY_BUCKETS_MS.findIndex(upper => durationMs <= upper);\n if (bucket === -1) bucket = LATENCY_BUCKETS_MS.length;\n hist.counts[bucket] += 1;\n }\n\n incrementCounter(name: string, labels: Record<string, string> = {}, by = 1): void {\n const key = MetricsRegistry.namedKey(name, labels);\n // Capped for the same reason request series are: whatever calls this\n // next may well pass something request-derived.\n if (!this.counters.has(key) && this.counters.size >= MAX_SERIES) return;\n this.counters.set(key, (this.counters.get(key) ?? 0) + by);\n }\n\n setGauge(name: string, value: number, labels: Record<string, string> = {}): void {\n const key = MetricsRegistry.namedKey(name, labels);\n if (!this.gauges.has(key) && this.gauges.size >= MAX_SERIES) return;\n this.gauges.set(key, value);\n }\n\n /** Prometheus escaping: backslash, quote and newline, in that order. */\n private static formatLabels(labels: Record<string, string>, extra?: Record<string, string>): string {\n const all = { ...labels,\n...extra };\n const entries = Object.entries(all).filter(([, v]) => v !== undefined && v !== \"\");\n if (entries.length === 0) return \"\";\n const body = entries\n .map(([k, v]) => `${k}=\"${String(v).replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, \"\\\\\\\"\").replace(/\\n/g, \"\\\\n\")}\"`)\n .join(\",\");\n return `{${body}}`;\n }\n\n /** Group `name -> [[labelKey, value]]` for one-HELP-per-metric rendering. */\n private static group(source: Map<string, number>): Map<string, [string, number][]> {\n const grouped = new Map<string, [string, number][]>();\n for (const [key, value] of source) {\n const [name, labelKey] = MetricsRegistry.splitNamedKey(key);\n const list = grouped.get(name) ?? [];\n list.push([labelKey, value]);\n grouped.set(name, list);\n }\n return grouped;\n }\n\n render(): string {\n const lines: string[] = [];\n\n lines.push(\"# HELP rebase_uptime_seconds Seconds since this runtime started.\");\n lines.push(\"# TYPE rebase_uptime_seconds gauge\");\n lines.push(`rebase_uptime_seconds ${((Date.now() - this.startedAt) / 1000).toFixed(0)}`);\n\n lines.push(\"# HELP rebase_requests_total Requests handled, by surface, method and status.\");\n lines.push(\"# TYPE rebase_requests_total counter\");\n for (const [key, value] of this.requests) {\n lines.push(`rebase_requests_total${MetricsRegistry.formatLabels(MetricsRegistry.parseLabels(key))} ${value}`);\n }\n\n lines.push(\"# HELP rebase_request_duration_ms Request latency in milliseconds.\");\n lines.push(\"# TYPE rebase_request_duration_ms histogram\");\n for (const [key, hist] of this.latency) {\n const labels = MetricsRegistry.parseLabels(key);\n let cumulative = 0;\n for (let i = 0; i < LATENCY_BUCKETS_MS.length; i++) {\n cumulative += hist.counts[i];\n lines.push(\n `rebase_request_duration_ms_bucket${MetricsRegistry.formatLabels(labels, { le: String(LATENCY_BUCKETS_MS[i]) })} ${cumulative}`\n );\n }\n cumulative += hist.counts[LATENCY_BUCKETS_MS.length];\n lines.push(`rebase_request_duration_ms_bucket${MetricsRegistry.formatLabels(labels, { le: \"+Inf\" })} ${cumulative}`);\n lines.push(`rebase_request_duration_ms_sum${MetricsRegistry.formatLabels(labels)} ${hist.sum.toFixed(3)}`);\n lines.push(`rebase_request_duration_ms_count${MetricsRegistry.formatLabels(labels)} ${hist.total}`);\n }\n\n for (const [name, entries] of MetricsRegistry.group(this.counters)) {\n lines.push(`# TYPE ${name} counter`);\n for (const [labelKey, value] of entries) {\n lines.push(`${name}${MetricsRegistry.formatLabels(MetricsRegistry.parseLabels(labelKey))} ${value}`);\n }\n }\n\n for (const [name, entries] of MetricsRegistry.group(this.gauges)) {\n lines.push(`# TYPE ${name} gauge`);\n for (const [labelKey, value] of entries) {\n lines.push(`${name}${MetricsRegistry.formatLabels(MetricsRegistry.parseLabels(labelKey))} ${value}`);\n }\n }\n\n const memory = process.memoryUsage();\n lines.push(\"# TYPE rebase_process_heap_bytes gauge\");\n lines.push(`rebase_process_heap_bytes ${memory.heapUsed}`);\n lines.push(\"# TYPE rebase_process_rss_bytes gauge\");\n lines.push(`rebase_process_rss_bytes ${memory.rss}`);\n\n return lines.join(\"\\n\") + \"\\n\";\n }\n}\n\n/**\n * Classify a path into the surface that served it.\n *\n * Path *shape*, never the full path: a label per entity id would create an\n * unbounded set of time series, which is the classic way to take down a\n * Prometheus. Collection slugs are bounded by the schema, so those are safe and\n * genuinely useful.\n */\nexport function classifySurface(pathname: string, basePath = \"/api\"): {\n surface: MetricSurface;\n collection?: string;\n} {\n const prefix = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n if (!pathname.startsWith(prefix)) {\n return { surface: \"other\" };\n }\n\n const rest = pathname.slice(prefix.length).replace(/^\\/+/, \"\");\n const [head, second] = rest.split(\"/\");\n\n switch (head) {\n case \"data\":\n return { surface: \"data\",\ncollection: second || undefined };\n case \"auth\":\n return { surface: \"auth\" };\n case \"storage\":\n return { surface: \"storage\" };\n case \"functions\":\n return { surface: \"functions\",\ncollection: second || undefined };\n case \"admin\":\n return { surface: \"admin\" };\n case \"meta\":\n return { surface: \"meta\" };\n default:\n return { surface: \"other\" };\n }\n}\n\nexport interface MetricsHandle {\n registry: MetricsRegistry;\n middleware: MiddlewareHandler<HonoEnv>;\n /**\n * Restrict the `collection` label to names that actually exist.\n *\n * Called once the collections are known — the middleware has to be installed\n * before them, since it must wrap every request. Until it is called, and for\n * any name not in the set, the label is dropped: a path segment is attacker-\n * controlled, and one series per value invented is unbounded memory.\n */\n setKnownCollections(slugs: Iterable<string>): void;\n}\n\n/**\n * Build the request-timing middleware and the registry it feeds.\n *\n * Timing wraps `next()` in a `finally`, so a request that throws is still\n * counted — an endpoint that only ever fails would otherwise be invisible in\n * exactly the situation the metrics exist for.\n */\nexport function createMetricsMiddleware(basePath = \"/api\"): MetricsHandle {\n const registry = new MetricsRegistry();\n let known: Set<string> | undefined;\n\n const middleware: MiddlewareHandler<HonoEnv> = async (c, next) => {\n const started = performance.now();\n const { surface, collection } = classifySurface(new URL(c.req.url).pathname, basePath);\n\n try {\n await next();\n } finally {\n const duration = performance.now() - started;\n const labels: Record<string, string> = {\n surface,\n method: c.req.method,\n status: String(c.res?.status ?? 0)\n };\n // Only a name the schema knows about becomes a label. A request for\n // `/api/data/<random>` is a 404, and recording it by name would let\n // anyone mint unlimited time series just by sending requests.\n if (collection && known?.has(collection)) labels.collection = collection;\n registry.recordRequest(labels, duration);\n }\n };\n\n return {\n registry,\n middleware,\n setKnownCollections(slugs: Iterable<string>) {\n known = new Set(slugs);\n }\n };\n}\n\n/**\n * Mount the scrape endpoint.\n *\n * When a token is configured it is required, and compared in constant time — a\n * timing oracle on a metrics token is a small thing, but it is free to avoid.\n */\nexport function createMetricsRoutes(registry: MetricsRegistry, token?: string): Hono<HonoEnv> {\n const router = new Hono<HonoEnv>();\n\n router.get(\"/\", (c) => {\n if (token) {\n const provided = extractBearerToken(c.req.header(\"authorization\")) ?? \"\";\n if (!provided || !safeCompare(provided, token)) {\n return c.text(\"Unauthorized\", 401);\n }\n }\n return c.text(registry.render(), 200, {\n \"Content-Type\": \"text/plain; version=0.0.4; charset=utf-8\"\n });\n });\n\n return router;\n}\n","/**\n * Fetching a bundle at boot, for platforms with no init container.\n *\n * A bundle normally arrives on disk before the process starts: `rebase build`\n * writes one, a container image carries one, and on Kubernetes an init container\n * fetches one into a shared volume before the runtime container runs. All three\n * mean `runFromBundle` can assume the files are already there.\n *\n * Serverless platforms have no init container. Cloud Run starts one container\n * and nothing else, so the choice is between baking a per-tenant image — a build\n * on every deploy and an image per tenant to garbage-collect — or fetching at\n * boot. This is the second.\n *\n * ## Every start, not just the first\n *\n * The fetch has to be cheap and repeatable because it runs on *every* cold\n * start: a scale-from-zero, an instance recycled after an hour idle, a new\n * revision. That is also why the platform's bundle URL is deliberately a stable\n * endpoint rather than a signed expiring one — an instance starting for the\n * first time in three days needs the same URL to work.\n *\n * ## It refuses rather than half-unpacking\n *\n * Every failure here — a URL that 403s, a truncated download, a tarball that\n * unpacks to something without a manifest — exits non-zero before the runtime\n * boots. A partially-unpacked bundle would boot into a confusing failure much\n * later: missing collections read as an empty schema, and\n * `REBASE_MIGRATE_ON_BOOT=ensure` would then happily create nothing and report\n * success. Failing at the fetch is the only place the error still says what is\n * actually wrong.\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst run = promisify(execFile);\n\n/** Where the runtime is told to fetch its bundle from. */\nexport const BUNDLE_URL_ENV = \"REBASE_BUNDLE_URL\";\n/** Bearer token for that fetch. Does not expire — see the module note. */\nexport const BUNDLE_TOKEN_ENV = \"REBASE_BUNDLE_TOKEN\";\n\nexport interface FetchBundleOptions {\n url: string;\n token?: string;\n /** Where to unpack. Defaults to a fresh directory under the OS temp dir. */\n destination?: string;\n /** Injected for tests. */\n fetchImpl?: typeof fetch;\n /** Injected for tests. */\n extract?: (tarball: string, destination: string) => Promise<void>;\n /** How long the download may take before it is abandoned. */\n timeoutMs?: number;\n}\n\n/**\n * Whether this process should fetch its bundle rather than read one from disk.\n *\n * An explicit `REBASE_BUNDLE` — a path — always wins. A platform that mounted a\n * bundle AND set a URL means somebody is mid-migration between the two, and the\n * local copy is the one that is definitely there.\n */\nexport function shouldFetchBundle(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env[BUNDLE_URL_ENV]) && !env.REBASE_BUNDLE;\n}\n\n/** Untar with the system `tar`, which every base image has. */\nasync function extractWithTar(tarball: string, destination: string): Promise<void> {\n // `-m` (do not restore mtimes) because some sandboxes reject utimes on\n // extracted files and the failure looks like a corrupt archive.\n await run(\"tar\", [\"-xzmf\", tarball, \"-C\", destination]);\n}\n\n/**\n * Download and unpack a bundle, returning the directory it landed in.\n *\n * Downloads to a file rather than streaming into `tar`, deliberately. A stream\n * that dies mid-transfer leaves `tar` having successfully extracted a prefix of\n * the archive and exiting 0 — the half-unpacked bundle this module exists to\n * refuse. Writing the whole tarball first means a truncated download is caught\n * by `tar` as a corrupt archive, which is an error.\n */\nexport async function fetchBundle(options: FetchBundleOptions): Promise<string> {\n const fetchImpl = options.fetchImpl ?? fetch;\n const extract = options.extract ?? extractWithTar;\n\n const destination = options.destination\n ?? fs.mkdtempSync(path.join(os.tmpdir(), \"rebase-bundle-\"));\n fs.mkdirSync(destination, { recursive: true });\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 60_000);\n\n let response: Response;\n try {\n response = await fetchImpl(options.url, {\n headers: options.token ? { authorization: `Bearer ${options.token}` } : {},\n signal: controller.signal\n });\n } catch (error: unknown) {\n throw new Error(\n `Could not download the bundle from ${options.url}: ` +\n (error instanceof Error ? error.message : String(error))\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n // The status is the diagnosis: 401/403 is a bad or missing token, 404 is\n // a bundle that was garbage-collected out from under a running service.\n throw new Error(\n `Could not download the bundle from ${options.url}: ${response.status} ${response.statusText}`\n );\n }\n\n const tarball = path.join(destination, \"bundle.tar.gz\");\n const body = Buffer.from(await response.arrayBuffer());\n if (body.length === 0) {\n throw new Error(`The bundle at ${options.url} is empty.`);\n }\n fs.writeFileSync(tarball, body);\n\n try {\n await extract(tarball, destination);\n } catch (error: unknown) {\n throw new Error(\n `The bundle downloaded from ${options.url} could not be unpacked ` +\n `(${body.length} bytes): ` + (error instanceof Error ? error.message : String(error))\n );\n } finally {\n // The archive is dead weight in an instance whose memory-backed temp\n // directory counts against its limit, and a Cloud Run instance's /tmp is\n // a tmpfs — leaving it there costs real memory for the life of the\n // instance.\n fs.rmSync(tarball, { force: true });\n }\n\n const root = bundleRootIn(destination);\n if (!root) {\n throw new Error(\n `The bundle downloaded from ${options.url} unpacked without a rebase-bundle.json. ` +\n `It is not a Rebase bundle, or it was truncated.`\n );\n }\n return root;\n}\n\n/**\n * Find the bundle root inside an unpacked directory.\n *\n * Tolerates one level of nesting, because whether a tarball has a top-level\n * directory depends on how it was created — `tar czf x.tgz dist-bundle` and\n * `tar czf x.tgz -C dist-bundle .` produce different shapes from the same\n * files, and both are things a build script does.\n */\nexport function bundleRootIn(directory: string): string | null {\n if (fs.existsSync(path.join(directory, \"rebase-bundle.json\"))) return directory;\n\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const nested = path.join(directory, entry.name);\n if (fs.existsSync(path.join(nested, \"rebase-bundle.json\"))) return nested;\n }\n return null;\n}\n","import path from \"path\";\nimport { createServer, type Server } from \"http\";\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { secureHeaders } from \"hono/secure-headers\";\nimport { getRequestListener } from \"@hono/node-server\";\nimport {\n DEFAULT_DATA_SOURCE_KEY,\n normalizeStorageSources,\n type DataSourceDefinition,\n type InitializedDriver,\n type StorageSourceDefinition\n} from \"@rebasepro/types\";\n\nimport { initializeRebaseBackend, type RebaseBackendInstance } from \"../init\";\nimport { loadCollectionsFromDirectory } from \"../collections/loader\";\nimport type { HonoEnv } from \"../api/types\";\nimport { logger } from \"../utils/logger\";\nimport { serveSPA } from \"../serve-spa\";\nimport { installShutdownHandlers } from \"../init/shutdown\";\nimport { listenWithPortRetry, cleanupDevPortFile } from \"../utils/dev-port\";\n\nimport { loadBootEnv, resolveCorsOrigin, resolveEnableSwagger, type RebaseBootEnv } from \"./env\";\nimport {\n BundleError,\n loadBundle,\n loadBundleConfigExports,\n loadBundleSchema,\n loadUsersCollection,\n type LoadedBundle\n} from \"./bundle\";\nimport { resolveDataSources, resolveStorageSources } from \"./sources\";\nimport { bundleResolutionRoots, initializeDataSources, probeDataSource, type InitializedDataSource } from \"./driver\";\nimport { resolveAuthOptions } from \"./options\";\nimport { createMetricsRoutes, createMetricsMiddleware } from \"../metrics\";\nimport { fetchBundle, shouldFetchBundle, BUNDLE_URL_ENV, BUNDLE_TOKEN_ENV } from \"./fetch-bundle.js\";\nimport { describeDriverSkew, readRuntimeVersion, schemaRecoveryGuidance } from \"./version-skew\";\n\n/** A running runtime, and the handle to stop it. */\nexport interface BootedRuntime {\n app: Hono<HonoEnv>;\n server: Server;\n backend: RebaseBackendInstance;\n bundle: LoadedBundle;\n env: RebaseBootEnv;\n /** The port actually bound, which in development may not be the one asked for. */\n port: number;\n dataSources: InitializedDataSource[];\n shutdown: () => Promise<void>;\n}\n\nexport interface BootOptions {\n /** Bundle directory. Defaults to `REBASE_BUNDLE` or `./dist-bundle`. */\n bundleDir?: string;\n /**\n * A bundle that has already been resolved.\n *\n * `rebase dev` passes one built from source (see `createSourceBundle`), so\n * development and production run the identical boot path rather than two\n * implementations that drift apart.\n */\n bundle?: LoadedBundle;\n /** Skip binding a port. Used by tests that drive `app.fetch` directly. */\n listen?: boolean;\n /** Install SIGTERM/SIGINT handlers. Off for tests. */\n handleSignals?: boolean;\n}\n\n/**\n * Boot a Rebase runtime from a built bundle.\n *\n * This is the entrypoint the official container image runs, and it is the same\n * code path a self-hosted deployment uses — there is no separate \"platform\"\n * runtime. Everything it does was previously the responsibility of a\n * hand-written `backend/src/index.ts` in every project: wiring CORS and security\n * headers, opening database connections, resolving storage, mounting health and\n * metrics, serving the client bundle, and shutting all of it down cleanly.\n *\n * Moving it here is what makes a project's *code* separable from the *engine*\n * that runs it: the bundle can then be handed to a newer runtime without being\n * rebuilt, which is the precondition for patching a fleet.\n */\nexport async function bootFromBundle(options: BootOptions = {}): Promise<BootedRuntime> {\n // Serverless platforms have no init container, so there may be nothing on\n // disk yet. `REBASE_BUNDLE_URL` means \"download it first\"; an explicit\n // bundle path always wins, because a platform that mounted one AND set a URL\n // is mid-migration between the two and the local copy is definitely there.\n //\n // This runs on EVERY cold start — a scale-from-zero, an instance recycled\n // after an hour idle — which is why the URL it is given is a stable endpoint\n // rather than a signed one that would have expired.\n const fetchedDir = !options.bundleDir && !options.bundle && shouldFetchBundle()\n ? await fetchBundle({\n url: process.env[BUNDLE_URL_ENV]!,\n token: process.env[BUNDLE_TOKEN_ENV]\n })\n : undefined;\n\n const bundleDir = options.bundleDir\n || fetchedDir\n || process.env.REBASE_BUNDLE\n || path.resolve(process.cwd(), \"dist-bundle\");\n\n // The bundle is located before the environment is validated, because\n // pointing at the wrong directory is the likeliest first-run mistake, and\n // \"no bundle here, build one\" is far more useful than being told\n // DATABASE_URL is missing — which it also is, but only because nothing has\n // been set up yet.\n const bundle = options.bundle ?? loadBundle(bundleDir);\n\n // Where dev-only state (the port file, the MCP discovery file) lives. A\n // source boot runs from the project root; a built bundle sits inside it.\n const devRoot = process.env.REBASE_DEV_PROJECT_ROOT || process.cwd();\n logger.info(\"Loaded bundle\", {\n app: bundle.manifest.app,\n kind: bundle.manifest.kind,\n schemaVersion: bundle.manifest.schemaVersion,\n builtAgainst: bundle.manifest.runtime?.builtAgainst\n });\n\n // A `static` bundle is a built SPA and nothing else — no collections, no data\n // sources, no database. It runs on this same image so a project's frontend\n // and admin apps are just more bundles, deployed and scaled independently of\n // the backend. Handled BEFORE `loadBootEnv`, which requires DATABASE_URL and\n // JWT_SECRET — a static app needs neither, and demanding them would be the\n // one thing that could stop a folder of assets from being served.\n if (bundle.manifest.kind === \"static\") {\n return bootStaticApp(bundle, devRoot, options);\n }\n\n const env = loadBootEnv();\n const isProduction = env.NODE_ENV === \"production\";\n\n // ── Declarations ─────────────────────────────────────────────────────────\n const configExports = await loadBundleConfigExports(bundle);\n const dataSourceDefs: DataSourceDefinition[] | undefined = configExports.dataSources;\n // `rebase.json` (recorded in the manifest) is authoritative; config code may\n // add sources it does not mention — a `direct`-transport bucket reached by a\n // provider SDK has no reason to appear in a document the platform reads for\n // provisioning. Merging rather than choosing is what keeps the console's view\n // and the tenant's reality the same list. A bundle built before the manifest\n // carried sources falls through to the config exports alone.\n const declaredStorage = normalizeStorageSources(\n bundle.manifest.storage?.sources,\n configExports.storageSources\n );\n const storageSourceDefs: StorageSourceDefinition[] | undefined =\n declaredStorage.length > 0 ? declaredStorage : undefined;\n\n // ── Databases ────────────────────────────────────────────────────────────\n const resolvedSources = resolveDataSources(process.env, dataSourceDefs);\n const schema = await loadBundleSchema(bundle);\n const driverRoots = bundleResolutionRoots(bundle.dir);\n const dataSources = await initializeDataSources(resolvedSources, schema, driverRoots);\n warnOnDriverSkew(dataSources, readRuntimeVersion(driverRoots));\n\n // ── HTTP ─────────────────────────────────────────────────────────────────\n const app = new Hono<HonoEnv>();\n\n app.use(\"/*\", cors({\n origin: resolveCorsOrigin(env),\n credentials: true\n }));\n app.use(\"/*\", secureHeaders({\n // An API serves assets and tokens to origins other than its own, so the\n // browser defaults are wrong here in two specific ways:\n //\n // - `crossOriginResourcePolicy` defaults to `same-origin`, which blocks a\n // frontend on another origin from loading anything this server serves.\n // - `crossOriginOpenerPolicy` defaults to `same-origin`, which severs\n // `window.opener` and breaks the OAuth popup sign-in that\n // `resolveAuthOptions` configures whenever GOOGLE_CLIENT_ID is set.\n //\n // Cross-origin access is still governed by CORS; these only stop the\n // browser from refusing before CORS is consulted.\n crossOriginResourcePolicy: \"cross-origin\",\n crossOriginOpenerPolicy: \"same-origin-allow-popups\"\n }));\n\n // Classified against the configured base path, not a hardcoded \"/api\" — a\n // project on a different base path would otherwise label every request\n // \"other\" and the per-surface breakdown would silently be empty.\n const metrics = env.REBASE_METRICS\n ? createMetricsMiddleware(env.REBASE_BASE_PATH)\n : undefined;\n if (metrics) {\n app.use(\"/*\", metrics.middleware);\n }\n\n const server = createServer(getRequestListener(app.fetch));\n\n // ── Backend ──────────────────────────────────────────────────────────────\n const usersCollection = await loadUsersCollection(bundle);\n const storage = resolveStorageSources(\n process.env,\n storageSourceDefs,\n path.join(bundle.dir, \"uploads\")\n );\n\n // ── Schema ───────────────────────────────────────────────────────────────\n //\n // Create any collection tables the database is missing, before the backend\n // starts serving. `initializeRebaseBackend` ensures AUTH tables; nothing\n // ensured collection tables, so a runtime booted against a fresh database\n // came up with working sign-in and a 500 on every `/api/data/*` route — the\n // state every managed tenant would have launched in.\n //\n // Additive only: the driver may create missing tables, columns and enum\n // types, and may never drop or rewrite. Destructive changes stay a\n // deliberate migration, because this runs unattended with nobody reading a\n // diff. `REBASE_MIGRATE_ON_BOOT=none` opts out entirely for a deployment\n // that manages its own schema.\n await ensureCollectionSchema(bundle, dataSources, env);\n\n const backend = await initializeRebaseBackend({\n server,\n app,\n basePath: env.REBASE_BASE_PATH,\n collectionsDir: bundle.collectionsDir,\n functionsDir: bundle.functionsDir,\n cronsDir: bundle.cronsDir,\n bootstrappers: dataSources.map(s => s.bootstrapper),\n dataSources: dataSourceDefs,\n storage,\n storageSources: storageSourceDefs,\n // Per-object access control comes from the project's own code — no\n // environment variable can express \"this user may read this key\".\n storageAuthorize: configExports.storageAuthorize,\n storagePublicRead: env.STORAGE_PUBLIC_READ,\n storageInsecureAllowAnyAuthenticated: env.STORAGE_ALLOW_ANY_AUTHENTICATED,\n callbacks: configExports.callbacks,\n auth: resolveAuthOptions(env, usersCollection),\n history: env.REBASE_HISTORY,\n enableSwagger: resolveEnableSwagger(env),\n compression: env.REBASE_COMPRESSION,\n maxBodySize: env.REBASE_MAX_BODY_SIZE,\n logging: env.LOG_LEVEL ? { level: env.LOG_LEVEL } : undefined,\n // CORS is installed above, before this call.\n corsHandled: true,\n // Published by the contract endpoint, so a client generated in another\n // repository can tell whether it is built against this schema.\n // Empty for a source boot: nothing was built, so the runtime computes a\n // version from the live collections instead of quoting one.\n schemaVersion: bundle.manifest.schemaVersion || undefined,\n runtimeVersion: bundle.manifest.runtime?.builtAgainst,\n // The schema editor rewrites collection *source* files. A bundle holds\n // compiled output, so there is nothing it could meaningfully edit —\n // and a running deployment is the last place that should be possible.\n schemaEditor: false\n });\n\n // ── RLS policies ───────────────────────────────────────────────────────────\n //\n // Now that the backend is up — auth tables and the `auth.*` helper functions\n // exist, the restricted user role is provisioned, and the collection tables\n // were created above — apply the collections' row-level-security policies.\n // Tables without them are not servable: authenticated requests run as a\n // restricted role, so a read with no policy returns nothing (a public\n // collection answers 401) and a write with no policy is denied. This is the\n // second half of what `db push` does, and the half a managed tenant could\n // not reach any other way. Ordered after `initializeRebaseBackend` on\n // purpose: `CREATE POLICY` validates the `auth.uid()` functions it references\n // exist, and those are created during auth initialization. Same\n // `REBASE_MIGRATE_ON_BOOT=none` opt-out as the table creation above.\n await ensureCollectionPolicies(bundle, dataSources, env);\n\n // Restrict metric labels to collections that exist, now that they do.\n metrics?.setKnownCollections(\n backend.collectionRegistry.getCollections()\n .map(collection => collection.slug)\n .filter((slug): slug is string => Boolean(slug))\n );\n\n // ── Health ───────────────────────────────────────────────────────────────\n // Not part of `initializeRebaseBackend` because it sits outside `basePath`:\n // orchestrators probe `/health`, not `/api/health`.\n app.get(\"/health\", async (c) => {\n const result = await backend.healthCheck();\n\n // `backend.healthCheck()` probes the default driver only. With several\n // databases configured, that would report a healthy server while every\n // collection routed to an unreachable secondary returns 500 — an\n // orchestrator would keep sending it traffic.\n const secondaries = await Promise.all(\n dataSources\n .filter(source => source.key !== DEFAULT_DATA_SOURCE_KEY)\n .map(async source => ({\n key: source.key,\n result: await probeDataSource(source)\n }))\n );\n\n const unhealthy = secondaries\n .filter(source => source.result && !source.result.healthy)\n .map(source => ({ key: source.key,\n error: source.result?.error }));\n const healthy = result.healthy && unhealthy.length === 0;\n\n return c.json({\n status: healthy ? \"ok\" : \"degraded\",\n latencyMs: result.latencyMs,\n ...(result.details ? { details: result.details } : {}),\n ...(unhealthy.length > 0 ? { dataSources: unhealthy } : {})\n }, healthy ? 200 : 503);\n });\n\n // Liveness vs readiness: `/health` touches the database, so a database blip\n // would make an orchestrator kill an otherwise healthy process. `/livez`\n // answers \"is this process running\", which is the question a liveness probe\n // is actually asking.\n app.get(\"/livez\", (c) => c.json({ status: \"ok\" }));\n\n // ── Metrics ──────────────────────────────────────────────────────────────\n if (metrics) {\n if (!env.REBASE_METRICS_TOKEN) {\n logger.warn(\n \"Metrics are enabled without REBASE_METRICS_TOKEN — /metrics is readable by anyone \" +\n \"who can reach this port. Set a token, or keep the port on a private network.\"\n );\n }\n app.route(\"/metrics\", createMetricsRoutes(metrics.registry, env.REBASE_METRICS_TOKEN));\n }\n\n // ── Static assets ────────────────────────────────────────────────────────\n // Mounted last: each app's `serveSPA` ends in a catch-all under its own\n // prefix, so anything registered after it would never be reached.\n //\n // `bundle.staticApps` arrives longest-path-first, which puts the \"/\"-rooted\n // app last. Ordering alone is not enough, though — every app also excludes\n // its siblings, or a miss under \"/admin\" would be answered with the site's\n // index.html at the admin's URL.\n if (env.REBASE_SERVE_STATIC) {\n for (const staticApp of bundle.staticApps) {\n const siblings = bundle.staticApps\n .filter(other => other !== staticApp)\n .map(other => other.path)\n .filter(other => other !== \"/\");\n logger.info(\"Serving static assets\", { path: staticApp.dir,\nat: staticApp.path });\n serveSPA(app, {\n frontendPath: staticApp.dir,\n basePath: staticApp.path,\n apiBasePath: env.REBASE_BASE_PATH,\n excludePaths: [\"/health\", \"/livez\", \"/metrics\", ...siblings],\n spa: staticApp.spa\n });\n }\n }\n\n // ── Listen ───────────────────────────────────────────────────────────────\n let port = env.PORT;\n if (options.listen !== false) {\n if (isProduction) {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(env.PORT, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n });\n logger.info(`Rebase runtime listening on port ${env.PORT}`);\n } else {\n port = await listenWithPortRetry(server, env.PORT, {\n portFileDir: devRoot,\n serviceKey: env.REBASE_SERVICE_KEY\n });\n // Phrased to match what `rebase dev` watches for before it starts\n // the frontend. One convention, shared by the template entrypoint\n // this replaced — changing the wording here silently breaks dev.\n logger.info(`Server running at http://localhost:${port}`);\n }\n }\n\n const closeConnections = async (): Promise<void> => {\n await Promise.allSettled(\n dataSources.map(source => source.connection.pool?.end())\n );\n if (!isProduction) cleanupDevPortFile(devRoot);\n };\n\n if (options.handleSignals !== false) {\n installShutdownHandlers(backend, { onCleanup: closeConnections });\n // The graceful path is not the only way a dev server ends. Without this,\n // a crash or a force-exit leaves `.rebase-dev-port` behind and the next\n // run inherits a port nothing is listening on.\n if (!isProduction) {\n process.on(\"exit\", () => cleanupDevPortFile(devRoot));\n }\n }\n\n return {\n app,\n server,\n backend,\n bundle,\n env,\n port,\n dataSources,\n shutdown: async () => {\n await backend.shutdown();\n await closeConnections();\n }\n };\n}\n\n/**\n * Boot a `static` bundle: serve its built SPA and nothing else.\n *\n * No database, no data sources, no backend — a static app is a folder of assets\n * plus an `index.html`. Kept deliberately minimal so it is cheap to run and\n * cannot fail for a reason a static site never should (a database blip, a\n * missing collection). Exposes the same `/livez` and `/health` the orchestrator\n * probes, so a static app is provisioned by the exact same deployment path as a\n * backend — the only difference is what the bundle contains.\n */\nasync function bootStaticApp(\n bundle: LoadedBundle,\n devRoot: string,\n options: BootOptions\n): Promise<BootedRuntime> {\n if (bundle.staticApps.length === 0) {\n throw new BundleError(\n \"A static bundle declares no assets to serve.\",\n \"Its manifest has `kind: \\\"static\\\"` but no `entry.static` — rebuild the app with `rebase build`.\"\n );\n }\n\n // Read only the handful of variables a static server uses, directly — the\n // full env schema requires a database and a JWT secret, which this path\n // deliberately does not.\n const isProduction = process.env.NODE_ENV === \"production\";\n const requestedPort = Number(process.env.PORT ?? \"3001\") || 3001;\n const basePath = process.env.REBASE_BASE_PATH || \"/api\";\n const metricsEnabled = process.env.REBASE_METRICS === \"true\";\n const metricsToken = process.env.REBASE_METRICS_TOKEN;\n\n const app = new Hono<HonoEnv>();\n\n // Assets must be loadable from other origins (a custom domain, the console),\n // so the same cross-origin relaxation the API path makes applies here.\n app.use(\"/*\", secureHeaders({\n crossOriginResourcePolicy: \"cross-origin\",\n crossOriginOpenerPolicy: \"same-origin-allow-popups\"\n }));\n\n const metrics = metricsEnabled ? createMetricsMiddleware(basePath) : undefined;\n if (metrics) app.use(\"/*\", metrics.middleware);\n\n const server = createServer(getRequestListener(app.fetch));\n\n // Liveness and readiness are the same for a static app: it is ready the\n // moment it can serve, and there is no database to make readiness lie.\n app.get(\"/livez\", (c) => c.json({ status: \"ok\" }));\n app.get(\"/health\", (c) => c.json({ status: \"ok\", latencyMs: 0 }));\n\n if (metrics) {\n app.route(\"/metrics\", createMetricsRoutes(metrics.registry, metricsToken));\n }\n\n // Mounted last: each app's serveSPA ends in a catch-all under its prefix.\n // Same ordering and sibling-exclusion rules as the backend path above.\n for (const staticApp of bundle.staticApps) {\n const siblings = bundle.staticApps\n .filter(other => other !== staticApp)\n .map(other => other.path)\n .filter(other => other !== \"/\");\n logger.info(\"Serving static app\", {\n app: bundle.manifest.app,\n path: staticApp.dir,\n at: staticApp.path\n });\n serveSPA(app, {\n frontendPath: staticApp.dir,\n basePath: staticApp.path,\n apiBasePath: basePath,\n excludePaths: [\"/health\", \"/livez\", \"/metrics\", ...siblings],\n spa: staticApp.spa\n });\n }\n\n let port = requestedPort;\n if (options.listen !== false) {\n if (isProduction) {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(requestedPort, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n });\n logger.info(`Rebase static runtime listening on port ${requestedPort}`);\n } else {\n port = await listenWithPortRetry(server, requestedPort, { portFileDir: devRoot });\n logger.info(`Server running at http://localhost:${port}`);\n }\n }\n\n // No backend and no data sources exist for a static app; the stub keeps the\n // returned shape uniform so callers (and shutdown) do not special-case it.\n const noopBackend = { shutdown: async () => {} } as unknown as RebaseBackendInstance;\n\n if (options.handleSignals !== false) {\n installShutdownHandlers(noopBackend, {\n onCleanup: async () => { if (!isProduction) cleanupDevPortFile(devRoot); }\n });\n if (!isProduction) process.on(\"exit\", () => cleanupDevPortFile(devRoot));\n }\n\n // A static app runs on a deliberately reduced env — only the fields it read\n // above are meaningful. Surfaced for callers/tests without pretending the\n // database-shaped fields exist.\n const env = {\n NODE_ENV: (process.env.NODE_ENV ?? \"development\"),\n PORT: requestedPort,\n REBASE_BASE_PATH: basePath,\n REBASE_METRICS: metricsEnabled,\n REBASE_METRICS_TOKEN: metricsToken\n } as unknown as RebaseBootEnv;\n\n return {\n app,\n server,\n backend: noopBackend,\n bundle,\n env,\n port,\n dataSources: [],\n shutdown: async () => {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n if (!isProduction) cleanupDevPortFile(devRoot);\n }\n };\n}\n\n/**\n * Boot and keep running, reporting failures the way a container should.\n *\n * A `BundleError` is a configuration problem with a known fix, so it prints the\n * message and its hint without a stack trace — the stack is noise when the\n * answer is \"set DATABASE_URL\". Anything else keeps its stack, because it is a\n * bug and the trace is the point.\n */\nexport async function runFromBundle(options: BootOptions = {}): Promise<BootedRuntime> {\n try {\n return await bootFromBundle(options);\n } catch (err) {\n if (err instanceof BundleError) {\n logger.error(err.message);\n if (err.hint) logger.error(err.hint);\n } else {\n logger.error(\"Failed to start the Rebase runtime\", {\n error: err instanceof Error ? err : new Error(String(err))\n });\n }\n process.exit(1);\n }\n}\n\n\n/**\n * Say so, once per boot, when a data source's driver is older than this runtime.\n *\n * The check exists because of how a managed deployment is assembled: the image\n * supplies `@rebasepro/server` (the entrypoint symlinks it over the bundle's\n * copy) while every driver comes from the bundle's own `deps.declared`, pinned\n * by the project's package.json. So the platform can ship a fix, roll every\n * tenant onto the new image, and still have none of them running the fixed\n * driver. Nothing detected that before this: the halves simply disagreed in\n * silence until some capability turned out to be missing three layers down.\n *\n * A warning rather than a refusal. Old drivers are usually fine — the pairing is\n * supported, and a boot that dies on version arithmetic would be a far worse\n * failure than the drift it is guarding against. This only has to make the skew\n * *visible*, so that the next person reading the log starts from the right\n * question.\n */\nexport function warnOnDriverSkew(\n dataSources: InitializedDataSource[],\n runtimeVersion: string | undefined\n): void {\n if (!runtimeVersion) return;\n\n for (const source of dataSources) {\n const skew = describeDriverSkew(source.driverVersion, runtimeVersion);\n if (!skew.stale) continue;\n logger.warn(\n `Driver version skew on data source \"${source.key}\": ` +\n `\"${source.driverPackage}\" is at ${source.driverVersion}, this runtime is ${runtimeVersion}. ` +\n \"A driver is installed from your bundle's dependencies, NOT supplied by the platform image, \" +\n \"so a newer runtime does not update it. Capabilities added after \" +\n `${source.driverVersion} are unavailable to this deployment — bump ` +\n `\"${source.driverPackage}\" in your project's package.json and redeploy.`\n );\n }\n}\n\n/**\n * Bring the database's collection tables up to date before serving.\n *\n * Delegates to whichever driver bootstrapped the default data source; a driver\n * without `ensureCollectionSchema` (a schemaless one, or an older build) skips\n * rather than failing, which is why this cannot break an existing deployment.\n *\n * Every path out of here says why, at info or louder. Guaranteeing the tables\n * exist is this function's entire job, so \"it declined, and said nothing\" is the\n * one outcome it must never produce: a deployment that skips comes up answering\n * sign-in and 500ing every `/api/data/*` route, and the operator's only evidence\n * is what these lines print. Silence here has already sent one investigation\n * chasing a stale runtime image that was not stale.\n *\n * Failure is fatal on purpose. Booting anyway would produce exactly the state\n * this exists to prevent — an app that answers sign-in and 500s every data\n * request — and a crash-looping pod with the DDL error in its logs is a far\n * better signal than a running one that silently cannot serve.\n */\nexport async function ensureCollectionSchema(\n bundle: LoadedBundle,\n dataSources: InitializedDataSource[],\n env: RebaseBootEnv\n): Promise<void> {\n // `info` is for the bundle shapes with legitimately nothing to create;\n // `warn` is for a bundle that asked for collection tables and is not getting\n // them. A backend carrying a config package is the shape that expects\n // tables, so every stop after that point is a real problem worth raising.\n const skip = (reason: string, level: \"info\" | \"warn\" = \"info\"): void => {\n logger[level](`Collection schema: skipped — ${reason}`);\n };\n\n const mode = env.REBASE_MIGRATE_ON_BOOT || \"ensure\";\n if (mode === \"none\") {\n skip(\"REBASE_MIGRATE_ON_BOOT=none, leaving the database schema untouched.\");\n return;\n }\n // A bundle without a config package introspects its collections FROM the\n // database, so there is nothing to create; a `static` bundle has no database\n // at all. Both conditions matter: gating on `kind` alone would push a\n // schema into an existing database that a project only meant to read.\n if (bundle.manifest.kind !== \"backend\") {\n skip(`this bundle's kind is \"${bundle.manifest.kind}\", which serves no database.`);\n return;\n }\n if (!bundle.manifest.entry?.config) {\n skip(\"this bundle declares no config package, so its collections are read from the database rather than from code.\");\n return;\n }\n // Reachable only when the config package exists but carries no collections\n // directory — a build that produced a manifest the runtime cannot act on,\n // which looks identical from the outside to a database that was never\n // migrated. Name the path so the two are told apart from the log alone.\n if (!bundle.collectionsDir) {\n skip(\n `this bundle declares a config package at \"${bundle.manifest.entry.config}\", but no collections directory resolved inside it. ` +\n \"Rebuild with `rebase build` and check the manifest's `entry.collections`.\",\n \"warn\"\n );\n return;\n }\n\n const primary = dataSources[0];\n if (!primary) {\n skip(\"no data source was initialized for this runtime.\", \"warn\");\n return;\n }\n if (!primary.bootstrapper.ensureCollectionSchema) {\n // What is missing is the method on the ADAPTER — the only object boot\n // ever sees — which is not the same as the driver package lacking the\n // code. Three unrelated causes collapse into this one symptom: a\n // schemaless driver, a driver too old to have it, and a driver that\n // implements it on a class the adapter never forwards. Only the middle\n // one is a version problem, so saying \"the driver does not implement\"\n // and naming versions points at the wrong suspect two times in three —\n // it sent one investigation after driver and runtime releases that were\n // both fine while a wrapper silently dropped the method in between.\n const skew = describeDriverSkew(primary.driverVersion, readRuntimeVersion(bundleResolutionRoots(bundle.dir)));\n skip(\n `the adapter from \"${primary.driverPackage}\" (engine \"${primary.engine}\") does not expose collection-table creation. ` +\n (skew.detail ? `${skew.detail} ` : \"\") +\n \"The driver package may well implement it on a class the adapter does not forward, so check the adapter's shape before blaming its version. \" +\n \"Collection tables will NOT be created, so every /api/data route will fail on a missing relation.\\n\" +\n schemaRecoveryGuidance({ staleDriver: skew.stale }),\n \"warn\"\n );\n return;\n }\n\n const collections = await loadCollectionsFromDirectory(bundle.collectionsDir);\n if (collections.length === 0) {\n skip(`no collections were loaded from \"${bundle.collectionsDir}\".`, \"warn\");\n return;\n }\n\n const { applied } = await primary.bootstrapper.ensureCollectionSchema(\n collections,\n preInitDriverResult(primary),\n message => logger.info(`schema: ${message}`)\n );\n logger.info(\n applied > 0\n ? `Applied ${applied} additive schema change(s) before boot.`\n : \"Collection schema is up to date.\"\n );\n}\n\n/**\n * The `InitializedDriver` to hand a bootstrapper before any driver exists.\n *\n * Both schema hooks are declared to take the result of `initializeDriver`, but\n * they deliberately run *before* it: the tables have to exist before the driver\n * introspects them and registers collections. So there is no real result to\n * pass, and the field the hooks actually read is `internals` — the driver's own\n * opaque handle, which at this point is exactly the connection the coordinator\n * just opened (`{ db, pool }`, where `db` is the drizzle instance).\n *\n * Wrapping it matters: the connection passed *bare* type-checks through any cast\n * and then reads `undefined.db` inside the driver, which surfaces as a boot\n * crash — `TypeError: Cannot read properties of undefined (reading 'db')` — on\n * every project whose driver implements these hooks. The cast is narrowed to the\n * one field a pre-init result cannot honestly supply, rather than `as never`\n * blanketing the whole argument.\n */\nfunction preInitDriverResult(source: InitializedDataSource): InitializedDriver {\n return { internals: source.connection } as unknown as InitializedDriver;\n}\n\n/**\n * Apply the project's RLS policies before serving — the companion to\n * {@link ensureCollectionSchema}, which creates the tables this makes servable.\n *\n * Runs after `initializeRebaseBackend`, not alongside table creation: the\n * generated policies call the `auth.*` helper functions, and `CREATE POLICY`\n * validates those exist, so this cannot run before auth is initialized. The\n * gate conditions mirror `ensureCollectionSchema` (mode, bundle shape, driver\n * support) — and because that function already ran and explained any skip on\n * this same boot, the benign gates here return quietly rather than logging the\n * same reason twice. The one thing it does say out loud is a driver that\n * created tables but cannot apply policies: that is the difference between a\n * served collection and a 401, and it must not pass in silence.\n */\nexport async function ensureCollectionPolicies(\n bundle: LoadedBundle,\n dataSources: InitializedDataSource[],\n env: RebaseBootEnv\n): Promise<void> {\n const mode = env.REBASE_MIGRATE_ON_BOOT || \"ensure\";\n if (mode === \"none\") return;\n if (bundle.manifest.kind !== \"backend\") return;\n if (!bundle.manifest.entry?.config) return;\n if (!bundle.collectionsDir) return;\n\n const primary = dataSources[0];\n if (!primary) return;\n if (!primary.bootstrapper.ensureCollectionPolicies) {\n // The tables may exist (ensureCollectionSchema ran) but their RLS does\n // not, so every user-context read is denied. Name it: a silent skip here\n // reads from outside the pod as \"the database has no data\".\n const skew = describeDriverSkew(primary.driverVersion, readRuntimeVersion(bundleResolutionRoots(bundle.dir)));\n logger.warn(\n `Collection policies: skipped — the \"${primary.driverPackage}\" driver (engine \"${primary.engine}\") ` +\n \"does not apply RLS policies at boot. \" +\n (skew.detail ? `${skew.detail} ` : \"\") +\n \"Collections will deny reads until policies are applied.\\n\" +\n schemaRecoveryGuidance({ staleDriver: skew.stale })\n );\n return;\n }\n\n const collections = await loadCollectionsFromDirectory(bundle.collectionsDir);\n if (collections.length === 0) return;\n\n const { applied } = await primary.bootstrapper.ensureCollectionPolicies(\n collections,\n preInitDriverResult(primary),\n message => logger.info(`policies: ${message}`)\n );\n logger.info(\n applied > 0\n ? `Applied ${applied} RLS policy statement(s) before serving.`\n : \"RLS policies are up to date.\"\n );\n}\n"],"x_google_ignoreList":[12,13],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","names":["core._coercedNumber","schemas.ZodNumber","RebaseClientError$1","RebaseApiError$1"],"sources":["../../types/src/errors.ts","../../types/src/types/storage_source.ts","../../common/src/data/sort-dialect.ts","../src/collections/BackendCollectionRegistry.ts","../src/collections/validate-config.ts","../src/collections/loader.ts","../src/services/driver-registry.ts","../src/services/routed-realtime-service.ts","../src/api/rest/query-parser.ts","../src/api/rest/write-validation.ts","../src/api/rest/idempotency.ts","../src/api/rest/api-generator.ts","../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/compat.js","../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/coerce.js","../src/utils/logging.ts","../src/utils/compression.ts","../src/utils/request-id.ts","../src/utils/request-logger.ts","../src/init/middlewares.ts","../src/storage/LocalStorageController.ts","../src/storage/image-transform.ts","../src/storage/tus-handler.ts","../src/storage/routes.ts","../src/storage/storage-registry.ts","../src/storage/index.ts","../src/init/storage.ts","../src/init/docs.ts","../src/init/health.ts","../src/init/shutdown.ts","../src/auth/collection-callback-warning.ts","../../client/dist/index.es.js","../src/history/history-routes.ts","../src/email/smtp-email-service.ts","../src/singleton.ts","../src/auth/require-auth.ts","../src/init.ts","../src/functions/define-function.ts","../src/cron/define-cron.ts","../src/utils/sql.ts","../src/env.ts","../src/services/webhook-service.ts","../src/utils/dev-port.ts","../src/serve-spa.ts","../src/boot/bundle.ts","../src/boot/env.ts","../src/boot/sources.ts","../src/boot/version-skew.ts","../src/boot/driver.ts","../src/boot/options.ts","../src/metrics/index.ts","../src/boot/fetch-bundle.ts","../src/boot/boot.ts"],"sourcesContent":["/**\n * Structured initializer for {@link RebaseApiError}.\n *\n * @group Errors\n */\nexport interface RebaseErrorInit {\n /**\n * HTTP status code, when the error originated from an HTTP response.\n * Left `undefined` for realtime/WebSocket, network, and client-side\n * logic errors that have no HTTP status.\n */\n status?: number;\n /** Stable, machine-readable error code (e.g. `\"NOT_FOUND\"`, `\"BAD_REQUEST\"`). */\n code?: string;\n /** Structured error payload returned by the server, when present. */\n details?: unknown;\n /** The underlying error this one wraps, if any. */\n cause?: unknown;\n}\n\n/**\n * The single error type thrown across the entire Rebase client surface —\n * HTTP data/control-plane calls, realtime/WebSocket operations, and\n * client-side logic errors (e.g. an unknown collection accessor). A `catch`\n * block only ever needs to check for this one class:\n *\n * ```ts\n * import { RebaseApiError } from \"@rebasepro/client\"; // re-exported\n *\n * try {\n * await client.data.products.update(id, { price: 9 });\n * } catch (e) {\n * if (e instanceof RebaseApiError) {\n * if (e.status === 404) { ... } // HTTP failures carry a status\n * console.error(e.code, e.details);\n * }\n * }\n * ```\n *\n * `status` is present for HTTP failures and `undefined` otherwise, so its\n * presence distinguishes transport-level errors from realtime/logic errors.\n *\n * @group Errors\n */\nexport class RebaseApiError extends Error {\n /** HTTP status code, or `undefined` for non-HTTP errors. */\n readonly status?: number;\n /** Stable machine-readable error code, when the server supplied one. */\n readonly code?: string;\n /** Structured error payload from the server, when present. */\n readonly details?: unknown;\n\n constructor(message: string, init: RebaseErrorInit = {}) {\n super(message);\n this.name = \"RebaseApiError\";\n this.status = init.status;\n this.code = init.code;\n this.details = init.details;\n if (init.cause !== undefined) {\n // `cause` is standard on Error but not always in the lib target's type.\n (this as { cause?: unknown }).cause = init.cause;\n }\n }\n}\n\n/**\n * Client-side logic error — raised before any request is made (e.g. accessing\n * an unknown collection accessor when a typed dictionary is configured).\n *\n * A subclass of {@link RebaseApiError} (with no `status`), so a single\n * `catch (e) { if (e instanceof RebaseApiError) ... }` handles it too.\n *\n * @group Errors\n */\nexport class RebaseClientError extends RebaseApiError {\n constructor(message: string) {\n super(message);\n this.name = \"RebaseClientError\";\n }\n}\n","/**\n * Describes a named storage backend — a place files live.\n *\n * Declared once and shared front + back: the frontend uses it to decide\n * transport (HTTP proxy vs direct SDK), the backend uses the same `key`\n * to resolve a StorageController, and collection properties reference\n * a definition by its `key` via `StorageConfig.storageSource`.\n *\n * This mirrors the {@link DataSourceDefinition} pattern used for databases.\n *\n * @group Models\n */\n\n/**\n * The default storage source key, used when a property does not specify\n * a `storageSource`. Shared by the frontend and backend registries so\n * both agree on \"the default storage backend\".\n * @group Models\n */\nexport const DEFAULT_STORAGE_SOURCE_KEY = \"(default)\";\n\n/**\n * How the *frontend* reaches a storage backend.\n *\n * - `\"server\"` — through the Rebase backend REST API (`/api/storage`).\n * The backend holds the actual `StorageController` and routes by\n * storage-source key. This is the default and covers Local, S3, GCS,\n * and any other server-mediated engine.\n * - `\"direct\"` — straight from the client to the external backend via\n * its own SDK (e.g. Firebase Storage via `@firebase/storage`).\n * The Rebase backend is **not** in the upload/download path.\n *\n * @group Models\n */\nexport type StorageSourceTransport = \"server\" | \"direct\";\n\n/**\n * Declarative definition of a storage source — a named place files live.\n *\n * Declared once and shared front and back: the frontend uses it to decide\n * transport (client HTTP proxy vs direct provider SDK), the backend uses\n * the same `key` to resolve a `StorageController`, and collection\n * properties reference a definition by its `key` via\n * `StorageConfig.storageSource`.\n *\n * @group Models\n */\nexport interface StorageSourceDefinition {\n /**\n * Unique identifier for this storage source. Collection properties\n * point at it via `StorageConfig.storageSource`.\n * Defaults to {@link DEFAULT_STORAGE_SOURCE_KEY}.\n */\n key: string;\n\n /**\n * The engine backing this storage source (e.g. `\"local\"`, `\"s3\"`,\n * `\"gcs\"`, `\"firebase\"`, `\"azure\"`, or a custom id).\n */\n engine: string;\n\n /**\n * How the frontend reaches this storage. Defaults to `\"server\"`.\n *\n * When `\"direct\"`, the client uses a provider-specific SDK\n * (e.g. `@firebase/storage`) and the backend does not proxy\n * upload/download traffic for this source.\n */\n transport: StorageSourceTransport;\n\n /** Human-readable label for the UI (e.g. \"Firebase Storage\", \"S3 Media\"). */\n label?: string;\n}\n\n/**\n * A resolved storage source: the single source of truth that the frontend\n * router and backend registry both derive from.\n *\n * @group Models\n */\nexport interface ResolvedStorageSource {\n /** Storage source key (routing key, shared front + back). */\n key: string;\n /** Engine backing the source. */\n engine: string;\n /** Frontend transport. */\n transport: StorageSourceTransport;\n /** Human-readable label. */\n label?: string;\n}\n\n/**\n * The environment-variable suffix for a storage or data source key.\n *\n * `\"\"` for the default source — so a single-bucket project keeps configuring\n * plain `S3_BUCKET` — and `__<KEY>` for every named one, uppercased with\n * non-alphanumerics collapsed to underscores: `media-cdn` → `S3_BUCKET__MEDIA_CDN`.\n *\n * The rule derives the variable name from the declared key rather than\n * discovering keys by scanning the environment. Scanning would have to guess how\n * `S3_BUCKET__MEDIA_CDN` splits into a key; deriving cannot be ambiguous, and a\n * typo surfaces as a missing source at boot instead of a silently ignored\n * variable.\n *\n * It lives in this package, with no dependencies, because four things must agree\n * on it exactly: the CLI (validating a build), the runtime (reading its own\n * environment), the control plane (writing a tenant's Secret), and the docs. A\n * second implementation of a naming convention is a second chance to disagree.\n *\n * @group Models\n */\nexport function storageEnvSuffix(key: string, defaultKey: string = DEFAULT_STORAGE_SOURCE_KEY): string {\n if (!key || key === defaultKey) return \"\";\n const normalized = key\n .replace(/[^A-Za-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toUpperCase();\n if (!normalized) {\n throw new Error(\n `Source key \"${key}\" cannot be turned into an environment variable name. ` +\n \"Use a key containing at least one letter or digit.\"\n );\n }\n return `__${normalized}`;\n}\n\n/**\n * Two distinct keys that collapse onto the same variable name, or `null`.\n *\n * `media-cdn` and `media_cdn` are different source keys but the same suffix, so\n * without this one of them silently reads the other's configuration. Returns the\n * offending pair rather than throwing, so each caller can raise it in its own\n * idiom — a `BundleError` at boot, a build failure in the CLI, a rejected deploy\n * in a control plane.\n *\n * @group Models\n */\nexport function findStorageSuffixCollision(\n keys: string[],\n defaultKey: string = DEFAULT_STORAGE_SOURCE_KEY\n): { a: string; b: string; suffix: string } | null {\n const seen = new Map<string, string>();\n for (const key of keys) {\n const suffix = storageEnvSuffix(key, defaultKey);\n const existing = seen.get(suffix);\n if (existing !== undefined && existing !== key) {\n return { a: existing, b: key, suffix };\n }\n seen.set(suffix, key);\n }\n return null;\n}\n\n/** The `storage` block of `rebase.json`, structurally. */\nexport type DeclaredStorageSources = Record<string, {\n engine: string;\n transport?: StorageSourceTransport;\n label?: string;\n}>;\n\n/**\n * Merge the two places a project may declare storage sources into one list.\n *\n * `rebase.json` is authoritative for every field it states. Config code may add\n * sources it does not mention and fill in fields it left out, but may not\n * contradict it: the manifest is what a host reads to decide which buckets need\n * configuring, and a runtime that quietly disagreed with it would put the\n * console back to describing a topology the tenant does not have — the exact\n * failure this whole mechanism exists to end.\n *\n * Note what is *not* here: no default source is invented when both inputs are\n * empty. That decision belongs to the resolver, which knows whether declaring\n * nothing means \"one plain bucket\" (it does) or \"no storage at all\".\n *\n * @group Models\n */\nexport function normalizeStorageSources(\n declared: DeclaredStorageSources | StorageSourceDefinition[] | undefined,\n exported: StorageSourceDefinition[] | undefined\n): StorageSourceDefinition[] {\n const merged = new Map<string, StorageSourceDefinition>();\n\n // Two shapes, one meaning. `rebase.json` states sources as a record keyed by\n // source key, which is how JSON expresses a set of named things; the bundle\n // manifest stores the already-resolved array. Accepting both is what lets the\n // CLI and the runtime call this with what each of them happens to hold.\n const declaredEntries: [string, { engine: string; transport?: StorageSourceTransport; label?: string }][] =\n Array.isArray(declared)\n ? declared.filter(d => d?.key).map(d => [d.key, d])\n : Object.entries(declared ?? {});\n\n for (const [key, config] of declaredEntries) {\n merged.set(key, {\n key,\n engine: config.engine,\n transport: config.transport ?? \"server\",\n ...(config.label !== undefined ? { label: config.label } : {})\n });\n }\n\n for (const definition of exported ?? []) {\n if (!definition?.key) continue;\n const existing = merged.get(definition.key);\n if (!existing) {\n merged.set(definition.key, {\n key: definition.key,\n engine: definition.engine,\n transport: definition.transport ?? \"server\",\n ...(definition.label !== undefined ? { label: definition.label } : {})\n });\n continue;\n }\n // Fill gaps only. `rebase.json` stated these; code does not overrule it.\n if (existing.label === undefined && definition.label !== undefined) {\n existing.label = definition.label;\n }\n }\n\n return Array.from(merged.values());\n}\n","import type { OrderByTuple } from \"@rebasepro/types\";\n\n/**\n * Sort-order wire codec.\n *\n * This is the ONLY module that knows about the colon-delimited wire format\n * (`\"field:direction\"`) used in HTTP query parameters.\n * Everything else speaks {@link OrderByTuple} exclusively.\n *\n * Mirrors the filter architecture in `filter-dialect.ts`.\n *\n * @module\n */\n\n/**\n * Serialize an {@link OrderByTuple} to the wire format `\"field:direction\"`.\n *\n * **Runtime tolerance:** if the input is already a well-formed wire string\n * (from an untyped JS caller), it is returned unchanged.\n * This is undocumented tolerance, not public API — don't rely on it.\n *\n * @param orderBy - A canonical `[field, direction]` tuple, or at runtime\n * possibly a pre-serialized string (undocumented tolerance).\n * @returns The wire-format string, or `undefined` if the input is falsy.\n *\n * @remarks\n * Field names containing `:` are representable in the tuple form but\n * **not** on the wire — this is an inherent limitation of the colon-delimited\n * encoding and is not resolved here.\n */\nexport function serializeOrderBy(orderBy?: OrderByTuple | string): string | undefined {\n if (!orderBy) return undefined;\n // Runtime tolerance: pass through a pre-serialized wire string unchanged.\n if (typeof orderBy === \"string\") return orderBy;\n return `${orderBy[0]}:${orderBy[1]}`;\n}\n\n/**\n * Deserialize a wire-format `\"field:direction\"` string into an {@link OrderByTuple}.\n *\n * Lenient parsing (matches existing server behaviour):\n * - Bare field name (no colon): `\"name\"` → `[\"name\", \"asc\"]`\n * - Unknown direction: `\"name:foo\"` → `[\"name\", \"asc\"]`\n * - Empty / falsy input: → `undefined`\n *\n * @param raw - The wire-format string from an HTTP query parameter.\n * @returns The canonical tuple, or `undefined` if the input is empty/falsy.\n */\nexport function deserializeOrderBy(raw?: string): OrderByTuple | undefined {\n if (!raw) return undefined;\n const idx = raw.indexOf(\":\");\n if (idx === -1) return [raw, \"asc\"];\n const field = raw.slice(0, idx);\n const dir = raw.slice(idx + 1);\n return [field, dir === \"desc\" ? \"desc\" : \"asc\"];\n}\n","import { CollectionRegistry } from \"@rebasepro/common\";\nimport { CollectionRegistryInterface } from \"../db/interfaces\";\nimport { CollectionConfig } from \"@rebasepro/types\";\n\n/**\n * Backend-agnostic collection registry.\n * Satisfies CollectionRegistryInterface through inheritance from CollectionRegistry.\n */\nexport class BackendCollectionRegistry extends CollectionRegistry implements CollectionRegistryInterface {\n\n /**\n * Get the available relation keys for a given collection path.\n * Maps from the collection's relation property names to the relation names.\n */\n getRelationKeysForCollection(collectionPath: string): string[] {\n const collection = this.getCollectionByPath(collectionPath) as (CollectionConfig & { relations?: { relationName?: string }[] }) | undefined;\n if (!collection?.relations) return [];\n return collection.relations.map(r => r.relationName ?? \"\").filter(Boolean);\n }\n}\n","import { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS } from \"@rebasepro/types\";\n\nimport { logger } from \"../utils/logger\";\n\n/**\n * A strict parse of every collection config, run at boot.\n *\n * Nothing used to check these files. A config written against an older version\n * loaded clean, and whichever keys had moved since were simply ignored — no\n * warning, no log line, no failed boot. The collection still served rows, so\n * the only signal was the feature quietly not being there: an icon that never\n * appeared, a relation that answered `[]`, a `readOnly` field the panel let you\n * edit. The renames are not the problem; a rename with no runtime signal is.\n *\n * Two severities, because two different things are being detected:\n *\n * - A **known-removed or known-renamed key** is high-confidence and actionable —\n * we know what it used to mean and what replaced it. That is an error, and\n * refusing to boot is the point. A minute of downtime beats a week of \"where\n * did my icons go\".\n * - An **unrecognised key** is not. Configs legitimately carry extra metadata,\n * and a key we do not know may simply be newer than this list. That warns,\n * loudly, and escalates to an error only when asked\n * (`REBASE_STRICT_COLLECTION_CONFIG=error`, or an explicit option).\n *\n * Everything is reported in one pass. Someone migrating a project wants the\n * whole list once, not fifty-five sequential boots.\n *\n * This is not `validateCollectionJson` in `@rebasepro/admin`. That one parses a\n * JSON string pasted into the panel's import dialog and checks value *shapes*\n * against the flat `AdminCollection` view model. This one checks key *identity*\n * against the authoring contract, on live objects, in a package that may not\n * import the admin. The two answer different questions about different types,\n * and merging them would mean the server depending on the admin panel.\n */\n\n/** How an unrecognised key is treated. */\nexport type UnknownKeyPolicy = \"warn\" | \"error\" | \"off\";\n\nexport interface ConfigProblem {\n severity: \"error\" | \"warning\";\n /** Dotted path into the config, e.g. `posts.properties.author`. */\n path: string;\n message: string;\n}\n\nexport interface ValidateCollectionConfigOptions {\n /**\n * What to do with a key that is in no known list. Defaults to the\n * `REBASE_STRICT_COLLECTION_CONFIG` environment variable, and to `\"warn\"`\n * when that is unset.\n */\n unknownKeys?: UnknownKeyPolicy;\n}\n\n/**\n * Read the unknown-key policy from the environment.\n *\n * `REBASE_STRICT_COLLECTION_CONFIG` accepts `error`/`strict`/`1`/`true` to\n * escalate, `off`/`0`/`false` to silence, and anything else warns.\n */\nexport function unknownKeyPolicyFromEnv(\n env: Record<string, string | undefined> = process.env\n): UnknownKeyPolicy {\n const raw = env.REBASE_STRICT_COLLECTION_CONFIG?.trim().toLowerCase();\n if (!raw) return \"warn\";\n if ([\"error\", \"strict\", \"1\", \"true\", \"yes\"].includes(raw)) return \"error\";\n if ([\"off\", \"0\", \"false\", \"no\", \"none\"].includes(raw)) return \"off\";\n return \"warn\";\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// The contract, as data.\n//\n// Every list below is derived from `packages/types/src/types/*` at the version\n// this file ships with. `ADMIN_COLLECTION_KEYS` and `ADMIN_PROPERTY_KEYS` are\n// imported rather than copied — core owns them and `@rebasepro/admin-types`\n// type-checks them against the option types, so those two cannot drift.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** `BaseCollectionConfig`, plus every engine-specific field, plus the `admin` block. */\nconst COLLECTION_KEYS = new Set<string>([\n // BaseCollectionConfig\n \"slug\",\n \"name\",\n \"singularName\",\n \"description\",\n \"childCollections\",\n \"dataSource\",\n \"engine\",\n \"databaseId\",\n \"properties\",\n \"auth\",\n \"disableDefaultPolicies\",\n \"callbacks\",\n \"ownerId\",\n \"metadata\",\n \"history\",\n \"strictWrites\",\n \"table\",\n \"relations\",\n \"securityRules\",\n // PostgresCollectionConfig\n \"schema\",\n // FirebaseCollectionConfig / MongoDBCollectionConfig\n \"path\",\n \"subcollections\",\n // Added back by @rebasepro/admin-types through declaration merging. Its\n // contents belong to the admin panel and are deliberately not checked here.\n \"admin\"\n]);\n\n/** `BaseProperty` — legal on a property of any type. */\nconst BASE_PROPERTY_KEYS = [\n \"type\",\n \"name\",\n \"description\",\n \"propertyConfig\",\n \"columnName\",\n \"defaultValue\",\n \"validation\",\n \"excludeFromApi\",\n \"dynamicProps\",\n \"conditions\",\n \"callbacks\",\n \"metadata\",\n // as above: added by @rebasepro/admin-types, contents not checked here.\n \"admin\"\n];\n\n/** The keys each property `type` adds on top of {@link BASE_PROPERTY_KEYS}. */\nconst PROPERTY_KEYS_BY_TYPE: Record<string, string[]> = {\n string: [\"columnType\", \"isId\", \"enum\", \"storage\", \"userSelect\", \"email\", \"url\"],\n number: [\"columnType\", \"isId\", \"enum\"],\n boolean: [],\n date: [\"columnType\", \"mode\", \"timezone\", \"autoValue\"],\n geopoint: [],\n binary: [],\n vector: [\"dimensions\"],\n reference: [\"isId\", \"path\", \"fixedFilter\", \"includeId\", \"includeEntityLink\"],\n relation: [\"isId\", \"relation\", \"resolvedRelation\", \"fixedFilter\", \"includeId\", \"includeEntityLink\", \"widget\"],\n array: [\"columnType\", \"of\", \"oneOf\", \"sortable\", \"canAddElements\"],\n map: [\"columnType\", \"properties\", \"propertiesOrder\", \"previewProperties\", \"keyValue\"]\n};\n\nconst PROPERTY_TYPES = Object.keys(PROPERTY_KEYS_BY_TYPE);\n\n/** `RelationBase` plus the fields of every `kind` in the tagged union. */\nconst RELATION_KEYS = new Set<string>([\n \"kind\",\n \"relationName\",\n \"target\",\n \"onUpdate\",\n \"onDelete\",\n \"overrides\",\n \"validation\",\n \"localKey\",\n \"foreignKeyOnTarget\",\n \"sourceKey\",\n \"through\",\n \"joinPath\",\n \"cardinality\"\n]);\n\nconst RELATION_KINDS = [\"belongsTo\", \"hasOne\", \"hasMany\", \"manyToMany\", \"via\"];\n\n/** Which link field each `kind` admits. Anything else is a leftover shape. */\nconst RELATION_FIELDS_BY_KIND: Record<string, string[]> = {\n belongsTo: [\"localKey\"],\n hasOne: [\"foreignKeyOnTarget\", \"sourceKey\"],\n hasMany: [\"foreignKeyOnTarget\", \"sourceKey\"],\n manyToMany: [\"through\"],\n via: [\"joinPath\", \"cardinality\"]\n};\n\nconst RELATION_LINK_FIELDS = [\"localKey\", \"foreignKeyOnTarget\", \"sourceKey\", \"through\", \"joinPath\", \"cardinality\"];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// What used to be legal, and is not.\n//\n// Sourced from the commits that made each change, not from recollection:\n// • 0.11 `def1195d1` + `e9eae2cf7` — the 38 presentation fields nest under\n// `admin`; the list is ADMIN_COLLECTION_KEYS in core.\n// • 0.11 `078798484` — a property's block is `admin`, not `ui`.\n// • 0.11 `7cee8f501` — the property's presentation fields nested in the first\n// place; the list is ADMIN_PROPERTY_KEYS in core.\n// • 0.11 `60c3a8ec7` — `Relation` becomes a tagged union, and every flat\n// relation field on `RelationProperty` moves into a nested `relation`.\n// • 0.10 `33d096cd5` — `editable` removed; everything is editable by default.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface Migration {\n /** What to do about it, in the imperative. */\n fix: string;\n /** The codemod that does it, if one exists. */\n codemod?: string;\n}\n\n/** Collection-level keys that no longer exist at the top level. */\nconst COLLECTION_MIGRATIONS: Record<string, Migration> = {\n editable: {\n fix: \"`editable` was removed in 0.10 — collections are editable by default. Delete it, or use `admin.disableDefaultActions` to take actions away\"\n }\n};\n\nfor (const key of ADMIN_COLLECTION_KEYS) {\n COLLECTION_MIGRATIONS[key] = {\n fix: `\\`${key}\\` moved into the collection's \\`admin\\` block in 0.11 — write \\`admin: { ${key}: … }\\``,\n codemod: \"node scripts/codemod/collections-admin-block.mjs\"\n };\n}\n\n/** Property-level keys that no longer exist at the top level of a property. */\nconst PROPERTY_MIGRATIONS: Record<string, Migration> = {\n ui: {\n fix: \"`ui` was renamed to `admin` in 0.11, to match the collection's block — rename the key\"\n },\n editable: {\n fix: \"`editable` was removed in 0.10 — properties are editable by default. Use `admin.readOnly` or `admin.disabled` instead\"\n }\n};\n\nfor (const key of ADMIN_PROPERTY_KEYS) {\n PROPERTY_MIGRATIONS[key] = {\n fix: `\\`${key}\\` belongs in the property's \\`admin\\` block — write \\`admin: { ${key}: … }\\``\n };\n}\n\n/**\n * The flat relation fields that `RelationProperty` used to carry.\n *\n * All of them moved into the nested `relation` object. Two of them do not\n * survive the move at all: `direction` and `inverseRelationName` were how the\n * old shape said which side owned the link, and the `kind` discriminant says it\n * now.\n */\nconst RELATION_PROPERTY_MIGRATIONS: Record<string, Migration> = {\n target: { fix: \"move `target` inside `relation` — `relation: { kind: …, target: … }`\" },\n cardinality: { fix: \"`cardinality` is implied by the relation's `kind` (`belongsTo`/`hasOne` are one, `hasMany`/`manyToMany` are many); it survives only on `relation: { kind: \\\"via\\\" }`\" },\n direction: { fix: \"`direction` was removed — the `kind` says which side owns the link. `owning` + one is `belongsTo`, `inverse` + one is `hasOne`, `inverse` + many is `hasMany`, `owning` + many is `manyToMany`\" },\n inverseRelationName: { fix: \"`inverseRelationName` was removed — name the far side with `relation: { kind: \\\"hasMany\\\", foreignKeyOnTarget: … }` instead of pointing at it\" },\n localKey: { fix: \"move `localKey` inside `relation` — `relation: { kind: \\\"belongsTo\\\", localKey: … }`\" },\n foreignKeyOnTarget: { fix: \"move `foreignKeyOnTarget` inside `relation` — `relation: { kind: \\\"hasOne\\\" | \\\"hasMany\\\", foreignKeyOnTarget: … }`\" },\n through: { fix: \"move `through` inside `relation` — `relation: { kind: \\\"manyToMany\\\", through: … }`\" },\n joinPath: { fix: \"move `joinPath` inside `relation` — `relation: { kind: \\\"via\\\", joinPath: … }`\" },\n onUpdate: { fix: \"move `onUpdate` inside `relation`\" },\n onDelete: { fix: \"move `onDelete` inside `relation`\" },\n overrides: { fix: \"move `overrides` inside `relation`\" },\n relationName: { fix: \"move `relationName` inside `relation` — `relation: { kind: …, relationName: … }`\" }\n};\n\nconst RELATION_UNION_CODEMOD = \"node scripts/codemod/relations-tagged-union.mjs\";\n\n/** Fields the old flat `Relation` carried that the tagged union does not. */\nconst RELATION_MIGRATIONS: Record<string, Migration> = {\n direction: { fix: RELATION_PROPERTY_MIGRATIONS.direction.fix, codemod: RELATION_UNION_CODEMOD },\n inverseRelationName: { fix: RELATION_PROPERTY_MIGRATIONS.inverseRelationName.fix, codemod: RELATION_UNION_CODEMOD }\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nclass ProblemCollector {\n readonly problems: ConfigProblem[] = [];\n\n constructor(private readonly unknownKeys: UnknownKeyPolicy) {\n }\n\n error(path: string, message: string): void {\n this.problems.push({ severity: \"error\", path, message });\n }\n\n /** A key we know moved or died. Always fatal — we know exactly what to do. */\n migrated(path: string, key: string, migration: Migration): void {\n this.error(\n path,\n `\\`${key}\\` is no longer read here. ${migration.fix}.` +\n (migration.codemod ? ` Run \\`${migration.codemod}\\` to migrate the whole project.` : \"\")\n );\n }\n\n /** A key nobody recognises. Might be metadata, might be newer than us. */\n unknown(path: string, key: string, context: string): void {\n if (this.unknownKeys === \"off\") return;\n this.problems.push({\n severity: this.unknownKeys === \"error\" ? \"error\" : \"warning\",\n path,\n message:\n `\\`${key}\\` is not a known ${context} key and is being ignored. ` +\n \"If it is deliberate metadata this is safe; if it is a typo or a key from an older \" +\n \"version, the feature it configures is silently absent.\"\n });\n }\n}\n\nfunction checkRelation(\n relation: unknown,\n path: string,\n collect: ProblemCollector\n): void {\n if (!isPlainObject(relation)) return;\n\n const kind = relation.kind;\n if (typeof kind !== \"string\") {\n collect.error(\n path,\n \"a relation has no `kind`. Relations became a tagged union in 0.11 — pick one of \" +\n `${RELATION_KINDS.join(\", \")}. Run \\`${RELATION_UNION_CODEMOD}\\` to migrate the whole project.`\n );\n } else if (!RELATION_KINDS.includes(kind)) {\n collect.error(path, `\\`kind: \"${kind}\"\\` is not a relation kind. Expected one of ${RELATION_KINDS.join(\", \")}.`);\n }\n\n for (const key of Object.keys(relation)) {\n const migration = RELATION_MIGRATIONS[key];\n if (migration) {\n collect.migrated(`${path}.${key}`, key, migration);\n continue;\n }\n if (!RELATION_KEYS.has(key)) {\n collect.unknown(`${path}.${key}`, key, \"relation\");\n }\n }\n\n // Each kind admits exactly one link field. A leftover from another shape\n // typechecks against nothing and is honoured by whichever consumer reads it\n // first — which is how a `many` relation carrying a `localKey` corrupted\n // writes before the union closed the door.\n if (typeof kind === \"string\" && RELATION_FIELDS_BY_KIND[kind]) {\n const allowed = RELATION_FIELDS_BY_KIND[kind];\n for (const field of RELATION_LINK_FIELDS) {\n if (relation[field] !== undefined && !allowed.includes(field)) {\n collect.error(\n `${path}.${field}`,\n `\\`${field}\\` is not valid on a \"${kind}\" relation. ` +\n `A \"${kind}\" takes ${allowed.length ? allowed.map(a => `\\`${a}\\``).join(\" and \") : \"no link field\"}.`\n );\n }\n }\n }\n}\n\nfunction checkProperty(\n property: unknown,\n path: string,\n collect: ProblemCollector\n): void {\n // A property may be a builder function in some authoring styles; there is\n // nothing to inspect statically, and guessing would be worse than silence.\n if (typeof property === \"function\") return;\n\n if (!isPlainObject(property)) {\n collect.error(path, \"a property must be an object.\");\n return;\n }\n\n const type = property.type;\n if (typeof type !== \"string\") {\n collect.error(path, \"a property has no `type`.\");\n } else if (!PROPERTY_TYPES.includes(type)) {\n collect.error(path, `\\`type: \"${type}\"\\` is not a property type. Expected one of ${PROPERTY_TYPES.join(\", \")}.`);\n }\n\n const allowed = new Set<string>([\n ...BASE_PROPERTY_KEYS,\n ...(typeof type === \"string\" ? PROPERTY_KEYS_BY_TYPE[type] ?? [] : [])\n ]);\n\n for (const key of Object.keys(property)) {\n if (allowed.has(key)) continue;\n\n // A relation's flat fields are checked first: `localKey` at the top of a\n // property is a 0.10 config, not an unknown key.\n if (type === \"relation\" && RELATION_PROPERTY_MIGRATIONS[key]) {\n collect.migrated(`${path}.${key}`, key, { ...RELATION_PROPERTY_MIGRATIONS[key], codemod: RELATION_UNION_CODEMOD });\n continue;\n }\n\n const migration = PROPERTY_MIGRATIONS[key];\n if (migration) {\n collect.migrated(`${path}.${key}`, key, migration);\n continue;\n }\n\n collect.unknown(`${path}.${key}`, key, `property (\\`${String(type)}\\`)`);\n }\n\n if (type === \"relation\" && property.relation !== undefined) {\n checkRelation(property.relation, `${path}.relation`, collect);\n }\n\n // Recurse into the two composites. `of` may be one property or an array of\n // them; `oneOf.properties` is a record like a map's.\n if (type === \"array\") {\n const of = property.of;\n if (Array.isArray(of)) {\n of.forEach((entry, index) => checkProperty(entry, `${path}.of[${index}]`, collect));\n } else if (of !== undefined) {\n checkProperty(of, `${path}.of`, collect);\n }\n const oneOf = property.oneOf;\n if (isPlainObject(oneOf) && isPlainObject(oneOf.properties)) {\n checkProperties(oneOf.properties, `${path}.oneOf.properties`, collect);\n }\n }\n\n if (type === \"map\" && isPlainObject(property.properties)) {\n checkProperties(property.properties, `${path}.properties`, collect);\n }\n}\n\nfunction checkProperties(\n properties: Record<string, unknown>,\n path: string,\n collect: ProblemCollector\n): void {\n for (const [key, property] of Object.entries(properties)) {\n checkProperty(property, `${path}.${key}`, collect);\n }\n}\n\nfunction checkCollection(\n collection: unknown,\n index: number,\n collect: ProblemCollector\n): void {\n if (!isPlainObject(collection)) {\n collect.error(`collection[${index}]`, \"a collection must be an object.\");\n return;\n }\n\n const slug = typeof collection.slug === \"string\" && collection.slug ? collection.slug : undefined;\n const at = slug ?? `collection[${index}]`;\n\n if (!slug) {\n collect.error(\n at,\n \"a collection has no `slug`. It is the collection's identity — the URL, the API path and \" +\n \"the key every relation targets.\"\n );\n }\n\n for (const key of Object.keys(collection)) {\n if (COLLECTION_KEYS.has(key)) continue;\n\n const migration = COLLECTION_MIGRATIONS[key];\n if (migration) {\n collect.migrated(`${at}.${key}`, key, migration);\n continue;\n }\n\n collect.unknown(`${at}.${key}`, key, \"collection\");\n }\n\n if (isPlainObject(collection.properties)) {\n checkProperties(collection.properties, `${at}.properties`, collect);\n } else if (collection.properties !== undefined) {\n collect.error(`${at}.properties`, \"`properties` must be an object keyed by property name.\");\n }\n\n if (Array.isArray(collection.relations)) {\n collection.relations.forEach((relation, i) => {\n const name = isPlainObject(relation) && typeof relation.relationName === \"string\"\n ? relation.relationName\n : String(i);\n checkRelation(relation, `${at}.relations[${name}]`, collect);\n });\n }\n}\n\n/**\n * Every problem across every collection, in one pass.\n *\n * Pure: it logs nothing and throws nothing, so callers that want to render the\n * list themselves (the doctor, a test) can.\n */\nexport function findCollectionConfigProblems(\n collections: readonly unknown[],\n options: ValidateCollectionConfigOptions = {}\n): ConfigProblem[] {\n const collect = new ProblemCollector(options.unknownKeys ?? unknownKeyPolicyFromEnv());\n collections.forEach((collection, index) => checkCollection(collection, index, collect));\n return collect.problems;\n}\n\nfunction render(problems: ConfigProblem[]): string {\n return problems.map(p => ` • ${p.path}\\n ${p.message}`).join(\"\\n\\n\");\n}\n\n/**\n * Warn about everything questionable, then refuse to boot if anything is wrong.\n *\n * Warnings are logged even when there are errors: someone migrating wants the\n * whole picture in one run, and the second-most annoying thing after a broken\n * boot is a boot that breaks again on something it could have told you the\n * first time.\n */\nexport function assertCollectionConfigs(\n collections: readonly unknown[],\n options: ValidateCollectionConfigOptions = {}\n): void {\n const problems = findCollectionConfigProblems(collections, options);\n if (problems.length === 0) return;\n\n const warnings = problems.filter(p => p.severity === \"warning\");\n const errors = problems.filter(p => p.severity === \"error\");\n\n if (warnings.length > 0) {\n logger.warn(\n `[collections] ${warnings.length} unrecognised key(s) in the collection config, ignored:\\n\\n` +\n render(warnings) +\n \"\\n\\nSet REBASE_STRICT_COLLECTION_CONFIG=error to make these fail the boot.\\n\"\n );\n }\n\n if (errors.length === 0) return;\n\n throw new Error(\n `${errors.length} problem(s) in the collection config.\\n\\n` +\n \"These keys are not read by this version. Nothing would have failed at runtime — \" +\n \"whatever they configure would simply be absent — so they are fatal at boot instead.\\n\\n\" +\n render(errors) + \"\\n\"\n );\n}\n","import { CollectionConfig, SecurityRule, isPostgresCollectionConfig } from \"@rebasepro/types\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport { logger } from \"../utils/logger\";\nimport { assertCollectionConfigs, type ValidateCollectionConfigOptions } from \"./validate-config\";\n\n/**\n * The one definition of \"the collections\".\n *\n * Four copies of this scan used to exist — the runtime, the drizzle-schema\n * generator, the policy generator and the doctor — each deciding for itself\n * which files counted. They agreed only by discipline, and any drift between\n * them would silently serve one set of collections while pushing policies for\n * another. Everything that needs to know what the collections are calls this.\n */\n\n/** Read from a directory's `index` module, or from a single-file source. */\nexport interface CollectionDefaults {\n /**\n * Applied to every collection that declares no `securityRules` of its own.\n *\n * This lives with the collections rather than in the server config because\n * `db push` generates the actual Postgres policies from these files and\n * never sees the running server — a default declared on the server could\n * never reach the database, and would look like an authorization setting\n * while enforcing nothing.\n */\n defaultSecurityRules?: SecurityRule[];\n}\n\nfunction isCollectionFile(file: string): boolean {\n return (file.endsWith(\".ts\") || file.endsWith(\".js\")) &&\n // Dotfiles are never collections. In particular macOS bsdtar puts\n // AppleDouble sidecars (`._foo.ts`) into build contexts — binary blobs\n // whose names end in .ts and whose first byte is \\x00, so importing\n // them kills the whole load.\n !file.startsWith(\".\") &&\n !file.includes(\".test.\") &&\n !file.endsWith(\".d.ts\") &&\n // index is the directory's own module: defaults live there, not a collection.\n file !== \"index.ts\" && file !== \"index.js\";\n}\n\nasync function importModule(filePath: string): Promise<Record<string, unknown>> {\n // Plain import() so tsx/loader hooks resolve .ts and workspace specifiers.\n return await import(pathToFileURL(filePath).href);\n}\n\n/** Read `defaultSecurityRules` from a collections directory's index module. */\nasync function readDefaults(directory: string): Promise<CollectionDefaults> {\n for (const name of [\"index.ts\", \"index.js\"]) {\n const indexPath = path.join(directory, name);\n if (!fs.existsSync(indexPath)) continue;\n try {\n const mod = await importModule(indexPath);\n return { defaultSecurityRules: mod.defaultSecurityRules as SecurityRule[] | undefined };\n } catch (err) {\n // The index usually just re-exports the collections for the frontend;\n // a failure to read it must not take the whole load down.\n logger.warn(`[collections] Could not read defaults from ${name}: ${err instanceof Error ? err.message : String(err)}`);\n return {};\n }\n }\n return {};\n}\n\n/**\n * Apply directory-level defaults. A collection declaring its own rules is left\n * alone; one declaring none inherits these. Declaring neither leaves\n * `securityRules` unset, which the policy generator treats as locked-by-default.\n */\nexport function applyCollectionDefaults(\n collections: CollectionConfig[],\n defaults: CollectionDefaults\n): CollectionConfig[] {\n if (!defaults.defaultSecurityRules?.length) return collections;\n for (const collection of collections) {\n if (isPostgresCollectionConfig(collection) && !collection.securityRules?.length) {\n collection.securityRules = defaults.defaultSecurityRules;\n }\n }\n return collections;\n}\n\n/**\n * Load collections from a directory of collection files, or from a single\n * module exporting `backendCollections` / `collections`.\n *\n * Throws if any file fails to import. A collection that cannot be loaded is a\n * configuration error, and continuing produces the worst outcome available: an\n * API missing a route, or a policy file missing a table, with a successful exit\n * code. Both read as \"no data\" rather than as a failure.\n *\n * Every collection is strict-parsed on the way out — see `validate-config` for\n * why a key that moved is fatal and a key nobody recognises only warns. It\n * happens here, at the one definition of \"the collections\", so the runtime, the\n * schema generator, the policy generator and the doctor all see the same\n * verdict rather than three of them silently accepting a config the fourth\n * rejects.\n */\nexport async function loadCollectionsFromDirectory(\n source: string,\n options: { validate?: false | ValidateCollectionConfigOptions } = {}\n): Promise<CollectionConfig[]> {\n const resolved = path.resolve(source);\n const validate = (collections: CollectionConfig[]): CollectionConfig[] => {\n if (options.validate !== false) assertCollectionConfigs(collections, options.validate ?? {});\n return collections;\n };\n\n if (!fs.existsSync(resolved)) {\n logger.warn(`[collections] Not found: ${resolved}`);\n return [];\n }\n\n // A single module exports the collections, and may export the defaults.\n if (!fs.statSync(resolved).isDirectory()) {\n const mod = await importModule(resolved);\n const collections = (mod.backendCollections || mod.collections || []) as CollectionConfig[];\n return validate(applyCollectionDefaults([...collections], {\n defaultSecurityRules: mod.defaultSecurityRules as SecurityRule[] | undefined\n }));\n }\n\n const collections: CollectionConfig[] = [];\n const failures: string[] = [];\n\n for (const file of fs.readdirSync(resolved).filter(isCollectionFile)) {\n try {\n const mod = await importModule(path.join(resolved, file));\n if (mod?.default) {\n collections.push(mod.default as CollectionConfig);\n } else {\n failures.push(`${file}: no default export`);\n }\n } catch (err) {\n failures.push(`${file}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `Could not load ${failures.length} collection file(s) from ${resolved}:\\n` +\n failures.map((f) => ` • ${f}`).join(\"\\n\") +\n \"\\n\\nEvery collection file must import cleanly and default-export a collection.\"\n );\n }\n\n return validate(applyCollectionDefaults(collections, await readDefaults(resolved)));\n}\n","/**\n * Driver Registry\n *\n * Manages multiple driver delegates for Rebase backend.\n * Allows different databases for different collections.\n *\n * Usage:\n * - Single DB: Pass a single DataDriver → maps to \"(default)\"\n * - Multiple DBs: Pass a map of { dbId: DataDriver }\n * - Collections use `databaseId` property to specify which driver to use\n * - Collections without `databaseId` fallback to \"(default)\"\n */\n\nimport { DataDriver } from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * The default driver identifier used when:\n * - A single driver is provided (not a map)\n * - A collection doesn't specify a databaseId\n */\nexport const DEFAULT_DRIVER_ID = \"(default)\";\n\n/**\n * Registry for managing multiple driver delegates\n */\nexport interface DriverRegistry {\n /**\n * Register a driver delegate with an ID\n * @param id - Unique identifier for this driver (e.g., \"analytics\", \"users\")\n * @param delegate - The DataDriver instance\n */\n register(id: string, delegate: DataDriver): void;\n\n /**\n * Get the default driver delegate (id = \"(default)\")\n * @throws Error if no default driver is registered\n */\n getDefault(): DataDriver;\n\n /**\n * Get a driver delegate by ID\n * @param id - Driver identifier, or undefined/null for default\n * @returns The DataDriver, or undefined if not found\n */\n get(id: string | undefined | null): DataDriver | undefined;\n\n /**\n * Get a driver delegate by ID, with fallback to default\n * @param id - Driver identifier, or undefined/null for default\n * @returns The DataDriver (falls back to default if id not found)\n * @throws Error if neither the specified nor default driver exists\n */\n getOrDefault(id: string | undefined | null): DataDriver;\n\n /**\n * Check if a driver with the given ID exists\n */\n has(id: string): boolean;\n\n /**\n * List all registered driver IDs\n */\n list(): string[];\n\n /**\n * Get the number of registered drivers\n */\n size(): number;\n}\n\n/**\n * Default implementation of DriverRegistry\n */\nexport class DefaultDriverRegistry implements DriverRegistry {\n private delegates = new Map<string, DataDriver>();\n\n /**\n * Create a DriverRegistry from either a single delegate or a map\n * @param input - Single DataDriver (maps to \"(default)\") or Record<string, DataDriver>\n */\n static create(\n input: DataDriver | Record<string, DataDriver>\n ): DefaultDriverRegistry {\n const registry = new DefaultDriverRegistry();\n\n if (isDataDriverDelegate(input)) {\n // Single delegate → register as \"(default)\"\n registry.register(DEFAULT_DRIVER_ID, input);\n } else {\n // Map of delegates → register each\n for (const [id, delegate] of Object.entries(input)) {\n registry.register(id, delegate);\n }\n // Ensure there's a default if not explicitly provided\n if (!registry.has(DEFAULT_DRIVER_ID) && registry.size() > 0) {\n // If no explicit \"(default)\", use the first one as default\n const firstId = Object.keys(input)[0];\n logger.warn(\n `[DriverRegistry] No \"${DEFAULT_DRIVER_ID}\" driver provided. ` +\n `Using \"${firstId}\" as the default.`\n );\n registry.register(DEFAULT_DRIVER_ID, input[firstId]);\n }\n }\n\n return registry;\n }\n\n register(id: string, delegate: DataDriver): void {\n if (this.delegates.has(id)) {\n logger.warn(`[DriverRegistry] Overwriting driver with id \"${id}\"`);\n }\n this.delegates.set(id, delegate);\n }\n\n getDefault(): DataDriver {\n const delegate = this.delegates.get(DEFAULT_DRIVER_ID);\n if (!delegate) {\n throw new Error(\n \"[DriverRegistry] No default driver registered. \" +\n `Register one with id \"${DEFAULT_DRIVER_ID}\" or pass a single DataDriver.`\n );\n }\n return delegate;\n }\n\n get(id: string | undefined | null): DataDriver | undefined {\n if (id === undefined || id === null) {\n return this.delegates.get(DEFAULT_DRIVER_ID);\n }\n return this.delegates.get(id);\n }\n\n getOrDefault(id: string | undefined | null): DataDriver {\n // If no ID specified, return default\n if (id === undefined || id === null) {\n return this.getDefault();\n }\n\n // Try to get by ID\n const delegate = this.delegates.get(id);\n if (delegate) {\n return delegate;\n }\n\n // Fallback to default with warning\n logger.warn(\n `[DriverRegistry] Driver \"${id}\" not found, falling back to \"${DEFAULT_DRIVER_ID}\"`\n );\n return this.getDefault();\n }\n\n has(id: string): boolean {\n return this.delegates.has(id);\n }\n\n list(): string[] {\n return Array.from(this.delegates.keys());\n }\n\n size(): number {\n return this.delegates.size;\n }\n}\n\n/**\n * Type guard to check if an object is a DataDriver\n */\nfunction isDataDriverDelegate(obj: unknown): obj is DataDriver {\n if (typeof obj !== \"object\" || obj === null) {\n return false;\n }\n const delegate = obj as DataDriver;\n // Check for required DataDriver properties\n return (\n typeof delegate.key === \"string\" &&\n typeof delegate.fetchCollection === \"function\" &&\n typeof delegate.fetchOne === \"function\" &&\n typeof delegate.save === \"function\" &&\n typeof delegate.delete === \"function\"\n );\n}\n","import { RealtimeProvider } from \"@rebasepro/types\";\n\n/**\n * A realtime client message as forwarded by the WebSocket server.\n */\ninterface ClientMessage {\n type: string;\n payload?: Record<string, unknown>;\n subscriptionId?: string;\n}\n\n/**\n * The concrete realtime service surface the WebSocket server drives — the\n * typed {@link RealtimeProvider} plus the client-connection methods that\n * every engine's realtime service implements.\n */\nexport interface WsRealtimeService extends RealtimeProvider {\n addClient(clientId: string, ws: unknown): void;\n handleClientMessage(clientId: string, message: ClientMessage, authContext?: unknown): Promise<void> | void;\n}\n\n/** Channel/presence/broadcast messages are engine-agnostic pub/sub. */\nconst CHANNEL_MESSAGE_TYPES = new Set([\n \"join_channel\", \"leave_channel\", \"broadcast\",\n \"presence_track\", \"presence_untrack\", \"presence_state\"\n]);\n\nexport interface RoutedRealtimeOptions {\n /** Per-engine realtime providers, keyed by data-source key. */\n providers: Record<string, RealtimeProvider>;\n /** Key of the default provider (handles channels/presence/broadcast). */\n defaultKey: string;\n /** Resolve a collection path to its data-source key. */\n resolveKey: (collectionPath: string) => string;\n}\n\n/**\n * Compose multiple per-engine {@link RealtimeProvider}s into one that routes\n * each subscription to the provider owning the subscribed collection — the\n * realtime counterpart of `buildRoutedRebaseData`.\n *\n * The WebSocket server stays single and engine-agnostic; this composite is\n * passed in its place. Routing rules:\n * - `subscribe_collection` / `subscribe_entity` → the provider for the\n * collection's data source (by `payload.path`).\n * - `unsubscribe` → forwarded to all providers (a no-op on non-owners).\n * - channel / presence / broadcast → the default provider (these are global\n * pub/sub, not bound to an engine).\n * - `addClient` and lifecycle (`onServerReady`/`destroy`/`stopListening`) →\n * all providers (each registers its own ws close handler for cleanup).\n */\nexport function createRoutedRealtimeService(opts: RoutedRealtimeOptions): WsRealtimeService {\n const { providers, defaultKey, resolveKey } = opts;\n\n const asWs = (p: RealtimeProvider): WsRealtimeService => p as unknown as WsRealtimeService;\n const all = (): WsRealtimeService[] => Object.values(providers).map(asWs);\n const fallback = (): WsRealtimeService => asWs(providers[defaultKey] ?? Object.values(providers)[0]);\n const forPath = (path?: string): WsRealtimeService => {\n if (!path) return fallback();\n const key = resolveKey(path);\n return asWs(providers[key] ?? providers[defaultKey] ?? Object.values(providers)[0]);\n };\n\n return {\n addClient(clientId, ws) {\n for (const p of all()) p.addClient?.(clientId, ws);\n },\n\n async handleClientMessage(clientId, message, authContext) {\n const { type } = message;\n if (type === \"subscribe_collection\" || type === \"subscribe_one\") {\n await forPath(message.payload?.path as string | undefined)\n .handleClientMessage(clientId, message, authContext);\n return;\n }\n if (type === \"unsubscribe\") {\n // The owning provider acts; others no-op on an unknown id.\n await Promise.all(all().map((p) => p.handleClientMessage(clientId, message, authContext)));\n return;\n }\n // Channels/presence/broadcast (and anything else) → default provider.\n await fallback().handleClientMessage(clientId, message, authContext);\n },\n\n subscribeToCollection(subscriptionId, config, callback) {\n forPath((config as { path?: string }).path).subscribeToCollection(subscriptionId, config, callback);\n },\n\n subscribeToOne(subscriptionId, config, callback) {\n forPath((config as { path?: string }).path).subscribeToOne(subscriptionId, config, callback);\n },\n\n unsubscribe(subscriptionId) {\n for (const p of all()) p.unsubscribe(subscriptionId);\n },\n\n async notifyUpdate(path: string, id: string, row: Record<string, unknown> | null, databaseId?: string) {\n await forPath(path).notifyUpdate(path, id, row, databaseId);\n },\n\n onServerReady(serverInfo) {\n for (const p of all()) p.onServerReady?.(serverInfo);\n },\n\n async destroy() {\n await Promise.all(all().map((p) => p.destroy?.()));\n },\n\n async stopListening() {\n await Promise.all(all().map((p) => p.stopListening?.()));\n }\n };\n}\n","import type { FilterValues, LogicalCondition, VectorSearchParams } from \"@rebasepro/types\";\nimport { toCanonicalOp, resolveClientListLimit, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT } from \"@rebasepro/types\";\nimport { deserializeOrderBy, deserializeFilter, deserializeLogicalCondition } from \"@rebasepro/common\";\nimport { QueryOptions } from \"../types\";\nimport { ApiError } from \"../errors\";\n\nexport const mapOperator = (op: string) => toCanonicalOp(op) ?? null;\n\nfunction getLastValue(val: unknown): unknown {\n if (Array.isArray(val)) {\n return val[val.length - 1];\n }\n return val;\n}\n\n/**\n * Parse an `or(...)` / `and(...)` logical group from its wire form.\n *\n * The wire carries the inner conditions wrapped in parens (e.g.\n * `(status.eq.active,age.gte.18)`); we re-attach the `or`/`and` prefix and\n * delegate to the canonical filter dialect (`@rebasepro/common`). Values are\n * preserved as strings — type coercion is the schema-aware driver's job, so\n * this path stays byte-for-byte consistent with the SDK/admin path (which\n * also parses via the shared dialect).\n */\nfunction parseLogicalGroup(type: \"or\" | \"and\", raw: unknown): LogicalCondition | undefined {\n let inner = String(raw).trim();\n if (inner.startsWith(\"(\") && inner.endsWith(\")\")) {\n inner = inner.slice(1, -1);\n }\n inner = inner.trim();\n if (!inner) return undefined;\n const parsed = deserializeLogicalCondition(`${type}(${inner})`);\n return \"type\" in parsed ? parsed : undefined;\n}\n\n/**\n * Parse the `?where=` JSON filter object.\n *\n * This is the dialect the OpenAPI document publishes on every\n * `GET /api/data/{slug}` — `{\"status\":[\"==\",\"active\"]}`: field → canonical\n * `[WhereFilterOp, value]` tuple. It is normalized through the same\n * `deserializeFilter` as the `?field=op.value` params below, so a value that\n * arrives as a PostgREST dot-string (`{\"status\":\"eq.active\"}`) or as a bare\n * scalar (`{\"status\":\"active\"}`) compiles to the same condition. Unlike the\n * querystring dialect, JSON carries types — a number stays a number.\n *\n * A malformed value is a 400 rather than a silent drop: dropping the filter\n * would run the read unfiltered and return everything RLS happens to allow.\n */\nfunction parseWhereParam(raw: unknown): FilterValues<string> | undefined {\n const str = String(raw).trim();\n if (!str) return undefined;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(str);\n } catch {\n throw ApiError.badRequest(\n \"Invalid `where` parameter: expected a JSON object, e.g. {\\\"status\\\":[\\\"==\\\",\\\"active\\\"]}\",\n \"INVALID_WHERE\"\n );\n }\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw ApiError.badRequest(\n \"Invalid `where` parameter: expected a JSON object mapping fields to conditions, \"\n + \"e.g. {\\\"status\\\":[\\\"==\\\",\\\"active\\\"]}\",\n \"INVALID_WHERE\"\n );\n }\n\n const filter = deserializeFilter(parsed as Record<string, unknown>);\n return Object.keys(filter).length > 0 ? filter : undefined;\n}\n\n// Re-exported for callers/tests that reference the REST list bounds. The\n// numbers and clamp live in `@rebasepro/types` so the REST parser and the\n// WebSocket ingress enforce ONE shared guarantee. See `resolveClientListLimit`.\nexport { DEFAULT_LIST_LIMIT, DEFAULT_VECTOR_LIST_LIMIT, MAX_LIST_LIMIT } from \"@rebasepro/types\";\n\n/**\n * Overridable list-pagination bounds for {@link parseQueryOptions}. Without\n * these, `GET /<collection>` with no `?limit` would buffer the ENTIRE table\n * into a JS array + JSON response (a trivial OOM/DoS), and `?limit=100000000`\n * would be honoured verbatim.\n */\nexport interface ListLimitOptions {\n /**\n * Page size used when the client sends no `?limit`. Applied to plain and\n * text-search reads — a vector search falls back to its own default (10).\n */\n defaultLimit?: number;\n /** Upper bound clamped onto any client-supplied `?limit`. */\n maxLimit?: number;\n}\n\n/**\n * Parse query parameters into QueryOptions\n */\nexport function parseQueryOptions(\n query: Record<string, unknown>,\n limits: ListLimitOptions = {}\n): QueryOptions {\n const options: QueryOptions = {};\n const rawLimit = getLastValue(query.limit) as number | string | null | undefined;\n\n const offsetVal = getLastValue(query.offset);\n if (offsetVal) options.offset = parseInt(String(offsetVal));\n\n const pageVal = getLastValue(query.page);\n if (pageVal) {\n const page = parseInt(String(pageVal));\n // Page stride uses the same bounded page size the read will use, so\n // pages neither overlap nor gap. (Vector search never paginates by\n // page, so the plain/text default is correct here.)\n const limit = resolveClientListLimit(rawLimit, {\n defaultLimit: limits.defaultLimit,\n maxLimit: limits.maxLimit\n });\n options.offset = (page - 1) * limit;\n }\n\n // ── Logical conditions (or / and) ──────────────────────────────────\n const orVal = getLastValue(query.or);\n const andVal = getLastValue(query.and);\n if (orVal) {\n const logical = parseLogicalGroup(\"or\", orVal);\n if (logical) options.logical = logical;\n } else if (andVal) {\n const logical = parseLogicalGroup(\"and\", andVal);\n if (logical) options.logical = logical;\n }\n\n // ── PostgREST-style field filters: ?field=op.value ─────────────────\n // Delegate to the canonical filter dialect (the single source of truth\n // for the wire grammar: operator codes, list/escape handling, implicit\n // eq). Values stay strings; the schema-aware driver coerces them to\n // column types. This keeps the REST path byte-for-byte consistent with\n // the SDK/admin path, which parses through the same `deserializeFilter`.\n //\n // `where` is reserved: it is the JSON filter dialect (see\n // `parseWhereParam`), not a column named \"where\". Leaving it out of this\n // list made the documented `?where={...}` compile as a filter on a\n // nonexistent field — which used to be dropped, widening the read to the\n // whole table, and is now a 400 `UNKNOWN_FILTER_FIELD`.\n const reservedQueryKeys = [\"limit\", \"offset\", \"page\", \"orderBy\", \"include\", \"fields\", \"searchString\", \"vector_search\", \"vector\", \"vector_distance\", \"vector_threshold\", \"or\", \"and\", \"where\"];\n const filterDict: Record<string, unknown> = {};\n for (const [key, rawValue] of Object.entries(query)) {\n if (reservedQueryKeys.includes(key)) continue;\n filterDict[key] = rawValue;\n }\n // Both dialects may be sent together; an explicit `?field=op.value` wins\n // over the same field inside `where`, being the more specific request.\n const whereVal = getLastValue(query.where);\n const where = {\n ...(whereVal !== undefined && whereVal !== null ? parseWhereParam(whereVal) : undefined),\n ...deserializeFilter(filterDict)\n };\n if (Object.keys(where).length > 0) {\n options.where = where;\n }\n\n // Sorting\n const orderByVal = getLastValue(query.orderBy);\n if (orderByVal) {\n try {\n options.orderBy = typeof orderByVal === \"string\"\n ? JSON.parse(orderByVal)\n : orderByVal;\n } catch {\n // Try simple format: \"field:direction\"\n if (typeof orderByVal === \"string\") {\n const parsed = deserializeOrderBy(orderByVal);\n if (parsed) {\n options.orderBy = [\n {\n field: parsed[0],\n direction: parsed[1]\n }\n ];\n }\n }\n }\n }\n\n // Relation includes\n const includeVal = getLastValue(query.include);\n if (includeVal) {\n const includeStr = String(includeVal).trim();\n if (includeStr === \"*\") {\n options.include = [\"*\"];\n } else {\n options.include = includeStr.split(\",\").map(s => s.trim()).filter(Boolean);\n }\n }\n\n // Field selection\n const fieldsVal = getLastValue(query.fields);\n if (fieldsVal) {\n const fieldsStr = String(fieldsVal).trim();\n options.fields = fieldsStr.split(\",\").map(s => s.trim()).filter(Boolean);\n }\n\n // ── Vector similarity search ───────────────────────────────────────\n // Every rejection here is a malformed *request*, so it must carry a 400.\n // A bare `Error` reaches the handler with no `statusCode` and no known\n // `code`, which makes it a 500 — logged with a full stack as an incident,\n // and answered with \"An unexpected error occurred\", because the handler\n // only forwards a message to the client below 500. The caller was told\n // nothing about what it got wrong.\n const vectorSearchVal = getLastValue(query.vector_search);\n const vectorVal = getLastValue(query.vector);\n if (vectorSearchVal && vectorVal) {\n const vectorStr = String(vectorVal);\n let decoded: unknown;\n try {\n decoded = JSON.parse(vectorStr);\n } catch {\n decoded = undefined;\n }\n // Validated outside the `try` on purpose: inside it, the thrown\n // ApiError would be caught by its own `catch` and re-thrown as\n // something else.\n if (!Array.isArray(decoded) || !decoded.every(v => typeof v === \"number\")) {\n throw ApiError.badRequest(\n \"Invalid `vector` format. Expected a JSON array of numbers, e.g. [0.1,0.2,0.3]\",\n \"INVALID_VECTOR\"\n );\n }\n const queryVector = decoded as number[];\n\n const distanceParamVal = getLastValue(query.vector_distance);\n const distanceParam = distanceParamVal ? String(distanceParamVal) : \"cosine\";\n if (distanceParam !== \"cosine\" && distanceParam !== \"l2\" && distanceParam !== \"inner_product\") {\n throw ApiError.badRequest(\n `Invalid \\`vector_distance\\`: ${distanceParam}. Expected: cosine, l2, or inner_product`,\n \"INVALID_VECTOR_DISTANCE\"\n );\n }\n\n const vectorSearch: VectorSearchParams = {\n property: String(vectorSearchVal),\n vector: queryVector,\n distance: distanceParam\n };\n\n const thresholdVal = getLastValue(query.vector_threshold);\n if (thresholdVal) {\n const threshold = parseFloat(String(thresholdVal));\n if (isNaN(threshold)) {\n throw ApiError.badRequest(\n \"Invalid `vector_threshold`. Expected a number.\",\n \"INVALID_VECTOR_THRESHOLD\"\n );\n }\n vectorSearch.threshold = threshold;\n }\n\n options.vectorSearch = vectorSearch;\n }\n\n // Resolve the limit LAST — once we know whether this is a vector search —\n // so a client-supplied limit is clamped to the hard max and an absent one\n // falls back to the correct mode default (plain/text = defaultLimit, vector\n // = 10). Without this a bare `GET /<collection>` would return the whole\n // table. Shared with the WebSocket ingress via `resolveClientListLimit`.\n options.limit = resolveClientListLimit(rawLimit, {\n vectorSearch: !!options.vectorSearch,\n defaultLimit: limits.defaultLimit,\n maxLimit: limits.maxLimit\n });\n\n return options;\n}\n","import { CollectionConfig, type ResolvedBelongsTo } from \"@rebasepro/types\";\nimport { resolveCollectionRelations } from \"@rebasepro/common\";\nimport { ApiError } from \"../errors\";\n\n/**\n * Reject a write naming a field the collection does not have.\n *\n * Unknown keys used to travel all the way into the INSERT, where Postgres\n * rejected them — so a typo came back as `column \"titel\" does not exist`,\n * phrased by the database, from a stack the caller cannot see, and only if the\n * column really was absent. It is a request problem and belongs in a 400.\n *\n * What counts as known:\n * - a declared property (for an introspected BaaS collection these *are* the\n * columns, so the set is exact);\n * - the foreign-key column behind an owning relation, which callers may write\n * directly instead of through the relation property;\n * - anything named in `options.extraKnownFields` — for an auth collection the\n * credential keys the auth adapter consumes before a row is ever built;\n * - nothing else. `id` in particular is not automatically known — see below.\n */\nexport function assertKnownWriteFields(\n values: Record<string, unknown>,\n collection: CollectionConfig,\n options?: { rowIndex?: number; extraKnownFields?: readonly string[] }\n): void {\n if (collection.strictWrites === false) return;\n\n // A collection that declares no properties describes nothing, so there is\n // nothing to check against — \"no declared fields\" is not the same claim as\n // \"no fields are allowed\", and reading it as the latter would turn every\n // write to such a collection into a 400. Postgres still has the last word.\n if (!collection.properties || Object.keys(collection.properties).length === 0) return;\n\n const known = new Set<string>(Object.keys(collection.properties));\n\n // An owning relation stores its target in a local FK column that usually\n // has no property of its own; writing it directly is legitimate.\n for (const relation of Object.values(resolveCollectionRelations(collection))) {\n if (relation.kind === \"belongsTo\") known.add((relation as ResolvedBelongsTo).localKey);\n }\n\n for (const field of options?.extraKnownFields ?? []) known.add(field);\n\n const unknown = Object.keys(values).filter(key => !known.has(key));\n if (unknown.length === 0) return;\n\n const where = options?.rowIndex !== undefined ? `Row ${options.rowIndex}: ` : \"\";\n\n // The `id` case is worth its own sentence, because the caller almost\n // certainly did not choose to send it — `create(data, id)` puts it there,\n // which is right for a table keyed on `id` and meaningless for any other.\n if (unknown.includes(\"id\") && !known.has(\"id\")) {\n const keys = Object.entries(collection.properties ?? {})\n .filter(([, prop]) => \"isId\" in (prop as object) && Boolean((prop as { isId?: unknown }).isId))\n .map(([name]) => `'${name}'`);\n const keyDesc = keys.length > 0 ? keys.join(\" + \") : \"its own key column\";\n throw ApiError.badRequest(\n `${where}'${collection.slug}' has no 'id' column — it is keyed on ${keyDesc}. ` +\n `The \\`id\\` argument of \\`create(data, id)\\` is written as an \\`id\\` column, so for this ` +\n `collection put the key in \\`data\\` instead.`,\n \"VALIDATION_UNKNOWN_FIELDS\"\n );\n }\n\n throw ApiError.badRequest(\n `${where}'${collection.slug}' has no field${unknown.length > 1 ? \"s\" : \"\"} ` +\n `${unknown.map(f => `'${f}'`).join(\", \")}. ` +\n `Known fields: ${[...known].sort().map(f => `'${f}'`).join(\", \")}.`,\n \"VALIDATION_UNKNOWN_FIELDS\"\n );\n}\n\n/**\n * Narrow response rows to the fields the caller asked for.\n *\n * `?fields=id,title` is documented in the generated OpenAPI — \"Comma-separated\n * list of fields to return (field selection)\" — and it is the first thing shown\n * on every endpoint in the API Explorer. It was parsed into `options.fields`\n * and then read by nothing at all: no driver referenced it, and every request\n * came back with every column. A caller asking for two fields of a `posts` row\n * still received its whole `content`.\n *\n * This shapes the *response*, which is what the parameter says it does; it is\n * not a column pushdown, so it saves bandwidth rather than database work.\n *\n * `id` always survives. Rows are addressed by it everywhere above this layer —\n * the admin table, realtime reconciliation, the offline cache — and a row that\n * arrives without one is not a smaller row, it is an unusable one. Asking for\n * `fields=title` and being unable to open the record you clicked is a worse\n * answer than one extra key.\n */\nexport function projectResponseFields<T extends Record<string, unknown>>(\n rows: T[],\n fields: readonly string[] | undefined,\n collection: CollectionConfig,\n options?: { include?: readonly string[] }\n): T[] {\n if (!fields || fields.length === 0) return rows;\n\n const declared = new Set<string>(Object.keys(collection.properties ?? {}));\n // The record is keyed by the property name the relation is reached under,\n // which is the name a caller would put in `fields`.\n for (const [key, relation] of Object.entries(resolveCollectionRelations(collection))) {\n declared.add(key);\n if (relation.kind === \"belongsTo\") declared.add((relation as ResolvedBelongsTo).localKey);\n }\n // `include` decides what is *loaded*; `fields` decides what is *returned*.\n // So `include=author&fields=title,author` yields both, and naming the\n // relation in `fields` without including it yields nothing for it — there\n // was nothing fetched to return. Included names are accepted here so that\n // a relation reached only through `include` (one the collection does not\n // declare as a property) is not rejected as unknown.\n for (const included of options?.include ?? []) declared.add(included);\n declared.add(\"id\");\n\n // A collection that declares nothing describes nothing to check against —\n // the same reasoning `assertKnownWriteFields` applies one function up.\n if (declared.size > 1) {\n const unknown = fields.filter(field => !declared.has(field));\n if (unknown.length > 0) {\n throw ApiError.badRequest(\n `'${collection.slug}' has no field${unknown.length > 1 ? \"s\" : \"\"} ` +\n `${unknown.map(f => `'${f}'`).join(\", \")} to return. ` +\n `Known fields: ${[...declared].sort().map(f => `'${f}'`).join(\", \")}.`,\n \"UNKNOWN_RESPONSE_FIELD\",\n { fields: unknown, collection: collection.slug }\n );\n }\n }\n\n const keep = new Set<string>([...fields, \"id\"]);\n return rows.map(row => {\n const projected: Record<string, unknown> = {};\n for (const key of Object.keys(row)) {\n if (keep.has(key)) projected[key] = row[key];\n }\n return projected as T;\n });\n}\n","import { DataDriver, isSQLAdmin } from \"@rebasepro/types\";\nimport { logger } from \"../../utils/logger\";\n\n/**\n * Remembering what a write already answered, so replaying it does not do it twice.\n *\n * The offline queue replays a mutation whenever it did not see the response —\n * which includes every case where the write *committed* and the ACK was lost to\n * a dropped connection. For a collection whose id the client chooses, the replay\n * collides on that id and the client can recognise its own earlier attempt. For\n * a collection with a serial id it cannot: the server ignored the id the client\n * invented and assigned its own, so the replay is indistinguishable from a new\n * row and inserts a second one. The scaffold's own collections use\n * `isId: \"increment\"`, so that is the default case, not an exotic one.\n *\n * A key is honoured only for the principal that created it. Mutation ids are\n * generated on the client, so keying on the id alone would let anyone who\n * learned (or guessed) another user's id replay their key and be handed that\n * user's row back — a read of someone else's data through a write endpoint.\n */\nconst TABLE = \"\\\"rebase\\\".\\\"idempotency_keys\\\"\";\n\n/**\n * How long a replay is recognised. Long enough to cover an offline stretch and\n * a retry schedule; short enough that the table stays small and a key cannot be\n * replayed indefinitely. Rows past this are pruned opportunistically rather than\n * by a scheduled job — there is no cron guaranteed to be running.\n */\nconst TTL_HOURS = 24;\n\n/**\n * The principal a key belongs to; anonymous and service writes share a sentinel.\n *\n * The NUL is written as an escape, not as a raw byte in the source. The\n * sentinel itself is deliberate — a uid can never contain one — but written\n * literally it makes this file test as binary, and every repo-wide grep then\n * skips all 124 lines of it silently. Identical at runtime.\n */\nfunction principal(uid: string | undefined): string {\n return uid && uid.length > 0 ? uid : \"\\u0000anon\";\n}\n\nexport interface IdempotencyStore {\n /** What this key answered before, or `undefined` if it is new. */\n recall(key: string, uid: string | undefined): Promise<unknown | undefined>;\n /** Record what this key answered. Never throws — see {@link createIdempotencyStore}. */\n remember(key: string, uid: string | undefined, response: unknown): Promise<void>;\n}\n\n/**\n * Returns `undefined` when the driver cannot run SQL, which disables the whole\n * mechanism rather than failing writes: a document backend has no table to put\n * this in, and refusing to serve is far worse than the duplicate this prevents.\n *\n * Every method swallows its own errors for the same reason. A write must not\n * fail because the bookkeeping around it did — the worst case of a failed\n * `remember` is the duplicate we already have today, while a thrown error would\n * reject a write the database has already accepted.\n */\nexport function createIdempotencyStore(driver: DataDriver): IdempotencyStore | undefined {\n const admin = driver.admin;\n if (!isSQLAdmin(admin)) return undefined;\n const exec = (sql: string, params?: unknown[]) => admin.executeSql(sql, params ? { params } : undefined);\n\n let ready: Promise<boolean> | undefined;\n /** Created on first use: most deployments never send a key at all. */\n const ensure = (): Promise<boolean> => {\n ready ??= (async () => {\n try {\n await exec(\"CREATE SCHEMA IF NOT EXISTS rebase\");\n await exec(`\n CREATE TABLE IF NOT EXISTS ${TABLE} (\n key TEXT NOT NULL,\n uid TEXT NOT NULL,\n response JSONB,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n PRIMARY KEY (uid, key)\n )\n `);\n await exec(`CREATE INDEX IF NOT EXISTS idx_idempotency_created ON ${TABLE}(created_at)`);\n return true;\n } catch (error) {\n logger.warn(\n \"Idempotency keys unavailable — a replayed offline write may insert a duplicate row.\",\n { detail: error instanceof Error ? error.message : String(error) }\n );\n return false;\n }\n })();\n return ready;\n };\n\n return {\n async recall(key, uid) {\n if (!key || !(await ensure())) return undefined;\n try {\n const rows = await exec(\n `SELECT response FROM ${TABLE}\n WHERE uid = $1 AND key = $2 AND created_at > NOW() - INTERVAL '${TTL_HOURS} hours'`,\n [principal(uid), key]\n );\n return rows[0]?.response;\n } catch {\n return undefined;\n }\n },\n\n async remember(key, uid, response) {\n if (!key || !(await ensure())) return;\n try {\n // ON CONFLICT DO NOTHING: two tabs replaying the same key at\n // once must not turn a race into a 23505 that fails the write.\n await exec(\n `INSERT INTO ${TABLE} (key, uid, response) VALUES ($1, $2, $3::jsonb)\n ON CONFLICT (uid, key) DO NOTHING`,\n [key, principal(uid), JSON.stringify(response ?? null)]\n );\n // Cheap and unsynchronised on purpose: an occasional extra pass\n // costs less than a scheduler this package cannot assume exists.\n if (Math.random() < 0.01) {\n await exec(`DELETE FROM ${TABLE} WHERE created_at < NOW() - INTERVAL '${TTL_HOURS} hours'`);\n }\n } catch {\n /* Bookkeeping only — never fail the write it describes. */\n }\n }\n };\n}\n\n/** The header the client sends. Matches the widely used Stripe/IETF spelling. */\nexport const IDEMPOTENCY_HEADER = \"Idempotency-Key\";\n","import { Hono, type Context } from \"hono\";\nimport { AuthAdapter, DataDriver, CollectionConfig, getCollectionDataPath } from \"@rebasepro/types\";\nimport { QueryOptions, HonoEnv } from \"../types\";\nimport { ApiError, isRebaseApiError } from \"../errors\";\nimport { parseQueryOptions, DEFAULT_LIST_LIMIT, MAX_LIST_LIMIT, type ListLimitOptions } from \"./query-parser\";\nimport { assertKnownWriteFields, projectResponseFields } from \"./write-validation\";\nimport { httpMethodToOperation, isOperationAllowed } from \"../../auth/api-keys/api-key-permission-guard\";\nimport type { ApiKeyMasked } from \"../../auth/api-keys/api-key-types\";\nimport { findRelation, resolveCollectionRelations } from \"@rebasepro/common\";\nimport { createIdempotencyStore, IDEMPOTENCY_HEADER, type IdempotencyStore } from \"./idempotency\";\n\n/**\n * Parse a JSON request body for a create/update. An empty body yields `{}`\n * (a valid \"no explicit fields\" write), but a **malformed** body throws a 400\n * rather than being silently swallowed to `{}` — which would turn bad input\n * into an unintended empty write.\n */\nasync function parseJsonBody(c: Context<HonoEnv>): Promise<Record<string, unknown>> {\n const raw = await c.req.text();\n if (!raw || raw.trim() === \"\") return {};\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch {\n throw ApiError.badRequest(\"Invalid JSON body\");\n }\n}\n\n\n\n/**\n * Lightweight REST API generator that leverages existing Rebase DataDriver.\n * Supports `include` query parameter for eager-loading relations via Drizzle.\n */\n/** Rows accepted by a single POST /<collection>/bulk. See `maxBulkRows`. */\nexport const DEFAULT_MAX_BULK_ROWS = 1000;\n\nexport class RestApiGenerator {\n private collections: CollectionConfig[];\n private router: Hono<HonoEnv>;\n private driver: DataDriver;\n private maxBulkRows: number;\n private listLimits: ListLimitOptions;\n\n private authAdapter?: AuthAdapter;\n\n constructor(\n collections: CollectionConfig[],\n driver: DataDriver,\n authAdapter?: AuthAdapter,\n maxBulkRows: number = DEFAULT_MAX_BULK_ROWS,\n listLimits: ListLimitOptions = {}\n ) {\n this.collections = collections;\n this.driver = driver;\n this.authAdapter = authAdapter;\n this.maxBulkRows = maxBulkRows;\n this.listLimits = {\n defaultLimit: listLimits.defaultLimit ?? DEFAULT_LIST_LIMIT,\n maxLimit: listLimits.maxLimit ?? MAX_LIST_LIMIT\n };\n this.router = new Hono<HonoEnv>();\n }\n\n /**\n * Built on first use rather than in the constructor: it probes the driver\n * for SQL support and creates a table, and most requests never send a key.\n */\n private idempotencyStore?: IdempotencyStore | null;\n private idempotency(): IdempotencyStore | undefined {\n this.idempotencyStore ??= createIdempotencyStore(this.driver) ?? null;\n return this.idempotencyStore ?? undefined;\n }\n\n /**\n * Parse request query params into QueryOptions, applying this generator's\n * list-pagination bounds (default page size + hard max limit) so no read\n * path can be tricked into buffering an entire table into memory.\n */\n private parseQuery(queryDict: Record<string, unknown>): QueryOptions {\n return parseQueryOptions(queryDict, this.listLimits);\n }\n\n\n\n /**\n * Generate REST routes using existing DataDriver\n */\n generateRoutes(): Hono<HonoEnv> {\n this.collections.forEach(collection => {\n this.createCollectionRoutes(collection);\n });\n\n // Catch-all routes for subcollection paths like\n // /authors/111094/posts and /authors/111094/posts/43\n // The DataDriver already knows how to resolve nested relation paths.\n this.createSubcollectionRoutes();\n\n return this.router;\n }\n\n /**\n * Check API key permissions for a collection operation.\n * Throws 403 if the key doesn't have the required permission.\n * No-ops if the request is not authenticated via an API key.\n */\n private enforceApiKeyPermission(\n c: { get: (key: string) => unknown; req: { method: string } },\n collectionSlug: string\n ): void {\n const apiKey = c.get(\"apiKey\") as ApiKeyMasked | undefined;\n if (!apiKey) return; // Not an API key request — skip\n\n const operation = httpMethodToOperation(c.req.method);\n if (!isOperationAllowed(apiKey.permissions, collectionSlug, operation)) {\n throw ApiError.forbidden(\n `API key does not have \"${operation}\" permission for collection \"${collectionSlug}\"`,\n \"API_KEY_FORBIDDEN\"\n );\n }\n }\n\n /**\n * API key permission check for nested paths. The operation targets the\n * LAST collection in the path (e.g. \"posts\" for /authors/1/posts), so\n * that is the slug the key must hold permission for — checking the\n * parent instead would let a key scoped to \"authors\" write \"posts\".\n * `parseSubPath` always yields a collectionPath ending in a collection\n * slug, never an id.\n */\n private enforceSubcollectionApiKeyPermission(\n c: { get: (key: string) => unknown; req: { method: string } },\n collectionPath: string\n ): void {\n this.enforceApiKeyPermission(c, collectionPath.split(\"/\").pop()!);\n }\n\n /**\n * The collection a nested path writes into — the target of the relation its\n * last segment names.\n *\n * Needed so a nested write can be checked against a schema at all. Without\n * it these routes skipped `assertKnownWriteFields` entirely, which is why a\n * typo `POST /posts` rejected with a 400 while the same typo on\n * `POST /authors/1/posts` reached the database.\n *\n * Returns `undefined` rather than throwing when the path cannot be walked:\n * the driver raises the authoritative error a moment later, and duplicating\n * it here would report a resolution failure as a validation failure.\n */\n private resolveNestedWriteCollection(collectionPath: string): CollectionConfig | undefined {\n const segments = collectionPath.split(\"/\").filter(s => s && s !== \"undefined\");\n let current = this.collections.find(c => c.slug === segments[0]);\n\n for (let i = 2; i < segments.length && current; i += 2) {\n const relation = findRelation(resolveCollectionRelations(current), segments[i]);\n if (!relation) return undefined;\n try {\n const target = relation.target();\n current = this.collections.find(c => c.slug === target?.slug) ?? target;\n } catch {\n return undefined;\n }\n }\n\n return current;\n }\n\n /**\n * Get the request-scoped driver. Throws if none is set — never falls\n * back to the unscoped `this.driver` to avoid bypassing RLS/auth.\n */\n private getScopedDriver(c: { get: (key: string) => unknown }): DataDriver {\n const driver = c.get(\"driver\") as DataDriver | undefined;\n if (!driver) throw ApiError.internal(\"Scoped driver not available\");\n return driver;\n }\n\n\n\n /**\n * Create REST routes for a collection using existing Rebase patterns\n */\n private createCollectionRoutes(collection: CollectionConfig): void {\n const basePath = `/${collection.slug}`;\n const resolvedCollection = collection;\n\n // GET /collection/count - Count entities (with optional filters)\n this.router.get(`${basePath}/count`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n const driver = this.getScopedDriver(c);\n\n const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);\n return c.json({ count: total });\n });\n\n // GET /collection - List entities\n this.router.get(basePath, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n\n const driver = this.getScopedDriver(c);\n const fetchService = driver.restFetchService;\n\n // Use include-aware path when available\n const entities = fetchService\n ? await fetchService.fetchCollectionForRest(\n collection.slug,\n {\n filter: queryOptions.where,\n // `?or=`/`?and=` were parsed and then dropped right here,\n // so a filtered read returned every row RLS allowed.\n logical: queryOptions.logical,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n orderBy: queryOptions.orderBy?.[0]?.field,\n order: queryOptions.orderBy?.[0]?.direction === \"desc\" ? \"desc\" : \"asc\",\n searchString,\n vectorSearch: queryOptions.vectorSearch\n },\n queryOptions.include\n )\n : await this.fetchRawCollection(driver, resolvedCollection, queryOptions, searchString);\n\n const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);\n\n return c.json({\n data: projectResponseFields(\n entities as Record<string, unknown>[],\n queryOptions.fields,\n resolvedCollection,\n { include: queryOptions.include }\n ),\n meta: {\n total,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n hasMore: (queryOptions.offset || 0) + entities.length < total\n }\n });\n });\n\n // GET /collection/:id - Get single entity\n this.router.get(`${basePath}/:id`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const id = c.req.param(\"id\");\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const driver = this.getScopedDriver(c);\n const fetchService = driver.restFetchService;\n\n // Use include-aware path when available\n const entity = fetchService\n ? await fetchService.fetchOneForRest(collection.slug, String(id), queryOptions.include)\n : await this.fetchRawEntity(driver, resolvedCollection, String(id));\n\n if (!entity) {\n throw ApiError.notFound(\"Entity not found\");\n }\n\n return c.json(projectResponseFields(\n [entity as Record<string, unknown>],\n queryOptions.fields,\n resolvedCollection,\n { include: queryOptions.include }\n )[0]);\n });\n\n // POST /collection/bulk - Write many rows as one transaction.\n //\n // Registered before POST /collection/:id-shaped routes so \"bulk\" is never\n // read as an id.\n this.router.post(`${basePath}/bulk`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const driver = this.getScopedDriver(c);\n const path = collection.slug;\n\n const body = await parseJsonBody(c) as { rows?: unknown; upsert?: unknown };\n\n if (!Array.isArray(body?.rows)) {\n throw ApiError.badRequest(\n \"Expected a JSON body of { rows: [...] }.\",\n \"INVALID_BULK_BODY\"\n );\n }\n if (body.rows.length === 0) {\n return c.json({ data: [], meta: { written: 0 } });\n }\n if (body.rows.some((row) => typeof row !== \"object\" || row === null || Array.isArray(row))) {\n throw ApiError.badRequest(\n \"Every entry in `rows` must be an object.\",\n \"INVALID_BULK_BODY\"\n );\n }\n if (body.upsert !== undefined && typeof body.upsert !== \"boolean\") {\n throw ApiError.badRequest(\"`upsert` must be a boolean.\", \"INVALID_BULK_BODY\");\n }\n\n const maxRows = this.maxBulkRows;\n if (body.rows.length > maxRows) {\n // A batch is one transaction, which holds locks for its whole\n // duration; an unbounded one is a self-inflicted outage. Say the\n // limit and the actual count so the caller can chunk to it.\n throw ApiError.badRequest(\n `Too many rows: ${body.rows.length} exceeds the ${maxRows}-row limit for a single bulk write. ` +\n `Send it in chunks of ${maxRows} or fewer.`,\n \"BULK_TOO_LARGE\"\n );\n }\n\n if (!driver.saveMany) {\n throw ApiError.badRequest(\n \"This collection's data source does not support bulk writes.\",\n \"BULK_UNSUPPORTED\"\n );\n }\n\n // Checked before the transaction opens, and named by row index: a\n // batch is all-or-nothing, so one bad field in ten thousand rows\n // should not be found by rolling the other 9,999 back.\n (body.rows as Record<string, unknown>[]).forEach((row, rowIndex) =>\n assertKnownWriteFields(row, resolvedCollection, { rowIndex }));\n\n const rows = await driver.saveMany({\n path,\n rows: body.rows as Record<string, unknown>[],\n collection: resolvedCollection,\n upsert: body.upsert === true\n });\n\n return c.json({\n data: rows.map((row) => this.formatResponse(row)),\n meta: { written: rows.length }\n });\n });\n\n // POST /collection - Create entity\n this.router.post(basePath, async (c) => {\n try {\n this.enforceApiKeyPermission(c, collection.slug);\n const driver = this.getScopedDriver(c);\n const path = collection.slug;\n\n\n const body = await parseJsonBody(c);\n\n const isAuth = collection.auth;\n const isAuthCollection = isAuth === true || (isAuth && typeof isAuth === \"object\" && isAuth.enabled === true);\n\n const collectionAuthConfig = typeof isAuth === \"object\" ? isAuth : undefined;\n\n // Auth signups carry credential fields (`password`, provider\n // bits) that the users collection does not declare as columns —\n // `prepareUserCreation` turns them into what the table has. The\n // adapter says which those are, so the body can still be checked\n // for everything else. Skipping the check outright (as this used\n // to) meant a typo on the users table was silently dropped and\n // answered 201, while the same typo on `posts` was a 400.\n if (!isAuthCollection) {\n assertKnownWriteFields(body, resolvedCollection);\n } else {\n const contract = this.authAdapter?.describeUserCreationContract?.(collectionAuthConfig);\n if (contract?.validate) {\n assertKnownWriteFields(body, resolvedCollection, {\n extraKnownFields: contract.extraFields\n });\n }\n }\n\n if (isAuthCollection && this.authAdapter?.prepareUserCreation) {\n const prepared = await this.authAdapter.prepareUserCreation(body, collectionAuthConfig);\n\n const entity = await driver.save({\n path,\n values: prepared.values,\n collection: resolvedCollection,\n status: \"new\"\n });\n\n const result = prepared.hookHandledEmail\n ? { temporaryPassword: prepared.clearPassword,\ninvitationSent: prepared.invitationSent }\n : this.authAdapter.finalizeUserCreation\n ? await this.authAdapter.finalizeUserCreation(\n // `driver.save` returns the flat row — the row IS the\n // values. Reading `entity.values` here (an Entity-era\n // leftover) handed the adapter `undefined`, whose\n // `.email` threw inside the invite-email try block —\n // reported as \"email delivery failed\", so no\n // invitation was ever sent.\n { id: entity.id as string,\nvalues: entity as Record<string, unknown> },\n prepared.clearPassword\n )\n : { invitationSent: false };\n\n const response = this.formatResponse(entity) as Record<string, unknown>;\n\n\n\n return c.json({\n ...response,\n invitationSent: result.invitationSent,\n ...(result.temporaryPassword ? { temporaryPassword: result.temporaryPassword } : {}),\n ...(\"emailDeliveryFailed\" in result && result.emailDeliveryFailed ? { emailDeliveryFailed: true } : {})\n }, 201);\n }\n\n // Deliberately not applied to the auth-signup branch above: that\n // response can carry a temporary password, and handing it out\n // again on a replayed key is a credential disclosure the plain\n // data path has no equivalent of.\n const idempotencyKey = c.req.header(IDEMPOTENCY_HEADER);\n const uid = (c.get(\"user\") as { uid?: string } | undefined)?.uid;\n const store = this.idempotency();\n if (idempotencyKey && store) {\n const already = await store.recall(idempotencyKey, uid);\n // `null` is a legitimate stored body, so presence is the\n // test — not truthiness.\n if (already !== undefined) return c.json(already as never, 201);\n }\n\n const entity = await driver.save({\n path,\n values: body,\n collection: resolvedCollection,\n status: \"new\"\n });\n\n const response = this.formatResponse(entity);\n\n if (idempotencyKey && store) {\n await store.remember(idempotencyKey, uid, response);\n }\n\n return c.json(response, 201);\n } catch (error) {\n if (isRebaseApiError(error) && !error.code) {\n // Only classify as BAD_REQUEST if it's an operational error\n // (e.g. validation, DB constraints). Runtime bugs like TypeError,\n // RangeError etc. should remain as 500 INTERNAL_ERROR.\n const isRuntimeBug = error instanceof TypeError\n || error instanceof RangeError\n || error instanceof SyntaxError\n || error instanceof ReferenceError;\n if (!isRuntimeBug) {\n error.code = \"BAD_REQUEST\";\n }\n }\n throw error;\n }\n });\n\n // PUT /collection/:id - Update entity\n this.router.put(`${basePath}/:id`, async (c) => {\n try {\n this.enforceApiKeyPermission(c, collection.slug);\n const id = c.req.param(\"id\");\n const driver = this.getScopedDriver(c);\n\n\n const existingEntity = await driver.fetchOne({\n path: getCollectionDataPath(collection),\n id: String(id),\n collection: resolvedCollection\n });\n\n if (!existingEntity) {\n throw ApiError.notFound(\"Entity not found\");\n }\n\n const body = await parseJsonBody(c);\n assertKnownWriteFields(body, resolvedCollection);\n\n const entity = await driver.save({\n path: getCollectionDataPath(collection),\n id: String(id),\n values: body,\n collection: resolvedCollection,\n status: \"existing\"\n });\n\n const response = this.formatResponse(entity);\n\n\n\n return c.json(response);\n } catch (error) {\n if (isRebaseApiError(error) && !error.code) {\n // Only classify as BAD_REQUEST if it's an operational error.\n // Runtime bugs (TypeError, RangeError, etc.) stay as 500.\n const isRuntimeBug = error instanceof TypeError\n || error instanceof RangeError\n || error instanceof SyntaxError\n || error instanceof ReferenceError;\n if (!isRuntimeBug) {\n error.code = \"BAD_REQUEST\";\n }\n }\n throw error;\n }\n });\n\n // DELETE /collection/:id - Delete entity\n this.router.delete(`${basePath}/:id`, async (c) => {\n this.enforceApiKeyPermission(c, collection.slug);\n const id = c.req.param(\"id\");\n const driver = this.getScopedDriver(c);\n\n\n const existingEntity = await driver.fetchOne({\n path: getCollectionDataPath(collection),\n id: String(id),\n collection: resolvedCollection\n });\n\n if (!existingEntity) {\n throw ApiError.notFound(\"Entity not found\");\n }\n\n await driver.delete({\n row: {\n // The address is the one in the URL, not something read back\n // off the row: a row is only its columns, so `existingEntity.id`\n // is undefined for any table not keyed on `id` — and the delete\n // went looking for a row called \"undefined\".\n id: String(id),\n path: getCollectionDataPath(collection),\n values: existingEntity\n },\n collection: resolvedCollection\n });\n\n\n\n return new Response(null, { status: 204 });\n });\n }\n\n /**\n * Catch-all routes for subcollection paths.\n *\n * Matches URL patterns like:\n * GET /authors/111094/posts → list child collection\n * GET /authors/111094/posts/43 → get child entity\n * POST /authors/111094/posts → create child entity\n * PUT /authors/111094/posts/43 → update child entity\n * DELETE /authors/111094/posts/43 → delete child entity\n *\n * The `:rest{.+}` regex param captures the full remainder of the URL\n * path (Hono v4 `*` wildcard does not populate `c.req.param(\"*\")`).\n * We split it into segments and reconstruct the `collectionPath`\n * (e.g. \"authors/111094/posts\") and optional `id` (e.g. \"43\").\n *\n * The DataDriver.save / fetchCollection / etc. already know how to\n * resolve multi-segment relation paths, so we just forward to them.\n */\n private createSubcollectionRoutes(): void {\n // Reserved path segments that should NOT be treated as relation names.\n // These are handled by dedicated route handlers (e.g., history routes)\n // mounted on the same data router.\n const RESERVED_SEGMENTS = new Set([\"history\"]);\n\n // Helper: parse a path like \"authors/111094/posts/43\" into\n // { collectionPath: \"authors/111094/posts\", id: \"43\" }\n // or \"authors/111094/posts\" into\n // { collectionPath: \"authors/111094/posts\", id: undefined }\n const parseSubPath = (rawPath: string): { collectionPath: string; id?: string } | null => {\n const segments = rawPath.split(\"/\").filter(Boolean);\n // A literal \"undefined\" segment is a client that interpolated a\n // variable it did not have. The whole-`rest` case is already refused\n // by the route guards above; this used to *drop* the segment, so\n // `/authors/123/undefined/posts` was quietly answered with the\n // contents of `/authors/123/posts`. Serving a path nobody asked for\n // is worse than refusing the one they did: the caller gets rows,\n // concludes the address it built was right, and the bug ships.\n if (segments.some(s => s === \"undefined\")) return null;\n // Need at least 3 segments for a subcollection path (parent/id/child)\n if (segments.length < 3) return null;\n\n // If any segment is a reserved path (e.g. \"history\"), this is not a\n // subcollection route — let it fall through to other handlers.\n if (segments.some(s => RESERVED_SEGMENTS.has(s))) return null;\n\n // Odd segment count → collection path (parent/id/child or parent/id/child/id2/grandchild)\n // Even segment count → entity path (parent/id/child/id)\n if (segments.length % 2 === 1) {\n return { collectionPath: segments.join(\"/\") };\n } else {\n const id = segments.pop()!;\n return { collectionPath: segments.join(\"/\"),\nid };\n }\n };\n\n // GET /<subcollection-path> — list or get single entity\n // Use :rest{.+} instead of * because Hono v4's wildcard doesn't\n // capture into c.req.param(\"*\") — it always returns undefined.\n this.router.get(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed) return next();\n\n const driver = this.getScopedDriver(c);\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n\n\n\n if (parsed.id === \"count\") {\n // GET /parent/:parentId/child/count — count child entities\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n\n const total = driver.count ? await driver.count({\n path: parsed.collectionPath,\n filter: queryOptions.where,\n searchString\n }) : 0;\n\n return c.json({ count: total });\n } else if (parsed.id) {\n // GET /parent/:parentId/child/:id — single entity\n const queryOptions = this.parseQuery(c.req.queries());\n const fetchService = driver.restFetchService;\n const entity = fetchService\n ? await fetchService.fetchOneForRest(parsed.collectionPath, parsed.id, queryOptions.include)\n : await driver.fetchOne({ path: parsed.collectionPath,\nid: parsed.id });\n if (!entity) throw ApiError.notFound(\"Entity not found\");\n\n return c.json(entity);\n } else {\n // GET /parent/:parentId/child — list entities.\n //\n // Same call the root list route makes. A child listing used to\n // be served by a second, thinner pipeline that accepted these\n // options and applied only `limit` — so `offset`, `orderBy` and\n // `include` were dropped without a word, and `total` counted\n // rows the filter would have excluded.\n const queryDict = c.req.queries();\n const queryOptions = this.parseQuery(queryDict);\n const searchString = Array.isArray(queryDict.searchString) ? queryDict.searchString[queryDict.searchString.length - 1] : undefined;\n const fetchService = driver.restFetchService;\n const listOptions = {\n filter: queryOptions.where,\n // Same omission the comment above describes, one parameter\n // later: parsed, then dropped, so `?or=` widened the read.\n logical: queryOptions.logical,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n orderBy: queryOptions.orderBy?.[0]?.field,\n order: queryOptions.orderBy?.[0]?.direction === \"desc\" ? \"desc\" as const : \"asc\" as const,\n searchString\n };\n const entities = fetchService\n ? await fetchService.fetchCollectionForRest(parsed.collectionPath, listOptions, queryOptions.include)\n : await driver.fetchCollection({ path: parsed.collectionPath,\n...listOptions });\n\n const total = driver.count ? await driver.count({\n path: parsed.collectionPath,\n filter: queryOptions.where,\n logical: queryOptions.logical,\n searchString\n }) : entities.length;\n\n return c.json({\n data: entities,\n meta: {\n total,\n limit: queryOptions.limit,\n offset: queryOptions.offset,\n hasMore: (queryOptions.offset || 0) + entities.length < total\n }\n });\n }\n });\n\n // POST /<subcollection-path> — create entity\n this.router.post(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed || parsed.id) return next();\n\n const driver = this.getScopedDriver(c);\n\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n const body = await parseJsonBody(c);\n\n const targetCollection = this.resolveNestedWriteCollection(parsed.collectionPath);\n if (targetCollection) assertKnownWriteFields(body, targetCollection);\n\n const entity = await driver.save({\n path: parsed.collectionPath,\n values: body,\n status: \"new\"\n });\n\n const response = this.formatResponse(entity);\n\n\n\n return c.json(response, 201);\n });\n\n // PUT /<subcollection-path>/:id — update entity\n this.router.put(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed || !parsed.id) return next();\n\n const driver = this.getScopedDriver(c);\n\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n\n const body = await parseJsonBody(c);\n\n const targetCollection = this.resolveNestedWriteCollection(parsed.collectionPath);\n if (targetCollection) assertKnownWriteFields(body, targetCollection);\n\n const entity = await driver.save({\n path: parsed.collectionPath,\n id: parsed.id,\n values: body,\n status: \"existing\"\n });\n\n const response = this.formatResponse(entity);\n\n\n\n return c.json(response);\n });\n\n // DELETE /<subcollection-path>/:id — delete entity\n this.router.delete(\"/:parent/:parentId/:rest{.+}\", async (c, next) => {\n const rest = c.req.param(\"rest\");\n if (!rest || rest === \"undefined\") return next();\n const rawPath = `${c.req.param(\"parent\")}/${c.req.param(\"parentId\")}/${rest}`;\n const parsed = parseSubPath(rawPath);\n if (!parsed || !parsed.id) return next();\n\n const driver = this.getScopedDriver(c);\n\n\n this.enforceSubcollectionApiKeyPermission(c, parsed.collectionPath);\n\n const existingEntity = await driver.fetchOne({\n path: parsed.collectionPath,\n id: parsed.id\n });\n\n if (!existingEntity) throw ApiError.notFound(\"Entity not found\");\n\n await driver.delete({\n row: {\n // The address from the path, for the same reason as the\n // collection-level delete above: a row carries no id.\n id: parsed.id,\n path: parsed.collectionPath,\n values: existingEntity\n }\n });\n\n\n\n return new Response(null, { status: 204 });\n });\n }\n\n /**\n * Format successful API response\n */\n private formatResponse<T>(data: T, meta?: Record<string, unknown>): unknown {\n if (meta) {\n return {\n data,\n meta\n };\n }\n return data;\n }\n\n\n\n /**\n * Fetch raw collection data without Entity wrapper (fallback for non-Postgres)\n */\n private async fetchRawCollection(driver: DataDriver, collection: CollectionConfig, queryOptions: QueryOptions, searchString?: string) {\n const entities = await driver.fetchCollection({\n path: getCollectionDataPath(collection),\n collection,\n filter: queryOptions.where,\n // The fallback every driver without a `restFetchService` uses —\n // mongo, firebase, anything a developer registers. It dropped the\n // group exactly as the Postgres path did.\n logical: queryOptions.logical,\n limit: queryOptions.limit,\n orderBy: queryOptions.orderBy?.[0]?.field,\n order: queryOptions.orderBy?.[0]?.direction === \"desc\" ? \"desc\" : \"asc\",\n startAfter: queryOptions.offset ? String(queryOptions.offset) : undefined,\n searchString,\n vectorSearch: queryOptions.vectorSearch\n });\n\n return entities;\n }\n\n /**\n * Count raw entities for a collection\n */\n private async countRawEntities(driver: DataDriver, collection: CollectionConfig, queryOptions: QueryOptions, searchString?: string): Promise<number> {\n return driver.count ? await driver.count({\n path: getCollectionDataPath(collection),\n collection,\n filter: queryOptions.where,\n // Counted as well as fetched, or `total` describes a different set\n // of rows from the one that was served.\n logical: queryOptions.logical,\n searchString\n }) : 0;\n }\n\n /**\n * Fetch single entity raw data without Entity wrapper (fallback)\n */\n private async fetchRawEntity(driver: DataDriver, collection: CollectionConfig, id: string) {\n const entity = await driver.fetchOne({\n path: getCollectionDataPath(collection),\n id,\n collection\n });\n\n return entity ?? null;\n }\n\n\n}\n","// Zod 3 compat layer\nimport * as core from \"../core/index.js\";\n/** @deprecated Use the raw string literal codes instead, e.g. \"invalid_type\". */\nexport const ZodIssueCode = {\n invalid_type: \"invalid_type\",\n too_big: \"too_big\",\n too_small: \"too_small\",\n invalid_format: \"invalid_format\",\n not_multiple_of: \"not_multiple_of\",\n unrecognized_keys: \"unrecognized_keys\",\n invalid_union: \"invalid_union\",\n invalid_key: \"invalid_key\",\n invalid_element: \"invalid_element\",\n invalid_value: \"invalid_value\",\n custom: \"custom\",\n};\nexport { $brand, config } from \"../core/index.js\";\n/** @deprecated Use `z.config(params)` instead. */\nexport function setErrorMap(map) {\n core.config({\n customError: map,\n });\n}\n/** @deprecated Use `z.config()` instead. */\nexport function getErrorMap() {\n return core.config().customError;\n}\n/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */\nexport var ZodFirstPartyTypeKind;\n(function (ZodFirstPartyTypeKind) {\n})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));\n","import * as core from \"../core/index.js\";\nimport * as schemas from \"./schemas.js\";\nexport function string(params) {\n return core._coercedString(schemas.ZodString, params);\n}\nexport function number(params) {\n return core._coercedNumber(schemas.ZodNumber, params);\n}\nexport function boolean(params) {\n return core._coercedBoolean(schemas.ZodBoolean, params);\n}\nexport function bigint(params) {\n return core._coercedBigint(schemas.ZodBigInt, params);\n}\nexport function date(params) {\n return core._coercedDate(schemas.ZodDate, params);\n}\n","/**\n * Configure console log levels based on environment variable\n * Call this early in your application to set up proper logging levels\n */\nexport function configureLogLevel(logLevel?: string) {\n const LOG_LEVEL = logLevel || process.env.LOG_LEVEL || \"info\";\n const logLevels = { error: 0,\nwarn: 1,\ninfo: 2,\ndebug: 3 };\n const currentLevel = logLevels[LOG_LEVEL as keyof typeof logLevels] ?? 2;\n\n if (currentLevel < 3) console.debug = () => { };\n if (currentLevel < 2) console.log = () => { };\n if (currentLevel < 1) console.warn = () => { };\n if (currentLevel < 0) console.error = () => { };\n}\n","import type { MiddlewareHandler } from \"hono\";\nimport { compress } from \"hono/compress\";\n\n/**\n * Response compression (gzip/deflate), negotiated from `Accept-Encoding`.\n *\n * Wraps Hono's `compress` with two corrections it does not make itself:\n *\n * - **`Vary: Accept-Encoding`** on every response it guards. Without it a shared\n * cache may hand a gzipped body to a client that asked for identity.\n * - **Range responses are left alone.** `Content-Range` describes offsets into\n * the identity body, so compressing a 206 desyncs the framing from the bytes\n * actually sent.\n *\n * No brotli: `CompressionStream` has no \"br\", so a br-only client would fall\n * back to identity — every real client sends gzip too.\n */\nexport function responseCompression(): MiddlewareHandler {\n const gzip = compress();\n\n return async (c, next) => {\n await next();\n\n const vary = c.res.headers.get(\"Vary\");\n if (!vary) {\n c.res.headers.set(\"Vary\", \"Accept-Encoding\");\n } else if (!/\\baccept-encoding\\b/i.test(vary)) {\n c.res.headers.append(\"Vary\", \"Accept-Encoding\");\n }\n\n if (c.res.status === 206 || c.res.headers.has(\"Content-Range\")) {\n return;\n }\n\n // The response is already built, so `compress` only needs to inspect and\n // re-wrap it — hence the no-op continuation.\n await gzip(c, async () => { /* already resolved */ });\n };\n}\n","/**\n * X-Request-ID Middleware for Hono.\n *\n * Generates a unique request identifier (UUID v4) for every inbound\n * request, or propagates an existing `X-Request-ID` header from the\n * caller. The ID is:\n *\n * 1. Stored in the Hono context (`c.get(\"requestId\")`)\n * 2. Echoed back on the response as `X-Request-ID`\n *\n * Downstream middleware and handlers (request logger, error handler,\n * etc.) read the ID from context to include it in log entries and\n * error responses, enabling end-to-end request tracing across services.\n *\n * @example\n * ```ts\n * import { requestId } from \"@rebasepro/server\";\n * app.use(\"/*\", requestId());\n * ```\n */\nimport { randomUUID } from \"node:crypto\";\nimport type { MiddlewareHandler } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\n\nexport const REQUEST_ID_HEADER = \"X-Request-ID\";\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function requestId(): MiddlewareHandler<HonoEnv> {\n return async (c, next) => {\n const incoming = c.req.header(REQUEST_ID_HEADER);\n const id = incoming && UUID_RE.test(incoming) ? incoming : randomUUID();\n\n c.set(\"requestId\", id);\n\n await next();\n\n c.header(REQUEST_ID_HEADER, id);\n };\n}\n","/**\n * Structured HTTP request logging middleware for Hono.\n *\n * Logs every request with method, path, status code, latency, and\n * content-length. In production, outputs JSON for Cloud Logging; in\n * development, emits a coloured one-liner.\n *\n * @example\n * ```ts\n * import { requestLogger } from \"@rebasepro/server\";\n * app.use(\"/*\", requestLogger());\n * ```\n */\nimport type { MiddlewareHandler } from \"hono\";\nimport { logger as log } from \"./logger\";\n\nexport interface RequestLoggerOptions {\n /** Paths to skip logging (e.g. \"/health\"). Supports exact match. */\n skip?: string[];\n}\n\nexport function requestLogger(options?: RequestLoggerOptions): MiddlewareHandler {\n const skipPaths = new Set(options?.skip ?? [\"/health\", \"/favicon.ico\"]);\n\n return async (c, next) => {\n const start = performance.now();\n const method = c.req.method;\n const path = c.req.path;\n\n // Skip noisy endpoints\n if (skipPaths.has(path)) {\n return next();\n }\n\n await next();\n\n const latencyMs = Math.round(performance.now() - start);\n const status = c.res.status;\n const contentLength = c.res.headers.get(\"content-length\");\n\n const data: Record<string, unknown> = {\n method,\n path,\n status,\n latencyMs\n };\n\n // Include request correlation ID if available\n const reqId = c.get(\"requestId\");\n if (reqId) {\n data.requestId = reqId;\n }\n\n if (contentLength) {\n data.contentLength = parseInt(contentLength, 10);\n }\n\n // Extract the user id from context if auth middleware ran.\n //\n // This read `c.get(\"uid\")` — a context key nothing has ever set, so\n // no request log has ever carried a user. The auth middlewares all set\n // `user`; the id lives on it.\n const uid = (c.get(\"user\") as { uid?: string } | undefined)?.uid;\n if (uid) {\n data.uid = uid;\n }\n\n if (status >= 500) {\n log.error(\"request\", data);\n } else if (status >= 400) {\n log.warn(\"request\", data);\n } else {\n log.info(\"request\", data);\n }\n };\n}\n","import { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { csrf } from \"hono/csrf\";\nimport { HonoEnv } from \"../api/types\";\nimport { responseCompression } from \"../utils/compression\";\nimport { requestId } from \"../utils/request-id\";\nimport { requestLogger } from \"../utils/request-logger\";\nimport { logger } from \"../utils/logger\";\nimport { logMiddleware } from \"../api/logs-routes\";\n\ninterface MiddlewareConfig {\n maxBodySize?: number;\n compression?: boolean;\n /**\n * The caller already installed a CORS middleware.\n *\n * The framework does not install one itself, so it warns when it sees no\n * sign of an origin policy. The bundle runtime always installs one, and a\n * warning that is wrong in the common case is worse than no warning — it\n * teaches people to skim past the ones that matter.\n */\n corsHandled?: boolean;\n csrf?: {\n origin: string | string[] | ((origin: string) => boolean);\n };\n}\n\nexport function configureMiddlewares(\n app: Hono<HonoEnv>,\n basePath: string,\n isProduction: boolean,\n config: MiddlewareConfig\n): void {\n // Request ID (correlation)\n app.use(`${basePath}/*`, requestId());\n\n // Response Compression — registered early so it wraps the final response of\n // every downstream handler, including error responses.\n //\n // Hono's `threshold` is deliberately not plumbed through: it only applies to\n // responses declaring a Content-Length, and `c.json()` sets none, so it\n // would silently do nothing on the very responses this exists to shrink.\n if (config.compression !== false) {\n app.use(`${basePath}/*`, responseCompression());\n logger.info(\"Response compression enabled\");\n }\n\n // Request Body Size Limit\n const maxBodySize = config.maxBodySize ?? 10 * 1024 * 1024; // 10MB default\n if (maxBodySize > 0) {\n app.use(`${basePath}/*`, bodyLimit({\n maxSize: maxBodySize,\n onError: (c) => {\n return c.json({\n error: {\n message: `Request body too large. Maximum size is ${Math.round(maxBodySize / 1024 / 1024)}MB.`,\n code: \"PAYLOAD_TOO_LARGE\"\n }\n }, 413);\n }\n }));\n logger.info(\"Request body limit configured\", { maxSizeMB: Math.round(maxBodySize / 1024 / 1024) });\n }\n\n // CSRF Protection (opt-in)\n if (config.csrf?.origin) {\n app.use(`${basePath}/*`, csrf({\n origin: config.csrf.origin\n }));\n logger.info(\"CSRF protection enabled\");\n }\n\n // CORS Warning. The framework does not install a CORS middleware itself —\n // that belongs to the app (the scaffolded template adds `hono/cors`). A\n // backend wired up by hand can therefore end up with no origin restriction\n // at all, which is most dangerous in production, so warn there too rather\n // than only in development.\n if (!config.corsHandled && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) {\n logger.warn(\n (isProduction ? \"[PRODUCTION] \" : \"\") +\n \"No CORS configuration detected (CORS_ORIGINS / FRONTEND_URL not set). \" +\n \"If your app does not install its own CORS middleware, the API may accept \" +\n \"requests from any origin. Set CORS_ORIGINS to restrict access.\"\n );\n }\n\n // Request Logging\n app.use(`${basePath}/*`, requestLogger());\n\n // Record requests into the in-memory ring buffer that backs the Studio's\n // Logs Explorer. This is a separate sink from `requestLogger` above, which\n // writes to stdout — both observe every request, neither duplicates the other.\n app.use(`${basePath}/*`, logMiddleware());\n}\n","/**\n * Local filesystem storage controller\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport { promisify } from \"util\";\nimport {\n StorageController,\n LocalStorageConfig,\n DEFAULT_MAX_FILE_SIZE\n} from \"./types\";\nimport {\n UploadFileProps,\n UploadFileResult,\n DownloadConfig,\n DownloadMetadata,\n StorageListResult,\n StorageReference\n} from \"@rebasepro/types\";\n\nconst mkdir = promisify(fs.mkdir);\nconst writeFile = promisify(fs.writeFile);\nconst readFile = promisify(fs.readFile);\nconst unlink = promisify(fs.unlink);\nconst readdir = promisify(fs.readdir);\nconst stat = promisify(fs.stat);\nconst access = promisify(fs.access);\n\n/**\n * Bucket used when a call names none.\n *\n * Every method resolves through this, so put/get/delete/list agree on where a\n * bare key lives.\n */\nexport const DEFAULT_BUCKET = \"default\";\n\n/**\n * Remove initial and trailing slashes from a path.\n * Handles paths like \"/images/\", \"images/\", \"/images\" → \"images\"\n */\nfunction normalizeStoragePath(s: string): string {\n let result = s;\n while (result.startsWith(\"/\")) {\n result = result.slice(1);\n }\n while (result.endsWith(\"/\")) {\n result = result.slice(0, -1);\n }\n return result;\n}\n\n/**\n * Local filesystem storage implementation\n * Stores files in a directory structure: {basePath}/{bucket}/{path}\n */\nexport class LocalStorageController implements StorageController {\n private config: LocalStorageConfig;\n private basePath: string;\n\n constructor(config: LocalStorageConfig) {\n this.config = config;\n this.basePath = path.resolve(config.basePath);\n }\n\n getType(): \"local\" {\n return \"local\";\n }\n\n /**\n * Ensure directory exists, creating it if necessary\n */\n private async ensureDir(dirPath: string): Promise<void> {\n try {\n await mkdir(dirPath, { recursive: true });\n } catch (error: unknown) {\n if (error instanceof Error && (error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n }\n }\n\n /**\n * Get the full filesystem path for a storage path, with a traversal guard\n * that keeps the result inside the bucket directory.\n *\n * Defaults the bucket the way `putObject` does.\n *\n * `putObject` has always written into `default` when given no bucket, while\n * the read side resolved a bare key against the storage root — where\n * nothing is. The two disagreed silently: `getObject` returned null (reads\n * as \"file missing\"), `deleteObject` deleted nothing (404s are swallowed by\n * design), and `listObjects` returned an empty page. So the obvious\n * `putObject({ key })` → `getObject(key)` did not round-trip and nothing\n * said why. One default, applied everywhere, removes the whole class.\n */\n private getFullPath(storagePath: string, bucket?: string): string {\n const bucketPath = path.join(this.basePath, bucket ?? DEFAULT_BUCKET);\n const resolved = path.resolve(path.join(bucketPath, storagePath));\n if (!resolved.startsWith(bucketPath + path.sep) && resolved !== bucketPath) {\n throw new Error(\"Path traversal detected: resolved storage path is outside the bucket directory.\");\n }\n return resolved;\n }\n\n /**\n * Validate file before upload\n */\n private validateFile(file: File): void {\n const maxSize = this.config.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;\n if (file.size > maxSize) {\n throw new Error(`File size ${file.size} exceeds maximum allowed size ${maxSize}`);\n }\n\n if (this.config.allowedMimeTypes && this.config.allowedMimeTypes.length > 0) {\n if (!this.config.allowedMimeTypes.includes(file.type)) {\n throw new Error(`File type ${file.type} is not allowed. Allowed types: ${this.config.allowedMimeTypes.join(\", \")}`);\n }\n }\n }\n\n async putObject({\n file,\n key,\n metadata,\n bucket\n }: UploadFileProps): Promise<UploadFileResult> {\n this.validateFile(file);\n\n // Always use a bucket (default to 'default')\n const usedBucket = bucket ?? DEFAULT_BUCKET;\n const fullStoragePath = key;\n const fullPath = this.getFullPath(fullStoragePath, usedBucket);\n\n // Ensure parent directory exists\n await this.ensureDir(path.dirname(fullPath));\n\n // Convert File to Buffer and write\n const arrayBuffer = await file.arrayBuffer();\n const buffer = Buffer.from(arrayBuffer);\n await writeFile(fullPath, buffer);\n\n // Always save metadata file with at least contentType (required for preview)\n const metadataPath = `${fullPath}.metadata.json`;\n await writeFile(metadataPath, JSON.stringify({\n ...(metadata || {}),\n contentType: file.type,\n size: file.size,\n uploadedAt: new Date().toISOString()\n }, null, 2));\n\n return {\n key: fullStoragePath,\n bucket: usedBucket,\n storageUrl: `local://${usedBucket}/${fullStoragePath}`\n };\n }\n\n async getSignedUrl(key: string, bucket?: string): Promise<DownloadConfig> {\n // Handle local:// URLs\n let resolvedPath = key;\n let resolvedBucket = bucket;\n\n if (key.startsWith(\"local://\")) {\n const withoutProtocol = key.substring(\"local://\".length);\n const firstSlash = withoutProtocol.indexOf(\"/\");\n if (firstSlash > 0) {\n resolvedBucket = withoutProtocol.substring(0, firstSlash);\n resolvedPath = withoutProtocol.substring(firstSlash + 1);\n }\n }\n\n // Normalize path to handle leading/trailing slashes\n resolvedPath = normalizeStoragePath(resolvedPath);\n const fullPath = this.getFullPath(resolvedPath, resolvedBucket);\n\n try {\n await access(fullPath, fs.constants.R_OK);\n } catch {\n return {\n url: null,\n fileNotFound: true\n };\n }\n\n // Read metadata if available\n let metadata: DownloadMetadata | undefined;\n const metadataPath = `${fullPath}.metadata.json`;\n try {\n const metadataContent = await readFile(metadataPath, \"utf-8\");\n const savedMetadata = JSON.parse(metadataContent);\n const fileStat = await stat(fullPath);\n\n metadata = {\n bucket: resolvedBucket ?? DEFAULT_BUCKET,\n fullPath: resolvedPath,\n name: path.basename(resolvedPath),\n size: fileStat.size,\n contentType: savedMetadata.contentType || \"application/octet-stream\",\n customMetadata: savedMetadata\n };\n } catch {\n // No metadata file, create basic metadata from stat\n try {\n const fileStat = await stat(fullPath);\n metadata = {\n bucket: resolvedBucket ?? DEFAULT_BUCKET,\n fullPath: resolvedPath,\n name: path.basename(resolvedPath),\n size: fileStat.size,\n contentType: \"application/octet-stream\",\n customMetadata: {}\n };\n } catch {\n // Stat failed\n }\n }\n\n // Return a relative URL that will be served by the storage routes\n const bucketPath = resolvedBucket ? `${resolvedBucket}/` : \"\";\n const url = `/api/storage/file/${bucketPath}${resolvedPath}`;\n\n return {\n url,\n metadata\n };\n }\n\n async getObject(key: string, bucket?: string): Promise<File | null> {\n // Handle local:// URLs\n let resolvedPath = key;\n let resolvedBucket = bucket;\n\n if (key.startsWith(\"local://\")) {\n const withoutProtocol = key.substring(\"local://\".length);\n const firstSlash = withoutProtocol.indexOf(\"/\");\n if (firstSlash > 0) {\n resolvedBucket = withoutProtocol.substring(0, firstSlash);\n resolvedPath = withoutProtocol.substring(firstSlash + 1);\n }\n }\n\n // Normalize path to handle leading/trailing slashes\n resolvedPath = normalizeStoragePath(resolvedPath);\n const fullPath = this.getFullPath(resolvedPath, resolvedBucket);\n\n try {\n await access(fullPath, fs.constants.R_OK);\n const buffer = await readFile(fullPath);\n\n // Try to get content type from metadata\n let contentType = \"application/octet-stream\";\n try {\n const metadataPath = `${fullPath}.metadata.json`;\n const metadataContent = await readFile(metadataPath, \"utf-8\");\n const metadata = JSON.parse(metadataContent);\n contentType = metadata.contentType || contentType;\n } catch {\n // No metadata, use default content type\n }\n\n const blob = new Blob([buffer], { type: contentType });\n return new File([blob], path.basename(resolvedPath), { type: contentType });\n } catch {\n return null;\n }\n }\n\n async deleteObject(key: string, bucket?: string): Promise<void> {\n // Handle local:// URLs\n let resolvedPath = key;\n let resolvedBucket = bucket;\n\n if (key.startsWith(\"local://\")) {\n const withoutProtocol = key.substring(\"local://\".length);\n const firstSlash = withoutProtocol.indexOf(\"/\");\n if (firstSlash > 0) {\n resolvedBucket = withoutProtocol.substring(0, firstSlash);\n resolvedPath = withoutProtocol.substring(firstSlash + 1);\n }\n }\n\n // Normalize path to handle leading/trailing slashes\n resolvedPath = normalizeStoragePath(resolvedPath);\n\n if (!resolvedPath) {\n // Safety: never delete the bucket root\n return;\n }\n\n const fullPath = this.getFullPath(resolvedPath, resolvedBucket);\n\n // Check if path exists before attempting to delete\n try {\n await access(fullPath, fs.constants.F_OK);\n } catch {\n // File doesn't exist — nothing to delete\n return;\n }\n\n try {\n const stats = await stat(fullPath);\n if (stats.isDirectory()) {\n // Only remove if empty — client must delete contents first\n await fs.promises.rmdir(fullPath);\n } else {\n await unlink(fullPath);\n // Also delete metadata file if exists\n try {\n await unlink(`${fullPath}.metadata.json`);\n } catch {\n // Metadata file might not exist\n }\n }\n } catch (error: unknown) {\n if (error instanceof Error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\" || code === \"ENOTEMPTY\") {\n // File doesn't exist or directory not empty — ignore\n return;\n }\n }\n throw error;\n }\n }\n\n async listObjects(prefix: string, options?: {\n bucket?: string;\n maxResults?: number;\n pageToken?: string;\n }): Promise<StorageListResult> {\n // Normalize path to handle leading/trailing slashes\n const normalizedPath = normalizeStoragePath(prefix);\n const fullPath = this.getFullPath(normalizedPath, options?.bucket);\n const items: StorageReference[] = [];\n const prefixes: StorageReference[] = [];\n\n try {\n await access(fullPath, fs.constants.R_OK);\n const entries = await readdir(fullPath, { withFileTypes: true });\n\n let count = 0;\n const maxResults = options?.maxResults ?? 1000;\n const startIndex = options?.pageToken ? parseInt(options.pageToken, 10) : 0;\n // Cursor over `entries`, not over emitted results. Every stored\n // object has a `.metadata.json` sidecar that is skipped without\n // emitting anything, so a token derived from `count` could fail to\n // advance — a page of nothing but sidecars handed back the token it\n // was called with, and `while (pageToken)` never terminated.\n let scanned = startIndex;\n\n for (let i = startIndex; i < entries.length && count < maxResults; i++) {\n const entry = entries[i];\n scanned = i + 1;\n\n // Skip metadata files\n if (entry.name.endsWith(\".metadata.json\")) {\n continue;\n }\n\n const entryPath = prefix ? `${prefix}/${entry.name}` : entry.name;\n const bucket = options?.bucket ?? DEFAULT_BUCKET;\n\n const ref: StorageReference = {\n bucket,\n fullPath: entryPath,\n name: entry.name,\n parent: null as never, // Simplified - not fully implementing parent chain\n root: null as never,\n toString: () => `local://${bucket}/${entryPath}`\n };\n\n if (entry.isDirectory()) {\n prefixes.push(ref);\n } else {\n items.push(ref);\n }\n count++;\n }\n\n const nextPageToken = scanned < entries.length ? String(scanned) : undefined;\n\n return {\n items,\n prefixes,\n nextPageToken\n };\n } catch (error: unknown) {\n const code = (error as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { items: [],\nprefixes: [] };\n }\n throw error;\n }\n }\n\n /**\n * Get the absolute filesystem path for serving files\n * Used by the storage routes to serve files directly\n */\n getAbsolutePath(key: string, bucket?: string): string {\n return this.getFullPath(key, bucket);\n }\n\n /**\n * Get the base path for the storage\n */\n getBasePath(): string {\n return this.basePath;\n }\n}\n","/**\n * Image Transformation Service\n *\n * Provides on-the-fly image resize, crop, format conversion, and quality\n * adjustment using the `sharp` library. Results are cached in an LRU\n * in-memory cache to avoid redundant processing.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet sharpFactory: ((input: Buffer | Uint8Array) => any) | undefined;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function getSharp(): Promise<(input: Buffer | Uint8Array) => any> {\n if (!sharpFactory) {\n try {\n const mod = await import(\"sharp\");\n sharpFactory = mod.default;\n } catch (err) {\n throw new Error(\"Failed to load optional 'sharp' dependency for image transformation.\");\n }\n }\n if (!sharpFactory) {\n throw new Error(\"Failed to load optional 'sharp' dependency for image transformation.\");\n }\n return sharpFactory;\n}\n\n/** Options that can be specified via query parameters. */\nexport interface ImageTransformOptions {\n width?: number;\n height?: number;\n quality?: number;\n format?: \"webp\" | \"avif\" | \"jpeg\" | \"png\";\n fit?: \"cover\" | \"contain\" | \"fill\" | \"inside\" | \"outside\";\n}\n\n/** Maximum dimension allowed (prevents abuse). */\nconst MAX_DIMENSION = 4096;\n/** Maximum quality value. */\nconst MAX_QUALITY = 100;\n/** Minimum quality value. */\nconst MIN_QUALITY = 1;\n\nconst VALID_FORMATS = new Set([\"webp\", \"avif\", \"jpeg\", \"png\"]);\nconst VALID_FITS = new Set([\"cover\", \"contain\", \"fill\", \"inside\", \"outside\"]);\n\n/**\n * Parse transform options from URL query parameters.\n * Returns `null` when no transformation is requested.\n */\nexport function parseTransformOptions(query: Record<string, string>): ImageTransformOptions | null {\n const opts: ImageTransformOptions = {};\n let hasTransform = false;\n\n if (query.width) {\n const w = parseInt(query.width, 10);\n if (!Number.isNaN(w) && w > 0) {\n opts.width = Math.min(w, MAX_DIMENSION);\n hasTransform = true;\n }\n }\n\n if (query.height) {\n const h = parseInt(query.height, 10);\n if (!Number.isNaN(h) && h > 0) {\n opts.height = Math.min(h, MAX_DIMENSION);\n hasTransform = true;\n }\n }\n\n if (query.quality) {\n const q = parseInt(query.quality, 10);\n if (!Number.isNaN(q)) {\n opts.quality = Math.min(Math.max(q, MIN_QUALITY), MAX_QUALITY);\n hasTransform = true;\n }\n }\n\n if (query.format && VALID_FORMATS.has(query.format)) {\n opts.format = query.format as ImageTransformOptions[\"format\"];\n hasTransform = true;\n }\n\n if (query.fit && VALID_FITS.has(query.fit)) {\n opts.fit = query.fit as ImageTransformOptions[\"fit\"];\n hasTransform = true;\n }\n\n return hasTransform ? opts : null;\n}\n\n/** MIME types that can be used as a Content-Type header. */\nconst FORMAT_CONTENT_TYPES: Record<string, string> = {\n webp: \"image/webp\",\n avif: \"image/avif\",\n jpeg: \"image/jpeg\",\n png: \"image/png\"\n};\n\n/** Check whether a content type is a transformable image. */\nexport function isTransformableImage(contentType: string): boolean {\n return (\n contentType.startsWith(\"image/\") &&\n !contentType.includes(\"svg\") &&\n !contentType.includes(\"gif\")\n );\n}\n\n/**\n * Apply image transformations and return the result buffer + content type.\n */\nexport async function transformImage(\n buffer: Buffer | Uint8Array,\n options: ImageTransformOptions\n): Promise<{ data: Buffer; contentType: string }> {\n const sharp = await getSharp();\n let pipeline = sharp(buffer);\n\n if (options.width || options.height) {\n pipeline = pipeline.resize({\n width: options.width,\n height: options.height,\n fit: options.fit || \"cover\",\n withoutEnlargement: true\n });\n }\n\n const format = options.format || \"webp\";\n const quality = options.quality || 80;\n\n switch (format) {\n case \"webp\":\n pipeline = pipeline.webp({ quality });\n break;\n case \"avif\":\n pipeline = pipeline.avif({ quality });\n break;\n case \"jpeg\":\n pipeline = pipeline.jpeg({ quality });\n break;\n case \"png\":\n pipeline = pipeline.png({ quality });\n break;\n }\n\n const data = await pipeline.toBuffer();\n return { data,\ncontentType: FORMAT_CONTENT_TYPES[format] };\n}\n\n// ---------------------------------------------------------------------------\n// LRU Transform Cache\n// ---------------------------------------------------------------------------\n\ninterface CacheEntry {\n data: Buffer;\n contentType: string;\n timestamp: number;\n}\n\n/**\n * Simple LRU cache for transformed images.\n *\n * Entries expire after `maxAgeMs` (default: 1 hour) and the cache\n * evicts the oldest entry when `maxEntries` is exceeded.\n */\nexport class TransformCache {\n private cache = new Map<string, CacheEntry>();\n private readonly maxEntries: number;\n private readonly maxAgeMs: number;\n private readonly maxTotalBytes: number;\n private totalBytes = 0;\n\n constructor(maxEntries = 500, maxAgeMs = 3_600_000, maxTotalBytes = 256 * 1024 * 1024) {\n this.maxEntries = maxEntries;\n this.maxAgeMs = maxAgeMs;\n this.maxTotalBytes = maxTotalBytes;\n }\n\n /** Build a deterministic cache key from file key + transform options. */\n buildKey(fileKey: string, options: ImageTransformOptions): string {\n return `${fileKey}::${JSON.stringify(options)}`;\n }\n\n get(cacheKey: string): { data: Buffer; contentType: string } | null {\n const entry = this.cache.get(cacheKey);\n if (!entry) return null;\n if (Date.now() - entry.timestamp > this.maxAgeMs) {\n this.totalBytes -= entry.data.length;\n this.cache.delete(cacheKey);\n return null;\n }\n // Move to end (most recently used)\n this.cache.delete(cacheKey);\n this.cache.set(cacheKey, entry);\n return { data: entry.data,\ncontentType: entry.contentType };\n }\n\n set(cacheKey: string, data: Buffer, contentType: string): void {\n // Evict oldest entries while over capacity (entry count or total bytes)\n while (\n (this.cache.size >= this.maxEntries || this.totalBytes + data.length > this.maxTotalBytes)\n && this.cache.size > 0\n ) {\n const oldest = this.cache.keys().next().value;\n if (oldest !== undefined) {\n const evicted = this.cache.get(oldest);\n if (evicted) this.totalBytes -= evicted.data.length;\n this.cache.delete(oldest);\n }\n }\n this.totalBytes += data.length;\n this.cache.set(cacheKey, { data,\ncontentType,\ntimestamp: Date.now() });\n }\n}\n","/**\n * TUS Protocol Handler\n *\n * Implements the TUS v1.0.0 resumable upload protocol with the\n * Creation and Termination extensions. Uploads are stored in a\n * temporary directory and moved to final storage on completion.\n *\n * @see https://tus.io/protocols/resumable-upload\n */\n\nimport { randomUUID } from \"crypto\";\nimport { writeFile, unlink, stat, mkdir, open } from \"fs/promises\";\nimport { existsSync } from \"fs\";\nimport { join } from \"path\";\nimport type { Context } from \"hono\";\nimport type { StorageController } from \"./types\";\nimport type { StorageRegistry } from \"./storage-registry\";\nimport { logger } from \"../utils/logger.js\";\nimport { ApiError } from \"../api/errors\";\n\n/** Metadata for an in-progress resumable upload. */\ninterface TusUpload {\n id: string;\n /** Total declared size in bytes. */\n size: number;\n /** Bytes received so far. */\n offset: number;\n /** TUS metadata parsed from the creation request. */\n metadata: Record<string, string>;\n /** Timestamp of creation (epoch ms). */\n createdAt: number;\n /** Absolute path to the temp file on disk. */\n filePath: string;\n /** Target bucket (from metadata). */\n bucket?: string;\n /** Target key / filename (from metadata). */\n key?: string;\n /** Whether the upload has been fully received and finalized. */\n completed: boolean;\n}\n\n/** Maximum upload size: 5 GB. */\nconst MAX_UPLOAD_SIZE = 5 * 1024 * 1024 * 1024;\n\n/** Stale upload expiry: 24 hours. */\nconst UPLOAD_EXPIRY_MS = 24 * 60 * 60 * 1000;\n\n/**\n * TUS resumable upload handler.\n *\n * Each instance manages uploads for a single storage root. The\n * `storageController` is used to finalize completed uploads by\n * calling `putObject`.\n */\nexport class TusHandler {\n private uploads = new Map<string, TusUpload>();\n private tusDir: string;\n private cleanupTimer?: ReturnType<typeof setInterval>;\n\n constructor(\n storageBaseDir: string,\n private storageController?: StorageController,\n private storageRegistry?: StorageRegistry,\n /**\n * Per-object authorization, applied to the resumable path too.\n *\n * TUS is a second way to write an object, so a hook enforced only on\n * `POST /upload` would leave the door it was added to close standing\n * open. The target key lives in the `Upload-Metadata` header, which\n * only this class parses — hence the injection rather than a check in\n * the route. Rejects by throwing.\n */\n private authorizeUpload?: (c: Context, key: string, bucket: string) => Promise<void>\n ) {\n this.tusDir = join(storageBaseDir, \".tus-uploads\");\n }\n\n /** Ensure the temp directory exists. */\n private async ensureDir(): Promise<void> {\n if (!existsSync(this.tusDir)) {\n await mkdir(this.tusDir, { recursive: true });\n }\n }\n\n /** Start periodic cleanup of stale uploads. */\n startCleanup(): void {\n if (this.cleanupTimer) return;\n this.cleanupTimer = setInterval(() => {\n void this.cleanupStale();\n }, 60_000); // every minute\n }\n\n /** Remove uploads that have been idle for longer than UPLOAD_EXPIRY_MS. */\n private async cleanupStale(): Promise<void> {\n const now = Date.now();\n for (const [id, upload] of this.uploads) {\n if (now - upload.createdAt > UPLOAD_EXPIRY_MS && !upload.completed) {\n try { await unlink(upload.filePath); } catch { /* ok */ }\n this.uploads.delete(id);\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // TUS Metadata Parsing\n // -----------------------------------------------------------------------\n\n /**\n * Parse the `Upload-Metadata` header.\n *\n * Format: `key base64value,key2 base64value2`\n */\n private parseMetadata(header: string): Record<string, string> {\n const metadata: Record<string, string> = {};\n if (!header) return metadata;\n for (const pair of header.split(\",\")) {\n const trimmed = pair.trim();\n const spaceIdx = trimmed.indexOf(\" \");\n if (spaceIdx === -1) {\n metadata[trimmed] = \"\";\n } else {\n const key = trimmed.substring(0, spaceIdx);\n const value = Buffer.from(trimmed.substring(spaceIdx + 1), \"base64\").toString(\"utf-8\");\n metadata[key] = value;\n }\n }\n return metadata;\n }\n\n // -----------------------------------------------------------------------\n // Protocol Endpoints\n // -----------------------------------------------------------------------\n\n /** `OPTIONS /tus` — TUS capability discovery. */\n options(): Response {\n return new Response(null, {\n status: 204,\n headers: {\n \"Tus-Resumable\": \"1.0.0\",\n \"Tus-Version\": \"1.0.0\",\n \"Tus-Extension\": \"creation,termination\",\n \"Tus-Max-Size\": String(MAX_UPLOAD_SIZE)\n }\n });\n }\n\n /** `POST /tus` — Create a new upload. */\n async create(c: Context): Promise<Response> {\n await this.ensureDir();\n\n const uploadLengthHeader = c.req.header(\"Upload-Length\");\n if (!uploadLengthHeader) {\n throw ApiError.badRequest(\"Upload-Length header is required\");\n }\n\n const uploadLength = parseInt(uploadLengthHeader, 10);\n if (Number.isNaN(uploadLength) || uploadLength <= 0) {\n throw ApiError.badRequest(\"Invalid Upload-Length\");\n }\n if (uploadLength > MAX_UPLOAD_SIZE) {\n throw new ApiError(413, \"PAYLOAD_TOO_LARGE\", `Upload-Length exceeds maximum of ${MAX_UPLOAD_SIZE} bytes`);\n }\n\n const metadata = this.parseMetadata(c.req.header(\"Upload-Metadata\") || \"\");\n\n // Gate before any temp file exists, so a denied upload leaves nothing\n // behind to resume.\n if (this.authorizeUpload) {\n const key = metadata.key || metadata.filename || \"\";\n await this.authorizeUpload(c, key, metadata.bucket || \"default\");\n }\n\n const id = randomUUID();\n const filePath = join(this.tusDir, id);\n\n // Create empty temp file\n await writeFile(filePath, Buffer.alloc(0));\n\n const upload: TusUpload = {\n id,\n size: uploadLength,\n offset: 0,\n metadata,\n createdAt: Date.now(),\n filePath,\n bucket: metadata.bucket || undefined,\n key: metadata.key || metadata.filename || undefined,\n completed: false\n };\n this.uploads.set(id, upload);\n\n // Build absolute Location\n const reqUrl = new URL(c.req.url);\n const location = `${reqUrl.origin}${reqUrl.pathname}/${id}`;\n\n return new Response(null, {\n status: 201,\n headers: {\n Location: location,\n \"Tus-Resumable\": \"1.0.0\",\n \"Upload-Offset\": \"0\"\n }\n });\n }\n\n /** `HEAD /tus/:id` — Query upload progress. */\n head(c: Context, id: string): Response {\n const upload = this.uploads.get(id);\n if (!upload) {\n throw ApiError.notFound(\"Upload not found\");\n }\n\n return new Response(null, {\n status: 200,\n headers: {\n \"Tus-Resumable\": \"1.0.0\",\n \"Upload-Offset\": String(upload.offset),\n \"Upload-Length\": String(upload.size),\n \"Cache-Control\": \"no-store\"\n }\n });\n }\n\n /** `PATCH /tus/:id` — Append data to an upload. */\n async patch(c: Context, id: string): Promise<Response> {\n const upload = this.uploads.get(id);\n if (!upload) {\n throw ApiError.notFound(\"Upload not found\");\n }\n if (upload.completed) {\n throw ApiError.badRequest(\"Upload already completed\");\n }\n\n // Validate offset\n const offsetHeader = c.req.header(\"Upload-Offset\");\n if (!offsetHeader) {\n throw ApiError.badRequest(\"Upload-Offset header is required\");\n }\n const offset = parseInt(offsetHeader, 10);\n if (offset !== upload.offset) {\n throw ApiError.conflict(\"Offset mismatch\");\n }\n\n // Validate content type\n const contentType = c.req.header(\"Content-Type\");\n if (contentType !== \"application/offset+octet-stream\") {\n throw new ApiError(415, \"UNSUPPORTED_MEDIA_TYPE\", \"Content-Type must be application/offset+octet-stream\");\n }\n\n // Read chunk and append to temp file\n const body = await c.req.arrayBuffer();\n const chunk = Buffer.from(body);\n\n // Prevent overrun\n if (upload.offset + chunk.length > upload.size) {\n throw new ApiError(413, \"PAYLOAD_TOO_LARGE\", \"Chunk exceeds declared Upload-Length\");\n }\n\n const fh = await open(upload.filePath, \"a\");\n try {\n await fh.write(chunk);\n } finally {\n await fh.close();\n }\n upload.offset += chunk.length;\n\n // Finalize if complete\n if (upload.offset >= upload.size) {\n await this.finalize(upload);\n }\n\n return new Response(null, {\n status: 204,\n headers: {\n \"Tus-Resumable\": \"1.0.0\",\n \"Upload-Offset\": String(upload.offset)\n }\n });\n }\n\n /** `DELETE /tus/:id` — Cancel and remove an upload. */\n async delete(c: Context, id: string): Promise<Response> {\n const upload = this.uploads.get(id);\n if (!upload) {\n throw ApiError.notFound(\"Upload not found\");\n }\n\n try { await unlink(upload.filePath); } catch { /* ok */ }\n this.uploads.delete(id);\n\n return new Response(null, {\n status: 204,\n headers: { \"Tus-Resumable\": \"1.0.0\" }\n });\n }\n\n // -----------------------------------------------------------------------\n // Finalization\n // -----------------------------------------------------------------------\n\n /**\n * Move a completed upload into the storage controller.\n */\n private async finalize(upload: TusUpload): Promise<void> {\n upload.completed = true;\n\n // Resolve the target controller: prefer storageId from TUS metadata,\n // then fall back to the registry default, then the single controller.\n const storageId = upload.metadata.storageId;\n let targetController = this.storageController;\n if (this.storageRegistry) {\n targetController = storageId\n ? this.storageRegistry.getOrDefault(storageId)\n : this.storageRegistry.getDefault();\n }\n\n if (!targetController) {\n // No controller — leave temp file in place\n logger.warn(\"[TUS] Upload completed but no StorageController configured. Temp file remains:\", { filePath: upload.filePath });\n return;\n }\n\n try {\n const { readFile } = await import(\"fs/promises\");\n const data = await readFile(upload.filePath);\n const fileName = upload.key || upload.metadata.filename || upload.id;\n const mimeType = upload.metadata.contentType || upload.metadata.filetype || \"application/octet-stream\";\n\n // `new Uint8Array(buffer)` rather than the Buffer directly: a Node\n // `Buffer` is typed `Buffer<ArrayBufferLike>`, and `ArrayBufferLike`\n // admits `SharedArrayBuffer`, which is not a `BlobPart`. This copies\n // into a plain ArrayBuffer, which is.\n const file = new File([new Uint8Array(data)], fileName, { type: mimeType });\n\n await targetController.putObject({\n file,\n key: fileName,\n bucket: upload.bucket\n });\n\n // Clean up temp file\n try { await unlink(upload.filePath); } catch { /* ok */ }\n this.uploads.delete(upload.id);\n\n logger.info(`[TUS] Upload ${upload.id} finalized → ${fileName}`, storageId ? { storageId } : {});\n } catch (err) {\n logger.error(`[TUS] Failed to finalize upload ${upload.id}`, { error: err });\n }\n }\n}\n","/**\n * Storage REST API routes using Hono\n *\n * Supports multi-backend routing via `StorageRegistry`. Each endpoint\n * accepts an optional `storageId` parameter (query string or form field)\n * to target a named storage backend. When omitted, the default backend\n * is used.\n */\n\nimport { Hono, type MiddlewareHandler } from \"hono\";\nimport fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport { StorageController, type StorageAuthorize, type StorageAuthorizeData, type StorageOperation } from \"./types\";\nimport { LocalStorageController } from \"./LocalStorageController\";\nimport type { StorageRegistry } from \"./storage-registry\";\nimport { DEFAULT_STORAGE_SOURCE_KEY, isPublicStoragePath, type StorageSourceDefinition, type AuthAdapter } from \"@rebasepro/types\";\nimport { requireAuth as jwtRequireAuth, optionalAuth as jwtOptionalAuth, queryTokenAuth, fileTokenAuth, publicObjectAuth } from \"../auth/middleware\";\nimport { generateDownloadToken } from \"../auth\";\nimport { ApiError, errorHandler } from \"../api/errors\";\nimport { HonoEnv } from \"../api/types\";\nimport { parseTransformOptions, transformImage, isTransformableImage, TransformCache } from \"./image-transform\";\nimport { TusHandler } from \"./tus-handler\";\n\n/** Shared image transform cache (LRU, 500 entries, 1 hour TTL). */\nconst transformCache = new TransformCache();\n\nexport interface StorageRoutesConfig {\n /**\n * Single storage controller (backward-compatible).\n * Used as fallback when no `registry` is provided.\n */\n controller?: StorageController;\n /**\n * Full storage registry for multi-backend routing.\n * When provided, endpoints resolve the controller from `storageId`\n * parameter. Takes precedence over `controller`.\n */\n registry?: StorageRegistry;\n /**\n * Declared storage sources, surfaced by `GET /sources` so the client can\n * bootstrap its registry. Carries the frontend `transport` (server vs\n * direct) and human-readable labels. Server-transport sources are also\n * derived from the registry; `direct` sources (e.g. Firebase Storage) only\n * exist here since the backend does not proxy them.\n */\n sources?: StorageSourceDefinition[];\n /** Base path for storage routes (default: '/api/storage') */\n basePath?: string;\n /** Require authentication for write operations (default: true) */\n requireAuth?: boolean;\n /** Allow unauthenticated read access to stored files (default: false).\n * When false and requireAuth is true, reads also require authentication. */\n publicRead?: boolean;\n /**\n * When provided, storage routes delegate auth to this adapter instead\n * of the built-in JWT module. This mirrors how data routes use\n * `createAdapterAuthMiddleware()` and avoids the \"JWT secret not\n * configured\" crash when `configureJwt()` was never called.\n */\n authAdapter?: AuthAdapter;\n /**\n * Per-object access control, consulted after authentication on every\n * storage route. See `StorageAuthorize`.\n *\n * Omitted, storage behaves as before: authenticated means allowed.\n */\n authorize?: StorageAuthorize;\n /**\n * Trusted data access handed to {@link authorize} on every call.\n *\n * A function rather than a value because the admin data plane is built after\n * the storage routes are mounted; by the time a request runs it is always\n * resolved.\n */\n authorizeData?: () => StorageAuthorizeData | undefined;\n}\n\n/**\n * Extract the wildcard portion of a route path from the full request path.\n *\n * Hono's `c.req.param('*')` does not work reliably in sub-routers mounted\n * via `app.route(prefix, subRouter)`. Instead we derive the wildcard value\n * from the fully-resolved `c.req.path` and `c.req.routePath`.\n *\n * For a route `/metadata/*` mounted at `/api/storage`, a request to\n * `/api/storage/metadata/default/file.jpg` yields routePath\n * `/api/storage/metadata/*`. We strip the prefix (everything before `/*`)\n * plus one character for the trailing `/` to obtain `default/file.jpg`.\n */\nexport function extractWildcardPath(c: { req: { path: string; routePath: string } }): string {\n const routePath = c.req.routePath; // e.g. \"/api/storage/metadata/*\"\n const prefix = routePath.replace(\"/*\", \"\"); // e.g. \"/api/storage/metadata\"\n const fullPath = c.req.path; // e.g. \"/api/storage/metadata/default/file.jpg\"\n const idx = fullPath.indexOf(prefix);\n if (idx < 0) return \"\";\n // +1 to skip the '/' after the prefix\n return fullPath.substring(idx + prefix.length + 1);\n}\n\n/**\n * Sanitize a user-supplied storage key to prevent path traversal and other attacks.\n * Removes null bytes, ../ sequences, leading slashes, and limits length.\n */\nfunction sanitizeStorageKey(key: string): string {\n let sanitized = key;\n // Remove null bytes\n sanitized = sanitized.replace(/\\0/g, \"\");\n // Remove ../ sequences (and ..\\ on Windows)\n sanitized = sanitized.replace(/\\.\\.\\/|\\.\\.\\\\/g, \"\");\n // Remove leading slashes\n sanitized = sanitized.replace(/^\\/+/, \"\");\n // Limit length\n sanitized = sanitized.slice(0, 1024);\n return sanitized;\n}\n\n/**\n * Build adapter-aware auth middleware for storage routes.\n *\n * When an `AuthAdapter` is provided, token verification is delegated to the\n * adapter instead of the built-in JWT module. This mirrors how data routes\n * use `createAdapterAuthMiddleware()`, but without RLS driver scoping (storage\n * routes don't interact with the DataDriver).\n *\n * Returns both a \"write\" middleware (enforces auth when `requireAuth` is true)\n * and a \"read\" middleware (enforces auth unless `publicRead` is set).\n */\nfunction buildAdapterAuthMiddleware(\n adapter: AuthAdapter,\n requireAuth: boolean,\n publicRead: boolean\n): { writeAuthMiddleware: MiddlewareHandler<HonoEnv>; readAuthMiddleware: MiddlewareHandler<HonoEnv> } {\n /**\n * Core middleware: verifies the request via the adapter. When `enforce`\n * is true, returns 401 if no authenticated user is resolved.\n */\n const createMiddleware = (enforce: boolean): MiddlewareHandler<HonoEnv> => {\n return async (c, next) => {\n let authenticatedUser = null;\n try {\n authenticatedUser = await adapter.verifyRequest(c.req.raw);\n } catch {\n return c.json({ error: { message: \"Unauthorized\", code: \"UNAUTHORIZED\" } }, 401);\n }\n\n if (authenticatedUser) {\n c.set(\"user\", {\n uid: authenticatedUser.uid,\n email: authenticatedUser.email,\n roles: authenticatedUser.roles\n });\n }\n\n // Respect a user already resolved by an upstream middleware\n // (e.g. `fileTokenAuth` for scoped `?token=` download tokens, or\n // `publicObjectAuth` for public paths). The adapter does not\n // understand these file-read tokens, so enforcing purely on\n // `authenticatedUser` would 401 an otherwise-valid file request.\n if (enforce && !authenticatedUser && !c.get(\"user\")) {\n return c.json({ error: { message: \"Unauthorized: Authentication required\", code: \"UNAUTHORIZED\" } }, 401);\n }\n\n return next();\n };\n };\n\n return {\n writeAuthMiddleware: createMiddleware(requireAuth),\n readAuthMiddleware: createMiddleware(!publicRead && requireAuth)\n };\n}\n\n/**\n * Create storage REST API routes\n */\nexport function createStorageRoutes(config: StorageRoutesConfig): Hono<HonoEnv> {\n const router = new Hono<HonoEnv>();\n router.onError(errorHandler);\n const { controller, registry, sources: declaredSources, requireAuth = true, publicRead = false, authAdapter, authorize, authorizeData } = config;\n\n /**\n * Run the per-object authorization hook, if one is configured.\n *\n * Denials are 403 rather than 404: the route already established that the\n * caller is authenticated, so hiding existence buys nothing, and a\n * distinguishable status is what makes a misconfigured policy debuggable.\n * A hook that throws denies too — an ownership lookup that fails must not\n * fall open.\n */\n const checkAuthorized = async (\n c: { get: (k: \"user\") => { uid: string; email?: string; roles?: string[] } | undefined },\n operation: StorageOperation,\n key: string,\n bucket: string,\n storageId?: string | null\n ): Promise<void> => {\n if (!authorize) return;\n\n const user = c.get(\"user\") ?? null;\n\n // A scoped download token *is* the authorization: it was minted by\n // `/metadata`, which ran this same hook, and it is valid only for the\n // path it was minted for. Re-running the hook here would ask the\n // synthetic token principal a question about ownership it cannot\n // answer, and would break every <img> the client already renders.\n // Public paths are declared public, so they are equally not the hook's\n // business.\n if (user?.uid === \"download-token\" || user?.uid === \"public\") return;\n\n let allowed: boolean;\n try {\n allowed = await authorize({\n key,\n bucket,\n operation,\n user,\n storageId: storageId ?? undefined,\n data: authorizeData?.()\n });\n } catch {\n allowed = false;\n }\n if (!allowed) {\n throw ApiError.forbidden(\"Not authorized for this object\");\n }\n };\n\n /**\n * Resolve the storage controller for a request.\n * Looks up by `storageId` in the registry, falls back to the single\n * controller, and finally to the registry default.\n */\n const resolveController = (storageId?: string | null): StorageController => {\n if (registry) {\n return registry.getOrDefault(storageId);\n }\n if (controller) {\n return controller;\n }\n throw new Error(\"No storage controller or registry available\");\n };\n\n /** Get the default controller (used for TUS and base-path derivation). */\n const getDefaultController = (): StorageController => {\n if (registry) return registry.getDefault();\n if (controller) return controller;\n throw new Error(\"No storage controller or registry available\");\n };\n\n // ── Auth middleware selection ────────────────────────────────────────\n // When an AuthAdapter is available, delegate token verification to it\n // (mirroring the data-routes pattern). This avoids calling the JWT\n // module which may not have been configured (e.g. custom auth).\n // When no adapter is present, fall back to the built-in JWT middleware.\n const { writeAuthMiddleware, readAuthMiddleware } = authAdapter\n ? buildAdapterAuthMiddleware(authAdapter, requireAuth, publicRead)\n : {\n writeAuthMiddleware: requireAuth ? jwtRequireAuth : jwtOptionalAuth,\n readAuthMiddleware: (publicRead || !requireAuth) ? jwtOptionalAuth : jwtRequireAuth\n };\n\n /**\n * Parse bucket and path from a combined file path.\n *\n * The resolved path is run through `sanitizeStorageKey` here — the same\n * function the upload route applies to incoming keys — so that read,\n * delete, metadata and folder routes strip `../`, null bytes and leading\n * slashes before the path reaches the controller, the authorize hook, or\n * the download-token it mints. The `LocalStorageController` traversal guard\n * (`getFullPath`) remains the load-bearing defence; this is the same\n * normalization on the write and read sides so a `..%2f` read/delete cannot\n * even reach it as a raw traversal string (it 404s as a normal miss instead\n * of throwing, and never leaks whether an escape was attempted).\n */\n const parseBucketAndPath = (filePath: string): { bucket: string; resolvedPath: string } => {\n const parts = filePath.split(\"/\");\n\n // Only recognize 'default' as an explicit bucket prefix\n if (parts.length > 1 && parts[0].toLowerCase() === \"default\") {\n return {\n bucket: \"default\",\n resolvedPath: sanitizeStorageKey(parts.slice(1).join(\"/\"))\n };\n }\n\n // All other paths use 'default' bucket with the full path\n return {\n bucket: \"default\",\n resolvedPath: sanitizeStorageKey(filePath)\n };\n };\n\n /**\n * POST /upload - Upload a file\n * Body: multipart/form-data with 'file' field\n * Request body can also contain metadata keys 'metadata_*'\n */\n router.post(\"/upload\", writeAuthMiddleware, async (c) => {\n const body = await c.req.parseBody();\n const uploadedFile = body[\"file\"];\n\n if (!uploadedFile || typeof uploadedFile === \"string\") {\n throw ApiError.badRequest(\"No file provided\");\n }\n\n const key = typeof body[\"key\"] === \"string\" ? body[\"key\"] : \"\";\n const bucket = typeof body[\"bucket\"] === \"string\" ? body[\"bucket\"] : undefined;\n const storageId = typeof body[\"storageId\"] === \"string\" ? body[\"storageId\"] : c.req.query(\"storageId\");\n\n const finalKey = sanitizeStorageKey(key || uploadedFile.name || \"unnamed\");\n\n // Extract custom metadata from request body\n const metadata: Record<string, unknown> = {};\n for (const [k, value] of Object.entries(body)) {\n if (k.startsWith(\"metadata_\")) {\n metadata[k.replace(\"metadata_\", \"\")] = value;\n }\n }\n\n await checkAuthorized(c, \"write\", finalKey, bucket ?? \"default\", storageId);\n\n const resolved = resolveController(storageId);\n const result = await resolved.putObject({\n file: uploadedFile,\n key: finalKey,\n metadata: Object.keys(metadata).length > 0 ? metadata : undefined,\n bucket\n });\n\n return c.json({\n success: true,\n data: result\n }, 201);\n });\n\n /**\n * GET /file/* - Download/serve a file\n * Path: /file/{bucket}/{path} or /file/{path}\n */\n router.get(\"/file/*\", fileTokenAuth, publicObjectAuth, readAuthMiddleware, async (c) => {\n // Allow cross-origin loading so admin frontends on different\n // ports (dev) or domains (CDN) can render images via <img>.\n c.header(\"Cross-Origin-Resource-Policy\", \"cross-origin\");\n\n const rawPath = extractWildcardPath(c);\n if (!rawPath) {\n throw ApiError.notFound(\"File not found\");\n }\n\n const filePath = decodeURIComponent(rawPath);\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n\n {\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n await checkAuthorized(c, \"read\", resolvedPath, bucket, storageId);\n }\n\n // Parse image transform query params (e.g. ?width=300&format=webp)\n const transformOpts = parseTransformOptions(c.req.query() as Record<string, string>);\n\n // For local storage, serve the file directly from disk\n if (resolved.getType() === \"local\") {\n const localController = resolved as LocalStorageController;\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n\n const absolutePath = localController.getAbsolutePath(resolvedPath, bucket);\n\n // Check if file exists\n try {\n await fsp.access(absolutePath);\n } catch {\n throw ApiError.notFound(\"File not found\");\n }\n\n // Get content type from metadata or infer from extension\n let contentType = \"application/octet-stream\";\n const metadataPath = `${absolutePath}.metadata.json`;\n try {\n const metadataRaw = await fsp.readFile(metadataPath, \"utf-8\");\n const metadata = JSON.parse(metadataRaw);\n contentType = metadata.contentType || contentType;\n } catch {\n // Ignore metadata errors (file may not exist)\n }\n\n const fileContent = await fsp.readFile(absolutePath);\n\n // Apply image transforms if requested and the file is a transformable image\n if (transformOpts && isTransformableImage(contentType)) {\n const cacheKey = transformCache.buildKey(filePath, transformOpts);\n let cached = transformCache.get(cacheKey);\n if (!cached) {\n cached = await transformImage(Buffer.from(fileContent), transformOpts);\n transformCache.set(cacheKey, cached.data, cached.contentType);\n }\n c.header(\"Content-Type\", cached.contentType);\n c.header(\"Cache-Control\", \"public, max-age=31536000, immutable\");\n return c.body(new Uint8Array(cached.data));\n }\n\n c.header(\"Content-Type\", contentType);\n return c.body(new Uint8Array(fileContent));\n }\n\n // For remote storage (S3, GCS, etc.), proxy the file through the backend.\n // We avoid redirecting to signed URLs because:\n // 1. Mixed-content (HTTPS page → HTTP MinIO) is blocked by browsers\n // 2. Internal IPs / VPC endpoints are unreachable from the browser\n const { bucket: parsedBucket, resolvedPath: parsedPath } = parseBucketAndPath(filePath);\n const fileObject = await resolved.getObject(parsedPath, parsedBucket);\n if (!fileObject) {\n throw ApiError.notFound(\"File not found\");\n }\n\n const remoteContentType = fileObject.type || \"application/octet-stream\";\n\n // Apply image transforms for remote storage too\n if (transformOpts && isTransformableImage(remoteContentType)) {\n const cacheKey = transformCache.buildKey(filePath, transformOpts);\n let cached = transformCache.get(cacheKey);\n if (!cached) {\n const buf = Buffer.from(await fileObject.arrayBuffer());\n cached = await transformImage(buf, transformOpts);\n transformCache.set(cacheKey, cached.data, cached.contentType);\n }\n c.header(\"Content-Type\", cached.contentType);\n c.header(\"Cache-Control\", \"public, max-age=31536000, immutable\");\n return c.body(new Uint8Array(cached.data));\n }\n\n c.header(\"Content-Type\", remoteContentType);\n c.header(\"Cache-Control\", \"public, max-age=3600, immutable\");\n const buf = await fileObject.arrayBuffer();\n return c.body(new Uint8Array(buf));\n });\n\n /**\n * GET /metadata/* - Get file metadata\n */\n router.get(\"/metadata/*\", fileTokenAuth, publicObjectAuth, readAuthMiddleware, async (c) => {\n const rawPath = extractWildcardPath(c);\n if (!rawPath) {\n return c.json({\n success: true,\n data: null,\n fileNotFound: true\n }, 404);\n }\n\n const filePath = decodeURIComponent(rawPath);\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n\n // The load-bearing check. This route mints the short-lived path-scoped\n // download token that `/file/*` then trusts, and it used to mint one\n // for any authenticated caller for any path — which is exactly why\n // \"reject full-access JWTs on file routes\" did not close the gap.\n await checkAuthorized(c, \"read\", resolvedPath, bucket, storageId);\n\n const downloadConfig = await resolved.getSignedUrl(resolvedPath, bucket);\n\n if (downloadConfig.fileNotFound) {\n throw ApiError.notFound(\"File not found\");\n }\n\n if (downloadConfig.metadata) {\n const scopedPath = `${bucket}/${resolvedPath}`;\n if (isPublicStoragePath(scopedPath)) {\n // Public object: served token-less via a permanent URL.\n downloadConfig.metadata.public = true;\n } else {\n // Private object: mint a short-lived, path-scoped download token.\n downloadConfig.metadata.token = generateDownloadToken(scopedPath, 300);\n downloadConfig.metadata.tokenExpiresIn = 300;\n }\n }\n\n return c.json({\n success: true,\n data: downloadConfig.metadata\n });\n });\n\n /**\n * DELETE /file/* - Delete a file\n */\n router.delete(\"/file/*\", writeAuthMiddleware, async (c) => {\n const rawPath = extractWildcardPath(c);\n if (!rawPath) {\n return c.json({ success: true,\nmessage: \"No file to delete\" });\n }\n\n const filePath = decodeURIComponent(rawPath);\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n const { bucket, resolvedPath } = parseBucketAndPath(filePath);\n\n await checkAuthorized(c, \"delete\", resolvedPath, bucket, storageId);\n\n await resolved.deleteObject(resolvedPath, bucket);\n\n return c.json({\n success: true,\n message: \"File deleted\"\n });\n });\n\n /**\n * GET /list - List files in a path\n */\n router.get(\"/list\", writeAuthMiddleware, async (c) => {\n // Fallback to path for backward compatibility. Sanitize the prefix the\n // same way object keys are sanitized elsewhere, so a listing cannot be\n // steered out of the bucket with `../` before it hits the controller.\n const storagePrefix = sanitizeStorageKey(c.req.query(\"prefix\") || c.req.query(\"path\") || \"\");\n const bucket = c.req.query(\"bucket\");\n const maxResults = c.req.query(\"maxResults\");\n const pageToken = c.req.query(\"pageToken\");\n const storageId = c.req.query(\"storageId\");\n const resolved = resolveController(storageId);\n\n // The prefix is the \"object\" being asked about — a listing is how you\n // discover keys you were never told, so leaving it ungated would hand\n // back exactly what per-object read control is meant to withhold.\n await checkAuthorized(c, \"list\", storagePrefix, bucket ?? \"default\", storageId);\n\n const result = await resolved.listObjects(\n storagePrefix,\n {\n bucket: bucket ?? (resolved.getType() === \"local\" ? \"default\" : undefined),\n maxResults: maxResults ? parseInt(maxResults, 10) : undefined,\n pageToken\n }\n );\n\n return c.json({\n success: true,\n data: result\n });\n });\n\n /**\n * POST /folder - Create a new folder\n * Body: { path: string, bucket?: string }\n */\n router.post(\"/folder\", writeAuthMiddleware, async (c) => {\n const body = await c.req.json();\n const folderPath = body.path;\n const storageId = typeof body.storageId === \"string\" ? body.storageId : c.req.query(\"storageId\");\n\n if (!folderPath || typeof folderPath !== \"string\") {\n throw ApiError.badRequest(\"Folder path is required\");\n }\n\n const resolved = resolveController(storageId);\n const { bucket, resolvedPath } = parseBucketAndPath(folderPath);\n\n if (!resolvedPath || resolvedPath.trim() === \"\") {\n throw ApiError.badRequest(\"Invalid folder path\");\n }\n\n await checkAuthorized(c, \"write\", resolvedPath, bucket, storageId);\n\n if (resolved.getType() === \"local\") {\n // For local storage, create the directory\n const localController = resolved as LocalStorageController;\n const absolutePath = localController.getAbsolutePath(resolvedPath, bucket);\n fs.mkdirSync(absolutePath, { recursive: true });\n } else {\n // For S3/GCS-compatible storage, create a zero-byte marker object with trailing slash\n const key = resolvedPath.endsWith(\"/\") ? resolvedPath : resolvedPath + \"/\";\n const emptyFile = new File([], key, { type: \"application/x-directory\" });\n await resolved.putObject({\n file: emptyFile,\n key\n });\n }\n\n return c.json({\n success: true,\n message: \"Folder created\"\n }, 201);\n });\n\n // -----------------------------------------------------------------------\n // TUS Resumable Uploads\n // -----------------------------------------------------------------------\n\n const defaultCtrl = getDefaultController();\n const tusBaseDir = defaultCtrl.getType() === \"local\"\n ? (defaultCtrl as LocalStorageController).getBasePath()\n : (process.env.STORAGE_PATH || \"./uploads\");\n const tusHandler = new TusHandler(\n tusBaseDir,\n defaultCtrl,\n registry,\n authorize\n ? async (c, key, bucket) => {\n await checkAuthorized(c as never, \"write\", sanitizeStorageKey(key), bucket, c.req.query(\"storageId\"));\n }\n : undefined\n );\n tusHandler.startCleanup();\n\n router.options(\"/tus\", (_c) => tusHandler.options());\n router.post(\"/tus\", writeAuthMiddleware, async (c) => tusHandler.create(c));\n router.get(\"/tus/:id\", readAuthMiddleware, (c) => tusHandler.head(c, c.req.param(\"id\")));\n router.patch(\"/tus/:id\", writeAuthMiddleware, async (c) => tusHandler.patch(c, c.req.param(\"id\")));\n router.delete(\"/tus/:id\", writeAuthMiddleware, async (c) => tusHandler.delete(c, c.req.param(\"id\")));\n\n // -----------------------------------------------------------------------\n // Storage Sources Discovery\n // -----------------------------------------------------------------------\n\n /**\n * GET /sources — list all registered storage backends.\n * The client can bootstrap its StorageSourceRegistry from this endpoint.\n */\n router.get(\"/sources\", (c) => {\n const byKey = new Map<string, { key: string; engine: string; transport: \"server\" | \"direct\"; label?: string }>();\n\n // 1. Server-backed sources derived from the registry (source of truth\n // for the actual engine type), or the single controller.\n if (registry) {\n for (const key of registry.list()) {\n byKey.set(key, {\n key,\n engine: registry.get(key)?.getType() ?? \"unknown\",\n transport: \"server\",\n });\n }\n } else {\n byKey.set(DEFAULT_STORAGE_SOURCE_KEY, {\n key: DEFAULT_STORAGE_SOURCE_KEY,\n engine: defaultCtrl.getType(),\n transport: \"server\",\n });\n }\n\n // 2. Overlay declared definitions: adds `direct` sources the backend\n // does not proxy, plus labels and explicit transport/engine.\n for (const def of declaredSources ?? []) {\n const existing = byKey.get(def.key);\n byKey.set(def.key, {\n key: def.key,\n engine: def.engine ?? existing?.engine ?? \"unknown\",\n transport: def.transport ?? existing?.transport ?? \"server\",\n label: def.label ?? existing?.label,\n });\n }\n\n return c.json({ success: true, data: Array.from(byKey.values()) });\n });\n\n return router;\n}\n","/**\n * Storage Registry\n *\n * Manages multiple storage controllers for Rebase backend.\n * Allows different storage backends for different use cases.\n *\n * Usage:\n * - Single storage: Pass a single StorageController → maps to \"(default)\"\n * - Multiple storages: Pass a map of { storageId: StorageController }\n * - String properties use `storageId` in their config to specify which storage to use\n * - Properties without `storageId` fallback to \"(default)\"\n */\n\nimport { StorageController } from \"./types\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * The default storage identifier used when:\n * - A single storage controller is provided (not a map)\n * - A property doesn't specify a storageId\n */\nexport const DEFAULT_STORAGE_ID = \"(default)\";\n\n/**\n * Registry for managing multiple storage controllers\n */\nexport interface StorageRegistry {\n /**\n * Register a storage controller with an ID\n * @param id - Unique identifier for this storage (e.g., \"media\", \"backups\")\n * @param controller - The StorageController instance\n */\n register(id: string, controller: StorageController): void;\n\n /**\n * Get the default storage controller (id = \"(default)\")\n * @throws Error if no default storage is registered\n */\n getDefault(): StorageController;\n\n /**\n * Get a storage controller by ID\n * @param id - Storage identifier, or undefined/null for default\n * @returns The StorageController, or undefined if not found\n */\n get(id: string | undefined | null): StorageController | undefined;\n\n /**\n * Get a storage controller by ID, with fallback to default\n * @param id - Storage identifier, or undefined/null for default\n * @returns The StorageController (falls back to default if id not found)\n * @throws Error if neither the specified nor default storage exists\n */\n getOrDefault(id: string | undefined | null): StorageController;\n\n /**\n * Check if a storage with the given ID exists\n */\n has(id: string): boolean;\n\n /**\n * List all registered storage IDs\n */\n list(): string[];\n\n /**\n * Get the number of registered storage controllers\n */\n size(): number;\n}\n\n/**\n * Default implementation of StorageRegistry\n */\nexport class DefaultStorageRegistry implements StorageRegistry {\n private controllers = new Map<string, StorageController>();\n\n /**\n * Create a StorageRegistry from either a single controller or a map\n * @param input - Single StorageController (maps to \"(default)\") or Record<string, StorageController>\n */\n static create(\n input: StorageController | Record<string, StorageController>\n ): DefaultStorageRegistry {\n const registry = new DefaultStorageRegistry();\n\n if (isStorageController(input)) {\n // Single controller → register as \"(default)\"\n registry.register(DEFAULT_STORAGE_ID, input);\n } else {\n // Map of controllers → register each\n for (const [id, controller] of Object.entries(input)) {\n if (isStorageController(controller)) {\n registry.register(id, controller);\n }\n }\n // Ensure there's a default if not explicitly provided\n if (!registry.has(DEFAULT_STORAGE_ID) && registry.size() > 0) {\n // If no explicit \"(default)\", use the first one as default\n const firstId = Object.keys(input).find(k => isStorageController(input[k]));\n if (firstId) {\n logger.warn(\n `[StorageRegistry] No \"${DEFAULT_STORAGE_ID}\" storage provided. ` +\n `Using \"${firstId}\" as the default.`\n );\n registry.register(DEFAULT_STORAGE_ID, input[firstId]);\n }\n }\n }\n\n return registry;\n }\n\n register(id: string, controller: StorageController): void {\n if (this.controllers.has(id)) {\n logger.warn(`[StorageRegistry] Overwriting storage with id \"${id}\"`);\n }\n this.controllers.set(id, controller);\n }\n\n getDefault(): StorageController {\n const controller = this.controllers.get(DEFAULT_STORAGE_ID);\n if (!controller) {\n throw new Error(\n \"[StorageRegistry] No default storage registered. \" +\n `Register one with id \"${DEFAULT_STORAGE_ID}\" or pass a single StorageController.`\n );\n }\n return controller;\n }\n\n get(id: string | undefined | null): StorageController | undefined {\n if (id === undefined || id === null) {\n return this.controllers.get(DEFAULT_STORAGE_ID);\n }\n return this.controllers.get(id);\n }\n\n getOrDefault(id: string | undefined | null): StorageController {\n // If no ID specified, return default\n if (id === undefined || id === null) {\n return this.getDefault();\n }\n\n // Try to get by ID\n const controller = this.controllers.get(id);\n if (controller) {\n return controller;\n }\n\n // Fallback to default with warning\n logger.warn(\n `[StorageRegistry] Storage \"${id}\" not found, falling back to \"${DEFAULT_STORAGE_ID}\"`\n );\n return this.getDefault();\n }\n\n has(id: string): boolean {\n return this.controllers.has(id);\n }\n\n list(): string[] {\n return Array.from(this.controllers.keys());\n }\n\n size(): number {\n return this.controllers.size;\n }\n}\n\n/**\n * Type guard to check if an object is a StorageController\n * vs a Record<string, StorageController> (multiple storages)\n */\nfunction isStorageController(obj: unknown): obj is StorageController {\n if (typeof obj !== \"object\" || obj === null) {\n return false;\n }\n const controller = obj as StorageController;\n // Check for required StorageController properties\n return (\n typeof controller.putObject === \"function\" &&\n typeof controller.getSignedUrl === \"function\" &&\n typeof controller.deleteObject === \"function\" &&\n typeof controller.listObjects === \"function\" &&\n typeof controller.getType === \"function\"\n );\n}\n","/**\n * Storage module for Rebase backend\n *\n * Provides pluggable file storage with three built-in providers:\n * - **Local filesystem** — zero config, great for dev and single-server deployments.\n * - **S3-compatible** — works with AWS S3, Cloudflare R2, MinIO, Hetzner Object Storage,\n * Backblaze B2, DigitalOcean Spaces, and GCS (via S3 interop).\n * - **Google Cloud Storage / Firebase Storage** — native GCS support via `@google-cloud/storage`\n * (optional peer dependency, lazily loaded).\n *\n * For other providers (Azure Blob, etc.), implement the\n * `StorageController` interface and pass the instance directly to the `storage` config.\n */\n\nexport * from \"./types\";\nexport { LocalStorageController } from \"./LocalStorageController\";\nexport { S3StorageController } from \"./S3StorageController\";\nexport { GCSStorageController } from \"./GCSStorageController\";\nexport { createStorageRoutes } from \"./routes\";\nexport type { StorageRoutesConfig } from \"./routes\";\nexport * from \"./storage-registry\";\nexport { parseTransformOptions, transformImage, isTransformableImage, TransformCache } from \"./image-transform\";\nexport type { ImageTransformOptions } from \"./image-transform\";\nexport { TusHandler } from \"./tus-handler\";\n\nimport { BackendStorageConfig, StorageController } from \"./types\";\nimport { LocalStorageController } from \"./LocalStorageController\";\n\n/**\n * Create a storage controller from a config object.\n *\n * For custom providers, implement `StorageController` directly instead\n * of going through this factory.\n */\nexport async function createStorageController(config: BackendStorageConfig): Promise<StorageController> {\n switch (config.type) {\n case \"local\":\n return new LocalStorageController(config);\n case \"s3\": {\n const { S3StorageController } = await import(\"./S3StorageController\");\n return new S3StorageController(config);\n }\n case \"gcs\": {\n const { GCSStorageController } = await import(\"./GCSStorageController\");\n return new GCSStorageController(config);\n }\n default:\n throw new Error(\n `Unknown storage type: ${(config as Record<string, unknown>).type}. ` +\n \"Built-in types: local, s3, gcs. \" +\n \"For other providers, implement the StorageController interface directly.\"\n );\n }\n}\n","import {\n BackendStorageConfig,\n createStorageController,\n DEFAULT_STORAGE_ID,\n DefaultStorageRegistry,\n StorageController,\n StorageRegistry\n} from \"../storage\";\nimport { logger } from \"../utils/logger\";\n\nexport async function initializeStorage(\n storageConfig: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController> | undefined,\n isProduction: boolean\n): Promise<{ storageRegistry?: StorageRegistry; storageController?: StorageController }> {\n if (!storageConfig) return {};\n\n logger.info(\"Configuring storage\");\n const controllers: Record<string, StorageController> = {};\n\n const toController = async (entry: BackendStorageConfig | StorageController, label: string): Promise<StorageController | undefined> => {\n if (typeof (entry as StorageController).putObject === \"function\") {\n return entry as StorageController;\n }\n const conf = entry as BackendStorageConfig;\n // On a managed platform the local backend is a pod's ephemeral\n // filesystem, so every uploaded file disappears at the next restart —\n // with no error at write time, no error at read time, and a log line\n // nobody reads until the data is already gone.\n //\n // So in production this backend is not registered at all. Storage is\n // off until a bucket is configured: uploads are refused with\n // STORAGE_NOT_CONFIGURED (see the stub router in `init.ts`) instead of\n // succeeding into a filesystem that is about to be wiped. Dropping the\n // backend rather than throwing keeps the rest of the app — data, auth,\n // realtime — serving, which a crash-looping rollout would not.\n if (isProduction && conf.type === \"local\" && !process.env.FORCE_LOCAL_STORAGE) {\n logger.error(\n `Storage backend \"${label}\" is set to \"local\" in production — DISABLED. Local ` +\n \"storage is the container filesystem, so uploaded files would be destroyed on the \" +\n \"next restart or redeploy. File uploads will be refused until storage is \" +\n \"configured: set S3-compatible storage (STORAGE_TYPE=s3) or GCS \" +\n \"(STORAGE_TYPE=gcs), or pass a custom StorageController. If this deployment \" +\n \"really does have a durable volume mounted at the storage path, set \" +\n \"FORCE_LOCAL_STORAGE=true.\"\n );\n return undefined;\n }\n return await createStorageController(conf);\n };\n\n if (\n typeof storageConfig === \"object\" &&\n (\"type\" in storageConfig || typeof (storageConfig as StorageController).putObject === \"function\")\n ) {\n const controller = await toController(\n storageConfig as BackendStorageConfig | StorageController,\n DEFAULT_STORAGE_ID\n );\n if (controller) controllers[DEFAULT_STORAGE_ID] = controller;\n } else {\n for (const [storageId, entry] of Object.entries(\n storageConfig as Record<string, BackendStorageConfig | StorageController>\n )) {\n const controller = await toController(entry, storageId);\n if (controller) controllers[storageId] = controller;\n }\n }\n\n if (Object.keys(controllers).length > 0) {\n const storageRegistry = DefaultStorageRegistry.create(controllers);\n const storageController = storageRegistry.getDefault();\n logger.info(\"Initialized storage backends\", { count: Object.keys(controllers).length });\n return { storageRegistry, storageController };\n }\n\n return {};\n}\n\n/** Inputs that decide whether storage has an access-control model at all. */\nexport interface StorageAccessControlState {\n /** A `storageAuthorize` hook was configured (per-object access control). */\n hasAuthorize: boolean;\n /** Reads are deliberately public (`storagePublicRead: true`). */\n publicRead: boolean;\n /** The legacy \"any authenticated user may touch any key\" behaviour was\n * explicitly acknowledged (`storageInsecureAllowAnyAuthenticated: true`). */\n allowAnyAuthenticated: boolean;\n}\n\n/**\n * The one message the boot guard emits, factored out so the production throw\n * and the development warning say exactly the same thing.\n */\nconst STORAGE_NO_ACCESS_CONTROL_MESSAGE =\n \"Storage is configured WITHOUT any access-control model. Keys share one flat \" +\n \"namespace and no `storageAuthorize` hook is set, so any authenticated user can \" +\n \"list every key (GET /storage/list?prefix=) and then read, overwrite or delete \" +\n \"any other user's files. Fix one of:\\n\" +\n \" • add a `storageAuthorize` hook that scopes access per user/tenant (recommended), or\\n\" +\n \" • set `storagePublicRead: true` if this bucket is genuinely a public read-only CDN, or\\n\" +\n \" • set `storageInsecureAllowAnyAuthenticated: true` to keep the legacy shared-namespace\\n\" +\n \" behaviour on purpose (single-tenant apps where every signed-in user is trusted).\";\n\n/**\n * Refuse to boot storage in production with no access-control model.\n *\n * Storage is not under RLS and its keys share one flat namespace, so with no\n * `storageAuthorize` hook the only thing separating two users' files is key\n * unguessability — which a `GET /list` defeats. This is the storage analogue of\n * the locked-by-default RLS on collections: rather than ship an allow-all\n * default silently, make the deployment state its intent.\n *\n * In production a bare allow-all config is refused (throws, so the rollout\n * fails loudly instead of serving everyone's files to everyone). Outside\n * production it is a loud warning, so local development is not blocked.\n *\n * Any one of the three explicit choices — a hook, public-read, or the insecure\n * opt-out — satisfies the guard.\n */\nexport function assertStorageAccessControlConfigured(\n state: StorageAccessControlState,\n isProduction: boolean\n): void {\n if (state.hasAuthorize || state.publicRead || state.allowAnyAuthenticated) {\n return;\n }\n if (isProduction) {\n throw new Error(STORAGE_NO_ACCESS_CONTROL_MESSAGE);\n }\n logger.warn(STORAGE_NO_ACCESS_CONTROL_MESSAGE);\n}\n","import { Hono } from \"hono\";\nimport { CollectionConfig } from \"@rebasepro/types\";\nimport { HonoEnv } from \"../api/types\";\nimport { logger } from \"../utils/logger\";\n\nexport async function mountOpenApiDocs(\n app: Hono<HonoEnv>,\n basePath: string,\n enableSwagger: boolean | undefined,\n activeCollections: CollectionConfig[],\n requireAuth: boolean\n): Promise<void> {\n if (enableSwagger === false || activeCollections.length === 0) {\n return;\n }\n\n const { generateOpenApiSpec } = await import(\"../api/openapi-generator\");\n\n app.get(`${basePath}/docs`, (c) => {\n const spec = generateOpenApiSpec(activeCollections, {\n basePath,\n requireAuth\n });\n return c.json(spec);\n });\n\n if (process.env.NODE_ENV !== \"production\") {\n app.get(`${basePath}/swagger`, (c) => {\n return c.html(`<!DOCTYPE html>\n<html>\n<head>\n <title>Rebase API Documentation</title>\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <link rel=\"stylesheet\" type=\"text/css\" href=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui.css\"/>\n <style>body{margin:0;padding:0;}</style>\n</head>\n<body>\n <div id=\"swagger-ui\"></div>\n <script src=\"https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js\"></script>\n <script>SwaggerUIBundle({ url: '${basePath}/docs', dom_id: '#swagger-ui' });</script>\n</body>\n</html>`);\n });\n logger.info(\"Swagger UI available\", { path: `${basePath}/swagger` });\n }\n}\n","import { AuthSchemaHealth, DataDriver, HealthCheckResult, isSQLAdmin } from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\n\n/**\n * @param defaultDriver — probed for basic database reachability.\n * @param authSchemaCheck — optional; asserts the auth schema is one this\n * runtime can serve. Reachability alone is not health: a database can answer\n * `SELECT 1` in a millisecond while the auth tables have been migrated out\n * from under the running code, so every login returns 500 behind a green\n * check. Reporting that as healthy is what lets an orchestrator keep routing\n * traffic to a server that cannot authenticate anyone.\n */\nexport function createHealthCheck(\n defaultDriver: DataDriver,\n authSchemaCheck?: () => Promise<AuthSchemaHealth>\n): () => Promise<HealthCheckResult> {\n return async (): Promise<HealthCheckResult> => {\n const start = performance.now();\n try {\n const admin = defaultDriver.admin;\n if (isSQLAdmin(admin)) {\n await admin.executeSql(\"SELECT 1\");\n } else {\n await defaultDriver.fetchCollection({\n path: \"__health_check_nonexistent__\",\n limit: 1\n });\n }\n\n const auth = await authSchemaCheck?.();\n const latencyMs = Math.round(performance.now() - start);\n if (auth && !auth.healthy) {\n logger.error(\"Health check failed: auth schema mismatch\", {\n problems: auth.problems,\n databaseVersion: auth.databaseVersion,\n runtimeVersion: auth.runtimeVersion\n });\n return {\n healthy: false,\n latencyMs,\n details: { authSchema: auth }\n };\n }\n\n return {\n healthy: true,\n latencyMs\n };\n } catch (error: unknown) {\n const latencyMs = Math.round(performance.now() - start);\n logger.error(\"Health check failed\", {\n error: error instanceof Error ? error : new Error(String(error)),\n latencyMs\n });\n return {\n healthy: false,\n latencyMs,\n details: {\n error: error instanceof Error ? error.message : String(error)\n }\n };\n }\n };\n}\n","import { Server } from \"http\";\nimport { RealtimeProvider } from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\n\ninterface ShutdownConfig {\n server: Server;\n cronScheduler?: { stop(): void };\n realtimeServices: Record<string, RealtimeProvider>;\n}\n\n/**\n * Minimal structural view of the backend instance needed by\n * {@link installShutdownHandlers}. Structural (rather than importing\n * `RebaseBackendInstance`) to avoid a circular import with `../init`.\n */\ninterface ShutdownCapableBackend {\n shutdown(timeoutMs?: number): Promise<void>;\n}\n\nexport interface ShutdownHandlerOptions {\n /**\n * Cleanup to run after the backend has drained — e.g. closing your\n * database pool: `onCleanup: () => pool.end()`.\n */\n onCleanup?: () => Promise<void> | void;\n\n /**\n * Hard force-exit timeout in milliseconds. If the shutdown sequence\n * (drain + cleanup) has not completed by then, the process exits with\n * code 1. Also passed to `backend.shutdown()` as its drain timeout.\n *\n * @default 15000\n */\n timeoutMs?: number;\n\n /**\n * Process signals to handle.\n * @default [\"SIGTERM\", \"SIGINT\"]\n */\n signals?: NodeJS.Signals[];\n\n /** @internal Injectable exit function for tests. */\n exit?: (code: number) => void;\n}\n\n/**\n * Install graceful-shutdown signal handlers for a Rebase backend.\n *\n * On the first signal received, this drains the backend via\n * `backend.shutdown()` — which stops the cron scheduler, tears down\n * realtime services, and closes the HTTP server. Do **not** call\n * `server.close()` yourself in addition: closing an already-closing\n * server deadlocks, because the second close's callback never fires.\n *\n * After the drain, `onCleanup` runs (close your database pool here),\n * and the process exits 0. A force-exit timer guards the whole\n * sequence: if it has not completed within `timeoutMs`, the process\n * exits 1. Repeated signals while a shutdown is in flight are ignored.\n *\n * @returns An uninstall function that removes the signal listeners\n * (useful in tests).\n *\n * @example\n * ```ts\n * const backend = await initializeRebaseBackend({ ... });\n * installShutdownHandlers(backend, { onCleanup: () => pool.end() });\n * ```\n */\nexport function installShutdownHandlers(\n backend: ShutdownCapableBackend,\n options: ShutdownHandlerOptions = {}\n): () => void {\n const {\n onCleanup,\n timeoutMs = 15_000,\n signals = [\"SIGTERM\", \"SIGINT\"],\n exit = process.exit\n } = options;\n\n let shuttingDown = false;\n\n const shutdownSequence = async (signal: NodeJS.Signals): Promise<void> => {\n if (shuttingDown) return;\n shuttingDown = true;\n\n logger.info(`Received ${signal}, shutting down gracefully...`);\n\n // Hard backstop — must be armed before any awaits.\n const forceTimer = setTimeout(() => {\n logger.error(`Shutdown timed out after ${Math.round(timeoutMs / 1000)}s. Forcefully exiting.`);\n exit(1);\n }, timeoutMs);\n forceTimer.unref();\n\n try {\n await backend.shutdown(timeoutMs);\n if (onCleanup) {\n await onCleanup();\n }\n clearTimeout(forceTimer);\n logger.info(\"Graceful shutdown complete.\");\n exit(0);\n } catch (err) {\n logger.error(\"Error during shutdown cleanup:\", { error: err instanceof Error ? err : new Error(String(err)) });\n exit(1);\n }\n };\n\n const listeners = signals.map((signal) => {\n const listener = () => { void shutdownSequence(signal); };\n process.on(signal, listener);\n return { signal, listener } as const;\n });\n\n return () => {\n for (const { signal, listener } of listeners) {\n process.removeListener(signal, listener);\n }\n };\n}\n\nexport function createShutdown(config: ShutdownConfig): (timeoutMs?: number) => Promise<void> {\n return (timeoutMs = 15_000): Promise<void> => {\n return new Promise<void>((resolve) => {\n (async () => {\n logger.info(\"Shutting down Rebase Backend...\");\n\n // 1. Stop cron scheduler\n if (config.cronScheduler) {\n config.cronScheduler.stop();\n logger.info(\"Cron scheduler stopped\");\n }\n\n // 2. Tear down realtime services (LISTEN clients, debounce timers,\n // subscriptions). Must happen BEFORE pool.end() so that pending\n // timer callbacks don't fire against a closed pool.\n for (const [key, rt] of Object.entries(config.realtimeServices)) {\n try {\n if (typeof rt.destroy === \"function\") {\n await rt.destroy();\n logger.info(`Realtime service \"${key}\" destroyed`);\n } else if (typeof rt.stopListening === \"function\") {\n await rt.stopListening();\n logger.info(`Realtime service \"${key}\" LISTEN client stopped`);\n }\n } catch (err) {\n logger.warn(`Error destroying realtime service \"${key}\":`, { error: err });\n }\n }\n\n // 3. Close the HTTP server (stop accepting, drain in-flight)\n config.server.close(() => {\n logger.info(\"HTTP server closed\");\n resolve();\n });\n\n // 4. Force-resolve after timeout (unless disabled with 0)\n if (timeoutMs > 0) {\n setTimeout(() => {\n logger.warn(`Forced shutdown after ${timeoutMs / 1000}s timeout`);\n resolve();\n }, timeoutMs).unref();\n }\n })();\n });\n };\n}\n","import { logger } from \"../utils/logger\";\n\n/** The data callbacks the auth write path does not run. */\nconst DATA_CALLBACKS = [\"beforeSave\", \"afterSave\", \"beforeDelete\", \"afterDelete\"] as const;\n\n/**\n * Warn when the auth collection hangs data callbacks that auth will not fire.\n *\n * Creating a user through the auth subsystem — registration, OAuth, the admin\n * user routes — writes to the user store directly, because that path owns\n * password hashing, identity rows and its own transaction. It deliberately does\n * not go through the collection save pipeline: a `beforeSave` able to rewrite\n * `password_hash` on its way to the database is a footgun, not a feature, and\n * the auth hooks (`afterUserCreate`, `beforeUserCreate`, …) exist to hang\n * behaviour off those events with the right contract.\n *\n * The cost is a reasonable expectation quietly not being met: someone puts\n * \"send the welcome email\" in `afterSave` on their users collection, tests it\n * by creating a user in the admin, and it works — because *that* is a\n * collection write. Then a real signup does nothing at all. Which is why this\n * is said at boot, naming the callbacks that will not run.\n */\nexport function warnOnAuthCollectionDataCallbacks(collection?: {\n slug?: string;\n callbacks?: Record<string, unknown>;\n}): void {\n if (!collection?.callbacks) return;\n\n const declared = DATA_CALLBACKS.filter(name => typeof collection.callbacks?.[name] === \"function\");\n if (declared.length === 0) return;\n\n logger.warn(\n `[Auth] The auth collection \"${collection.slug}\" defines ` +\n `${declared.join(\"/\")} callback(s), but these do NOT fire when users are ` +\n `created or updated through the auth system (registration, admin, OAuth) — ` +\n `that path bypasses the collection save pipeline. Use auth hooks ` +\n `(afterUserCreate, beforeUserCreate, afterUserDelete, …) for those side effects.`\n );\n}\n","import { DEFAULT_STORAGE_SOURCE_KEY, EntityReference, EntityRelation, GeoPoint, PUBLIC_STORAGE_PREFIX, RebaseApiError, RebaseApiError as RebaseApiError$1, RebaseClientError, RebaseClientError as RebaseClientError$1, Vector, isPublicStoragePath, toCanonicalOp } from \"@rebasepro/types\";\nimport { COMPOSITE_ID_SEPARATOR, QueryBuilder, RebasePaginationError, and, buildCompositeId, collectAllPages, cond, or, paginateFind, serializeFilter, serializeLogicalCondition, serializeOrderBy } from \"@rebasepro/common\";\nimport { toSnakeCase } from \"@rebasepro/utils\";\n//#region src/reviver.ts\nfunction rebaseReviver(_key, value) {\n\tif (value && typeof value === \"object\" && \"__type\" in value) {\n\t\tconst record = value;\n\t\tswitch (record.__type) {\n\t\t\tcase \"date\":\n\t\t\tcase \"Date\": {\n\t\t\t\tif (typeof record.value !== \"string\") return value;\n\t\t\t\tconst date = new Date(record.value);\n\t\t\t\treturn isNaN(date.getTime()) ? null : date;\n\t\t\t}\n\t\t\tcase \"reference\":\n\t\t\tcase \"EntityReference\": return new EntityReference({\n\t\t\t\tid: String(record.id),\n\t\t\t\tpath: record.path,\n\t\t\t\tdriver: record.driver,\n\t\t\t\tdatabaseId: record.databaseId\n\t\t\t});\n\t\t\tcase \"relation\":\n\t\t\tcase \"EntityRelation\": return new EntityRelation(record.id, record.path, record.data);\n\t\t\tcase \"GeoPoint\": return new GeoPoint(record.latitude, record.longitude);\n\t\t\tcase \"Vector\": return new Vector(record.value);\n\t\t\tdefault: return value;\n\t\t}\n\t}\n\treturn value;\n}\n//#endregion\n//#region src/transport.ts\n/**\n* True when there is no browser to have signed a user in — a Node script, a\n* cron job, an edge worker.\n*\n* Anonymous is an ordinary, correct state in a browser: before sign-in, on a\n* marketing page, for public reads. Warning there would be noise that teaches\n* people to ignore warnings, so the guard is off entirely. This uses the same\n* `typeof window` test as {@link resolveBaseUrl}, and additionally treats a\n* defined `document` as a browser so an SSR shim or test harness that installs\n* only one of the two is still excluded.\n*/\nfunction isServerLikeEnvironment() {\n\treturn typeof window === \"undefined\" && typeof document === \"undefined\";\n}\n/**\n* Emitted once per client. Kept as a constant so the wording is testable and\n* greppable — this is the string a user will paste into a search.\n*/\nvar ANONYMOUS_SERVER_CLIENT_WARNING = \"[rebase] This client was created outside a browser with no credential — no `token`, no auth token getter, and no cookie auth flow — so every request runs as an anonymous caller. Row-level security will return only publicly readable rows, which is usually nothing and occasionally the wrong thing. Inside a cron or function handler, use the `client` you were handed instead of building a new one: its data plane is already admin-scoped. In a standalone script or job, pass the service key as `token`. If you really do want anonymous access, pass `anonymous: true` to silence this.\";\n/**\n* Refuse a filter whose *value* is missing.\n*\n* `where: { status: [\"==\", undefined] }` used to serialize to the literal\n* string, so `status=eq.undefined` went out on the wire and the server dutifully\n* looked for rows whose status is the four-letter word \"undefined\". The caller\n* saw an empty page, not an error — the classic shape of a variable that was\n* never set.\n*\n* Dropping the condition instead would be worse than sending it: the query\n* would come back *unfiltered*, which for an ownership or tenant filter means\n* returning rows the caller never asked to see. So this is a hard error, and\n* both correct spellings are named in the message: omit the key to skip the\n* filter, or use `[\"is-null\", null]` to match SQL NULL (which still\n* serializes — `null` is a value, `undefined` is the absence of one).\n*/\nfunction assertNoUndefinedFilterValues(where) {\n\tconst reject = (field, op) => {\n\t\tthrow new RebaseClientError$1(`Filter on \"${field}\" has an undefined value ([\"${String(op)}\", undefined]). Omit \"${field}\" from \\`where\\` to skip the filter, or use [\"is-null\", null] to match SQL NULL.`);\n\t};\n\tfor (const [field, condition] of Object.entries(where)) {\n\t\tif (condition === void 0) continue;\n\t\tif (!Array.isArray(condition)) continue;\n\t\tconst tuples = Array.isArray(condition[0]) ? condition : [condition];\n\t\tfor (const tuple of tuples) {\n\t\t\tif (!Array.isArray(tuple) || tuple.length !== 2) continue;\n\t\t\tconst [op, value] = tuple;\n\t\t\tif (value === void 0) reject(field, op);\n\t\t\tif (Array.isArray(value) && value.some((v) => v === void 0)) reject(field, op);\n\t\t}\n\t}\n}\nfunction buildQueryString(params) {\n\tif (!params) return \"\";\n\tconst parts = [];\n\tif (params.limit != null) parts.push(`limit=${params.limit}`);\n\tif (params.offset != null) parts.push(`offset=${params.offset}`);\n\tif (params.page != null) parts.push(`page=${params.page}`);\n\tif (params.orderBy) {\n\t\tconst wire = serializeOrderBy(params.orderBy);\n\t\tif (wire) parts.push(`orderBy=${encodeURIComponent(wire)}`);\n\t}\n\tif (params.searchString) parts.push(`searchString=${encodeURIComponent(params.searchString)}`);\n\tif (params.include && params.include.length > 0) parts.push(`include=${encodeURIComponent(params.include.join(\",\"))}`);\n\tif (params.logical) {\n\t\tconst root = params.logical;\n\t\tconst serialized = (root.conditions ?? []).map(serializeLogicalCondition).join(\",\");\n\t\tparts.push(`${root.type}=${encodeURIComponent(`(${serialized})`)}`);\n\t}\n\tif (params.where) {\n\t\tassertNoUndefinedFilterValues(params.where);\n\t\tconst serialized = serializeFilter(params.where);\n\t\tfor (const [field, value] of Object.entries(serialized)) if (Array.isArray(value)) for (const v of value) parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(v)}`);\n\t\telse parts.push(`${encodeURIComponent(field)}=${encodeURIComponent(value)}`);\n\t}\n\treturn parts.length > 0 ? \"?\" + parts.join(\"&\") : \"\";\n}\n/**\n* The base every request and every caller-built URL resolves against.\n*\n* `baseUrl` is optional because the common production shape is a Rebase\n* backend serving its own SPA, where the API is simply the page's origin.\n* Leaving it unset is therefore the *correct* configuration there — and the\n* one that keeps working when a second hostname (a custom domain) points at\n* the same app.\n*\n* When unset in a browser this resolves to the page origin rather than \"\".\n* Requests behave identically either way, but the empty string is a trap for\n* anything that builds a URL from `client.baseUrl`: `new URL(\"\" + path)`\n* throws, so apps \"fixed\" it by baking an absolute host into their bundle —\n* which is exactly what breaks the day a custom domain is added, and which no\n* amount of CORS configuration repairs, because a SameSite=Lax auth cookie is\n* not sent cross-site either.\n*/\nfunction resolveBaseUrl(configured) {\n\tif (configured) return configured.replace(/\\/$/, \"\");\n\tif (typeof window !== \"undefined\" && window.location?.origin) return window.location.origin;\n\treturn \"\";\n}\nfunction createTransport(config, environment) {\n\tconst fetchFn = config.fetch || globalThis.fetch;\n\tconst apiPath = config.apiPath || \"/api\";\n\tlet token = config.token;\n\tlet tokenGetter;\n\tlet onUnauthorizedHandler = config.onUnauthorized;\n\t/** Once per client, never per request — log spam is its own bug. */\n\tlet anonymousWarningIssued = false;\n\t/**\n\t* Warn a server-side caller that it built a client that can only ever be\n\t* anonymous. Deliberately checked at the *first request* rather than at\n\t* construction: `setToken()` / `setAuthTokenGetter()` and a server-side\n\t* `auth.signIn…()` (which calls `transport.setToken`) all land after the\n\t* constructor, and warning at construction would fire on every one of them.\n\t*/\n\tfunction warnIfAnonymousServerClient(activeToken) {\n\t\tif (anonymousWarningIssued) return;\n\t\tif (activeToken) return;\n\t\tif (tokenGetter) return;\n\t\tif (config.anonymous) return;\n\t\tif (environment?.credentialOutOfBand) return;\n\t\tif (!isServerLikeEnvironment()) return;\n\t\tanonymousWarningIssued = true;\n\t\tconsole.warn(ANONYMOUS_SERVER_CLIENT_WARNING);\n\t}\n\tfunction getHeaders(activeToken, init) {\n\t\treturn {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t...activeToken ? { Authorization: `Bearer ${activeToken}` } : {},\n\t\t\t...init?.headers || {}\n\t\t};\n\t}\n\tasync function request(path, init) {\n\t\tconst url = resolveBaseUrl(config.baseUrl) + apiPath + path;\n\t\tlet activeToken = token;\n\t\tif (tokenGetter) try {\n\t\t\tconst fetched = await tokenGetter();\n\t\t\tif (fetched !== null && fetched !== void 0) activeToken = fetched;\n\t\t} catch (e) {}\n\t\twarnIfAnonymousServerClient(activeToken);\n\t\tconst headers = getHeaders(activeToken, init);\n\t\tif (init?.body instanceof FormData) delete headers[\"Content-Type\"];\n\t\tconst res = await fetchFn(url, {\n\t\t\t...init,\n\t\t\theaders\n\t\t});\n\t\tif (res.status === 204) return void 0;\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tlet body = {};\n\t\tif (text) try {\n\t\t\tbody = JSON.parse(text, rebaseReviver);\n\t\t} catch (e) {}\n\t\tconst getErrorField = (obj, field) => {\n\t\t\tconst err = obj?.error;\n\t\t\tif (err && typeof err === \"object\" && err !== null) return err[field];\n\t\t};\n\t\tif (res.status === 401 && onUnauthorizedHandler) {\n\t\t\tif (await onUnauthorizedHandler()) {\n\t\t\t\tlet retryToken = token;\n\t\t\t\tif (tokenGetter) try {\n\t\t\t\t\tconst fetched = await tokenGetter();\n\t\t\t\t\tif (fetched !== null && fetched !== void 0) retryToken = fetched;\n\t\t\t\t} catch (e) {}\n\t\t\t\tconst retryHeaders = getHeaders(retryToken, init);\n\t\t\t\tconst retryRes = await fetchFn(url, {\n\t\t\t\t\t...init,\n\t\t\t\t\theaders: retryHeaders\n\t\t\t\t});\n\t\t\t\tif (retryRes.status === 204) return void 0;\n\t\t\t\tconst retryText = await retryRes.text().catch(() => \"\");\n\t\t\t\tlet retryBody = {};\n\t\t\t\tif (retryText) try {\n\t\t\t\t\tretryBody = JSON.parse(retryText, rebaseReviver);\n\t\t\t\t} catch (e) {}\n\t\t\t\tif (!retryRes.ok) {\n\t\t\t\t\tlet fallbackMessage = retryRes.statusText;\n\t\t\t\t\tif (retryRes.status === 404 && !fallbackMessage) fallbackMessage = `Endpoint not found (${init?.method || \"GET\"} ${path}). This usually means the collection is not registered on the backend, or the frontend API URL configuration (e.g. VITE_API_URL) is missing or pointing to the wrong host.`;\n\t\t\t\t\tthrow new RebaseApiError$1(String(getErrorField(retryBody, \"message\") || fallbackMessage || `Request failed with status ${retryRes.status}`), {\n\t\t\t\t\t\tstatus: retryRes.status,\n\t\t\t\t\t\tcode: getErrorField(retryBody, \"code\"),\n\t\t\t\t\t\tdetails: getErrorField(retryBody, \"details\")\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn retryBody;\n\t\t\t}\n\t\t}\n\t\tif (!res.ok) {\n\t\t\tlet fallbackMessage = res.statusText;\n\t\t\tif (res.status === 404 && !fallbackMessage) fallbackMessage = `Endpoint not found (${init?.method || \"GET\"} ${path}). This usually means the collection is not registered on the backend, or the frontend API URL configuration (e.g. VITE_API_URL) is missing or pointing to the wrong host.`;\n\t\t\tthrow new RebaseApiError$1(String(getErrorField(body, \"message\") || fallbackMessage || `Request failed with status ${res.status}`), {\n\t\t\t\tstatus: res.status,\n\t\t\t\tcode: getErrorField(body, \"code\"),\n\t\t\t\tdetails: getErrorField(body, \"details\")\n\t\t\t});\n\t\t}\n\t\treturn body;\n\t}\n\treturn {\n\t\trequest,\n\t\tsetToken(newToken) {\n\t\t\ttoken = newToken || void 0;\n\t\t},\n\t\tsetAuthTokenGetter(getter) {\n\t\t\ttokenGetter = getter;\n\t\t},\n\t\tsetOnUnauthorized(handler) {\n\t\t\tonUnauthorizedHandler = handler;\n\t\t},\n\t\tget baseUrl() {\n\t\t\treturn resolveBaseUrl(config.baseUrl);\n\t\t},\n\t\tget apiPath() {\n\t\t\treturn apiPath;\n\t\t},\n\t\tget storageUrlOrigin() {\n\t\t\treturn config.storageUrlOrigin?.replace(/\\/$/, \"\") || void 0;\n\t\t},\n\t\tget fetchFn() {\n\t\t\treturn fetchFn;\n\t\t},\n\t\tgetHeaders: (init) => getHeaders(token, init),\n\t\tresolveToken: async () => {\n\t\t\tif (tokenGetter) try {\n\t\t\t\tconst fetched = await tokenGetter();\n\t\t\t\tif (fetched !== null && fetched !== void 0) return fetched;\n\t\t\t} catch (e) {}\n\t\t\treturn token || null;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/auth.ts\n/** Map a raw user object from an auth response (`/login`, `/refresh`, `/me`) to a `User`. */\nfunction mapRawUser(raw) {\n\treturn {\n\t\tuid: raw.uid,\n\t\temail: raw.email ?? null,\n\t\tdisplayName: raw.displayName ?? null,\n\t\tphotoURL: raw.photoURL ?? null,\n\t\tproviderId: raw.providerId ?? \"password\",\n\t\tisAnonymous: raw.isAnonymous ?? false,\n\t\temailVerified: raw.emailVerified,\n\t\troles: raw.roles,\n\t\tmetadata: raw.metadata\n\t};\n}\n/** Placeholder user, used only as a last resort when none can be resolved. */\nvar EMPTY_USER = {\n\tuid: \"\",\n\temail: null,\n\tdisplayName: null,\n\tphotoURL: null,\n\tproviderId: \"password\",\n\tisAnonymous: false\n};\nfunction createMemoryStorage() {\n\tconst store = {};\n\treturn {\n\t\tgetItem(key) {\n\t\t\treturn store[key] ?? null;\n\t\t},\n\t\tsetItem(key, value) {\n\t\t\tstore[key] = value;\n\t\t},\n\t\tremoveItem(key) {\n\t\t\tdelete store[key];\n\t\t}\n\t};\n}\nfunction detectStorage() {\n\ttry {\n\t\tif (typeof localStorage !== \"undefined\") {\n\t\t\tlocalStorage.setItem(\"__rebase_test__\", \"1\");\n\t\t\tlocalStorage.removeItem(\"__rebase_test__\");\n\t\t\treturn localStorage;\n\t\t}\n\t} catch (e) {}\n\treturn createMemoryStorage();\n}\nfunction createAuth(transport, options) {\n\tconst opts = options || {};\n\tconst storage = opts.storage || detectStorage();\n\tconst authPath = opts.authPath || \"/auth\";\n\tconst autoRefresh = opts.autoRefresh !== false;\n\tconst persistSession = opts.persistSession !== false;\n\tconst authFlowMode = opts.authFlowMode || \"json\";\n\tconst STORAGE_KEY = \"rebase_auth\";\n\tconst REFRESH_BUFFER_MS = 12e4;\n\tconst MAX_REFRESH_RETRIES = 5;\n\tconst REFRESH_RETRY_BASE_MS = 1e3;\n\tconst REFRESH_RETRY_MAX_MS = 3e4;\n\tlet currentSession = null;\n\tconst listeners = /* @__PURE__ */ new Set();\n\tlet refreshTimeout = null;\n\tlet inFlightRefresh = null;\n\tlet resolveInitialized;\n\tconst isInitialized = new Promise((resolve) => {\n\t\tresolveInitialized = resolve;\n\t});\n\tfunction authUrl(endpoint) {\n\t\treturn transport.baseUrl + transport.apiPath + authPath + endpoint;\n\t}\n\tfunction getFetch() {\n\t\treturn transport.fetchFn || globalThis.fetch;\n\t}\n\tfunction throwApiError(status, body, statusText) {\n\t\tthrow new RebaseApiError(body?.error?.message || body?.message || statusText, {\n\t\t\tstatus,\n\t\t\tcode: body?.error?.code || body?.code,\n\t\t\tdetails: body?.error?.details || body?.details\n\t\t});\n\t}\n\tfunction emit(event, session) {\n\t\tfor (const fn of listeners) try {\n\t\t\tfn(event, session);\n\t\t} catch (e) {}\n\t}\n\tfunction saveSession(session) {\n\t\tif (!persistSession || authFlowMode === \"cookie\") return;\n\t\ttry {\n\t\t\tstorage.setItem(STORAGE_KEY, JSON.stringify(session));\n\t\t} catch (e) {}\n\t}\n\tfunction clearStoredSession() {\n\t\ttry {\n\t\t\tstorage.removeItem(STORAGE_KEY);\n\t\t} catch (e) {}\n\t}\n\tfunction loadStoredSession() {\n\t\ttry {\n\t\t\tconst raw = storage.getItem(STORAGE_KEY);\n\t\t\tif (raw) return JSON.parse(raw);\n\t\t} catch (e) {}\n\t\treturn null;\n\t}\n\t/**\n\t* A refresh failure is only fatal if the refresh token itself is rejected\n\t* (expired / invalid / forbidden). Network blips, timeouts, and 5xx (e.g. a\n\t* backend restart mid-session) are transient and must NOT log the user out.\n\t*/\n\tfunction isFatalRefreshError(err) {\n\t\tif (!(err instanceof RebaseApiError)) return false;\n\t\tif (err.code === \"TOKEN_ALREADY_USED\") return false;\n\t\tif (err.code === \"INVALID_TOKEN\" || err.code === \"TOKEN_EXPIRED\") return true;\n\t\treturn err.status === 401 || err.status === 403;\n\t}\n\t/**\n\t* Drop this client's session without telling the server.\n\t*\n\t* `signOut()` is a user action: it POSTs /logout, which revokes the whole\n\t* sign-in. That is the wrong hammer for a refresh that failed. Our token\n\t* may be stale precisely because a sibling tab holds a live one, and\n\t* logging out on its behalf would turn one tab's bad luck into everybody\n\t* being signed out — the exact failure this work exists to remove.\n\t*/\n\tfunction abandonSessionLocally() {\n\t\tcurrentSession = null;\n\t\tclearStoredSession();\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t\ttransport.setToken(null);\n\t\temit(\"SIGNED_OUT\", null);\n\t}\n\t/**\n\t* Recover from a 401 on an ordinary API request.\n\t*\n\t* Returns `true` when the caller should retry — we minted a fresh access\n\t* token. When the refresh is rejected *fatally* (the refresh token itself\n\t* is invalid, expired or revoked) this client can no longer act as the\n\t* user at all, so we drop the session and emit `SIGNED_OUT`. UIs gate on\n\t* that event, so they show their login screen instead of leaving the user\n\t* staring at \"Invalid or expired token\" on every view.\n\t*\n\t* Transient failures (offline, 5xx, backend restarting) keep the session:\n\t* the scheduled refresh backs off and retries, and the token is very\n\t* likely still good once the backend answers again.\n\t*/\n\tasync function handleUnauthorized() {\n\t\tif (!currentSession) return false;\n\t\tif (authFlowMode !== \"cookie\" && !currentSession.refreshToken) {\n\t\t\tabandonSessionLocally();\n\t\t\treturn false;\n\t\t}\n\t\ttry {\n\t\t\tawait refreshSession();\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tif (isFatalRefreshError(err)) abandonSessionLocally();\n\t\t\treturn false;\n\t\t}\n\t}\n\tasync function attemptScheduledRefresh(attempt) {\n\t\ttry {\n\t\t\tawait refreshSession();\n\t\t} catch (err) {\n\t\t\tif (isFatalRefreshError(err)) {\n\t\t\t\tabandonSessionLocally();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (attempt >= MAX_REFRESH_RETRIES) {\n\t\t\t\tabandonSessionLocally();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst backoff = Math.min(REFRESH_RETRY_BASE_MS * 2 ** attempt, REFRESH_RETRY_MAX_MS);\n\t\t\trefreshTimeout = setTimeout(() => {\n\t\t\t\tattemptScheduledRefresh(attempt + 1);\n\t\t\t}, backoff);\n\t\t}\n\t}\n\tfunction scheduleRefresh(expiresAt) {\n\t\tif (refreshTimeout) clearTimeout(refreshTimeout);\n\t\tif (!autoRefresh) return;\n\t\tconst delay = expiresAt - REFRESH_BUFFER_MS - Date.now();\n\t\tif (delay <= 0) {\n\t\t\tattemptScheduledRefresh(0);\n\t\t\treturn;\n\t\t}\n\t\trefreshTimeout = setTimeout(() => {\n\t\t\tattemptScheduledRefresh(0);\n\t\t}, delay);\n\t}\n\t/**\n\t* Stop the scheduled token refresh, leaving the session itself alone.\n\t*\n\t* This is teardown, not sign-out. `scheduleRefresh` arms an ordinary\n\t* `setTimeout` up to a token lifetime away, and it is not `unref`'d — so on\n\t* Node it holds the event loop open by itself. `client.close()` promised\n\t* that \"a script that does not call this will not exit on its own\", which\n\t* was true, while the converse it plainly implies was not: a signed-in\n\t* client that closed its socket still hung, because this timer outlived it.\n\t* Any script, cron handler or job that signs in hit that.\n\t*\n\t* Deliberately does NOT clear the session, touch storage, or emit\n\t* SIGNED_OUT. Closing a client is not the user signing out — `signOut()`\n\t* POSTs /logout and revokes the whole sign-in, which is the wrong hammer\n\t* (see `abandonSessionLocally`) — and a persisted session must still be\n\t* there for the next client to restore.\n\t*/\n\tfunction stopAutoRefresh() {\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t}\n\tfunction handleAuthResponse(data, event) {\n\t\tconst user = mapRawUser(data.user);\n\t\tconst session = {\n\t\t\taccessToken: data.tokens.accessToken,\n\t\t\trefreshToken: data.tokens.refreshToken || currentSession?.refreshToken || \"\",\n\t\t\texpiresAt: data.tokens.accessTokenExpiresAt,\n\t\t\tuser\n\t\t};\n\t\tcurrentSession = session;\n\t\tsaveSession(session);\n\t\ttransport.setToken(session.accessToken);\n\t\tscheduleRefresh(session.expiresAt);\n\t\temit(event || \"SIGNED_IN\", session);\n\t\treturn session;\n\t}\n\tasync function signInWithEmail(email, password) {\n\t\tconst res = await getFetch()(authUrl(\"/login\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\temail,\n\t\t\t\tpassword\n\t\t\t}),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function signUp(email, password, displayName) {\n\t\tconst fetchFn = getFetch();\n\t\tconst payload = {\n\t\t\temail,\n\t\t\tpassword\n\t\t};\n\t\tif (displayName !== void 0) payload.displayName = displayName;\n\t\tconst res = await fetchFn(authUrl(\"/register\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\t/**\n\t* Sign in with Google.\n\t*\n\t* Supports three invocation styles:\n\t* - `signInWithGoogle({ idToken })` — ID-token flow (One Tap / Sign In button)\n\t* - `signInWithGoogle({ accessToken })` — Access-token flow (popup)\n\t* - `signInWithGoogle({ code, redirectUri })` — Authorization code flow (most secure)\n\t*/\n\tasync function signInWithGoogle(payload) {\n\t\tconst res = await getFetch()(authUrl(\"/google\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst responseBody = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, responseBody, res.statusText);\n\t\tconst session = handleAuthResponse(responseBody, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function signInWithLinkedin(code, redirectUri) {\n\t\tconst res = await getFetch()(authUrl(\"/linkedin\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tcode,\n\t\t\t\tredirectUri\n\t\t\t}),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\t/**\n\t* Generic OAuth sign-in. Posts the given payload to `/auth/{providerId}`.\n\t* Use this for any provider registered on the backend.\n\t*/\n\tasync function signInWithOAuth(providerId, payload) {\n\t\tconst res = await getFetch()(authUrl(`/${providerId}`), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(payload),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function signInWithGitHub(code, redirectUri) {\n\t\treturn signInWithOAuth(\"github\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithMicrosoft(code, redirectUri) {\n\t\treturn signInWithOAuth(\"microsoft\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithApple(code, redirectUri, user) {\n\t\treturn signInWithOAuth(\"apple\", {\n\t\t\tcode,\n\t\t\tredirectUri,\n\t\t\tuser\n\t\t});\n\t}\n\tasync function signInWithFacebook(code, redirectUri) {\n\t\treturn signInWithOAuth(\"facebook\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithTwitter(code, redirectUri, codeVerifier) {\n\t\treturn signInWithOAuth(\"twitter\", {\n\t\t\tcode,\n\t\t\tredirectUri,\n\t\t\tcodeVerifier\n\t\t});\n\t}\n\tasync function signInWithDiscord(code, redirectUri) {\n\t\treturn signInWithOAuth(\"discord\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithGitLab(code, redirectUri) {\n\t\treturn signInWithOAuth(\"gitlab\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithBitbucket(code, redirectUri) {\n\t\treturn signInWithOAuth(\"bitbucket\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithSlack(code, redirectUri) {\n\t\treturn signInWithOAuth(\"slack\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signInWithSpotify(code, redirectUri) {\n\t\treturn signInWithOAuth(\"spotify\", {\n\t\t\tcode,\n\t\t\tredirectUri\n\t\t});\n\t}\n\tasync function signOut() {\n\t\tconst fetchFn = getFetch();\n\t\ttry {\n\t\t\tif (authFlowMode === \"cookie\" || currentSession?.refreshToken) await fetchFn(authUrl(\"/logout\"), {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\t\tbody: JSON.stringify({ refreshToken: currentSession?.refreshToken }),\n\t\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t\t});\n\t\t} catch (e) {}\n\t\tcurrentSession = null;\n\t\tclearStoredSession();\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t\ttransport.setToken(null);\n\t\temit(\"SIGNED_OUT\", null);\n\t}\n\t/**\n\t* Serialise refreshes across TABS, not just within one.\n\t*\n\t* The in-flight promise below covers callers inside a single JavaScript\n\t* context. It does nothing about the far more common case: two tabs of the\n\t* same app booting together, each firing its own /refresh with the same\n\t* cookie. The server tolerates that now (superseded tokens stay usable for\n\t* a grace window), but tolerating a stampede is not the same as avoiding\n\t* one, and every extra rotation is another chance to end up holding a\n\t* token whose response never arrived.\n\t*\n\t* Web Locks are best-effort on purpose. supabase-js shipped this and then\n\t* spent a year fielding deadlock reports — a lock held by a crashed or\n\t* frozen tab must never be able to wedge sign-in — so a lock we cannot\n\t* take within the timeout is simply not taken, and the refresh proceeds\n\t* unserialised, exactly as it did before.\n\t*/\n\tconst REFRESH_LOCK_NAME = \"rebase-auth-refresh\";\n\tconst REFRESH_LOCK_TIMEOUT_MS = 5e3;\n\tasync function withRefreshLock(fn) {\n\t\tconst locks = globalThis.navigator?.locks;\n\t\tif (!locks?.request) return fn();\n\t\tconst controller = new AbortController();\n\t\tconst giveUp = setTimeout(() => controller.abort(), REFRESH_LOCK_TIMEOUT_MS);\n\t\ttry {\n\t\t\treturn await locks.request(REFRESH_LOCK_NAME, { signal: controller.signal }, async () => fn());\n\t\t} catch (e) {\n\t\t\tif (e?.name !== \"AbortError\") throw e;\n\t\t\treturn fn();\n\t\t} finally {\n\t\t\tclearTimeout(giveUp);\n\t\t}\n\t}\n\tfunction refreshSession() {\n\t\tif (inFlightRefresh) return inFlightRefresh;\n\t\tinFlightRefresh = withRefreshLock(() => doRefreshSession()).finally(() => {\n\t\t\tinFlightRefresh = null;\n\t\t});\n\t\treturn inFlightRefresh;\n\t}\n\tasync function doRefreshSession() {\n\t\tif (authFlowMode !== \"cookie\" && !currentSession?.refreshToken) throw new Error(\"No active session to refresh\");\n\t\tconst res = await getFetch()(authUrl(\"/refresh\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ refreshToken: currentSession?.refreshToken }),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst accessToken = body.tokens.accessToken;\n\t\ttransport.setToken(accessToken);\n\t\tlet user = currentSession?.user;\n\t\tif (body.user && typeof body.user.uid === \"string\") user = mapRawUser(body.user);\n\t\telse if (!user || !user.uid) try {\n\t\t\tuser = await getUser();\n\t\t} catch {}\n\t\tconst session = {\n\t\t\taccessToken,\n\t\t\trefreshToken: body.tokens.refreshToken || currentSession?.refreshToken || \"\",\n\t\t\texpiresAt: body.tokens.accessTokenExpiresAt,\n\t\t\tuser: user ?? EMPTY_USER\n\t\t};\n\t\tcurrentSession = session;\n\t\tsaveSession(session);\n\t\ttransport.setToken(session.accessToken);\n\t\tscheduleRefresh(session.expiresAt);\n\t\temit(\"TOKEN_REFRESHED\", session);\n\t\treturn session;\n\t}\n\tasync function getUser() {\n\t\treturn (await transport.request(authPath + \"/me\", { method: \"GET\" })).user;\n\t}\n\t/**\n\t* Resolve an email to a minimal public profile (`uid`, `displayName`,\n\t* `photoURL`) for invite-by-email flows. Returns `null` when no account\n\t* matches. Requires the backend to opt in via `auth.allowUserLookup`;\n\t* otherwise the endpoint is absent and this rejects.\n\t*/\n\tasync function findUserByEmail(email) {\n\t\treturn (await transport.request(authPath + \"/find-user\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify({ email })\n\t\t})).user;\n\t}\n\tasync function updateUser(updates) {\n\t\tconst data = await transport.request(authPath + \"/me\", {\n\t\t\tmethod: \"PATCH\",\n\t\t\tbody: JSON.stringify(updates)\n\t\t});\n\t\tif (currentSession) {\n\t\t\tcurrentSession = {\n\t\t\t\t...currentSession,\n\t\t\t\tuser: data.user\n\t\t\t};\n\t\t\tsaveSession(currentSession);\n\t\t\temit(\"USER_UPDATED\", currentSession);\n\t\t}\n\t\treturn data.user;\n\t}\n\tasync function resetPasswordForEmail(email) {\n\t\tconst res = await getFetch()(authUrl(\"/forgot-password\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ email })\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function resetPassword(token, password) {\n\t\tconst res = await getFetch()(authUrl(\"/reset-password\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\ttoken,\n\t\t\t\tpassword\n\t\t\t})\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function changePassword(oldPassword, newPassword) {\n\t\treturn transport.request(authPath + \"/change-password\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify({\n\t\t\t\toldPassword,\n\t\t\t\tnewPassword\n\t\t\t})\n\t\t});\n\t}\n\t/**\n\t* Link an OAuth provider to the **currently signed-in** account.\n\t*\n\t* Use this when `signIn*` failed with `EMAIL_NOT_VERIFIED` — an account\n\t* with that email already exists under a different sign-in method — or to\n\t* attach a provider whose email differs from the account's.\n\t*\n\t* The payload is the same one the provider's sign-in method takes, e.g.\n\t* `linkProvider(\"google\", { idToken })`.\n\t*\n\t* Unlike sign-in, this does not require the provider to have verified the\n\t* email, and the emails need not match: the active session already proves\n\t* account ownership.\n\t*\n\t* Throws `IDENTITY_ALREADY_LINKED` (409) if that provider identity is\n\t* attached to a different user. Succeeds idempotently (`alreadyLinked:\n\t* true`) if it is already attached to the current one.\n\t*/\n\tasync function linkProvider(providerId, payload) {\n\t\treturn transport.request(authPath + \"/link/\" + providerId, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(payload)\n\t\t});\n\t}\n\tasync function sendVerificationEmail() {\n\t\treturn transport.request(authPath + \"/send-verification\", { method: \"POST\" });\n\t}\n\tasync function verifyEmail(token) {\n\t\tconst res = await getFetch()(authUrl(\"/verify-email?token=\" + encodeURIComponent(token)), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" }\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function sendMagicLink(email) {\n\t\tconst res = await getFetch()(authUrl(\"/magic-link\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ email })\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tasync function verifyMagicLink(token) {\n\t\tconst res = await getFetch()(authUrl(\"/magic-link/verify\"), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ token }),\n\t\t\tcredentials: authFlowMode === \"cookie\" ? \"include\" : void 0\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\tconst session = handleAuthResponse(body, \"SIGNED_IN\");\n\t\treturn {\n\t\t\tuser: session.user,\n\t\t\taccessToken: session.accessToken,\n\t\t\trefreshToken: session.refreshToken\n\t\t};\n\t}\n\tasync function getSessions() {\n\t\treturn (await transport.request(authPath + \"/sessions\", { method: \"GET\" })).sessions;\n\t}\n\tasync function revokeSession(sessionId) {\n\t\treturn transport.request(authPath + \"/sessions/\" + encodeURIComponent(sessionId), { method: \"DELETE\" });\n\t}\n\tasync function revokeAllSessions() {\n\t\tconst result = await transport.request(authPath + \"/sessions\", { method: \"DELETE\" });\n\t\tcurrentSession = null;\n\t\tclearStoredSession();\n\t\tif (refreshTimeout) {\n\t\t\tclearTimeout(refreshTimeout);\n\t\t\trefreshTimeout = null;\n\t\t}\n\t\ttransport.setToken(null);\n\t\temit(\"SIGNED_OUT\", null);\n\t\treturn result;\n\t}\n\tasync function getAuthConfig() {\n\t\tconst res = await getFetch()(authUrl(\"/config\"), {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" }\n\t\t});\n\t\tconst body = await res.json().catch(() => ({}));\n\t\tif (!res.ok) throwApiError(res.status, body, res.statusText);\n\t\treturn body;\n\t}\n\tfunction getSession() {\n\t\treturn currentSession;\n\t}\n\tfunction onAuthStateChange(callback) {\n\t\tlisteners.add(callback);\n\t\treturn () => listeners.delete(callback);\n\t}\n\tif (persistSession) {\n\t\tconst stored = loadStoredSession();\n\t\tif (stored && stored.accessToken) if (stored.expiresAt > Date.now()) {\n\t\t\tcurrentSession = stored;\n\t\t\ttransport.setToken(stored.accessToken);\n\t\t\tscheduleRefresh(stored.expiresAt);\n\t\t\tresolveInitialized();\n\t\t} else if (authFlowMode === \"cookie\" || stored.refreshToken) {\n\t\t\tcurrentSession = stored;\n\t\t\trefreshSession().then(() => {\n\t\t\t\tresolveInitialized();\n\t\t\t}).catch(() => {\n\t\t\t\tcurrentSession = null;\n\t\t\t\tclearStoredSession();\n\t\t\t\ttransport.setToken(null);\n\t\t\t\tresolveInitialized();\n\t\t\t});\n\t\t} else resolveInitialized();\n\t\telse if (authFlowMode === \"cookie\") refreshSession().then(() => {\n\t\t\tresolveInitialized();\n\t\t}).catch(() => {\n\t\t\tresolveInitialized();\n\t\t});\n\t\telse resolveInitialized();\n\t} else resolveInitialized();\n\treturn {\n\t\tsignInWithEmail,\n\t\tsignUp,\n\t\tsignInWithGoogle,\n\t\tsignInWithLinkedin,\n\t\tsignInWithOAuth,\n\t\tsignInWithGitHub,\n\t\tsignInWithMicrosoft,\n\t\tsignInWithApple,\n\t\tsignInWithFacebook,\n\t\tsignInWithTwitter,\n\t\tsignInWithDiscord,\n\t\tsignInWithGitLab,\n\t\tsignInWithBitbucket,\n\t\tsignInWithSlack,\n\t\tsignInWithSpotify,\n\t\tsignOut,\n\t\tstopAutoRefresh,\n\t\trefreshSession,\n\t\thandleUnauthorized,\n\t\tgetUser,\n\t\tfindUserByEmail,\n\t\tupdateUser,\n\t\tresetPasswordForEmail,\n\t\tresetPassword,\n\t\tchangePassword,\n\t\tlinkProvider,\n\t\tsendVerificationEmail,\n\t\tverifyEmail,\n\t\tsendMagicLink,\n\t\tverifyMagicLink,\n\t\tgetSessions,\n\t\trevokeSession,\n\t\trevokeAllSessions,\n\t\tgetAuthConfig,\n\t\tgetSession,\n\t\tonAuthStateChange,\n\t\tcanRestoreSession: () => persistSession || authFlowMode === \"cookie\",\n\t\tisInitialized: () => isInitialized\n\t};\n}\nfunction createCookieStorage(options = {}) {\n\tconst defaultOptions = {\n\t\tpath: \"/\",\n\t\tsameSite: \"Lax\",\n\t\t...options\n\t};\n\treturn {\n\t\tgetItem(key) {\n\t\t\tif (typeof document === \"undefined\") return null;\n\t\t\tconst nameEQ = encodeURIComponent(key) + \"=\";\n\t\t\tconst ca = document.cookie.split(\";\");\n\t\t\tfor (let i = 0; i < ca.length; i++) {\n\t\t\t\tlet c = ca[i];\n\t\t\t\twhile (c.charAt(0) === \" \") c = c.substring(1, c.length);\n\t\t\t\tif (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tsetItem(key, value) {\n\t\t\tif (typeof document === \"undefined\") return;\n\t\t\tlet cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;\n\t\t\tif (defaultOptions.path) cookieStr += `; path=${defaultOptions.path}`;\n\t\t\tif (defaultOptions.domain) cookieStr += `; domain=${defaultOptions.domain}`;\n\t\t\tif (defaultOptions.maxAge !== void 0) cookieStr += `; max-age=${defaultOptions.maxAge}`;\n\t\t\telse cookieStr += `; max-age=${365 * 24 * 60 * 60}`;\n\t\t\tif (defaultOptions.secure) cookieStr += \"; secure\";\n\t\t\tif (defaultOptions.sameSite) cookieStr += `; samesite=${defaultOptions.sameSite}`;\n\t\t\tdocument.cookie = cookieStr;\n\t\t},\n\t\tremoveItem(key) {\n\t\t\tif (typeof document === \"undefined\") return;\n\t\t\tlet cookieStr = `${encodeURIComponent(key)}=; path=${defaultOptions.path || \"/\"}; max-age=-1`;\n\t\t\tif (defaultOptions.domain) cookieStr += `; domain=${defaultOptions.domain}`;\n\t\t\tdocument.cookie = cookieStr;\n\t\t}\n\t};\n}\n//#endregion\n//#region src/admin.ts\nfunction createAdmin(transport, options) {\n\tconst adminPath = (options || {}).adminPath || \"/admin\";\n\tasync function listUsers() {\n\t\treturn transport.request(adminPath + \"/users\", { method: \"GET\" });\n\t}\n\tasync function listUsersPaginated(options) {\n\t\tconst params = new URLSearchParams();\n\t\tif (options?.limit !== void 0) params.set(\"limit\", String(options.limit));\n\t\tif (options?.offset !== void 0) params.set(\"offset\", String(options.offset));\n\t\tif (options?.search) params.set(\"search\", options.search);\n\t\tif (options?.orderBy) params.set(\"orderBy\", options.orderBy);\n\t\tif (options?.orderDir) params.set(\"orderDir\", options.orderDir);\n\t\tconst qs = params.toString();\n\t\treturn transport.request(adminPath + \"/users\" + (qs ? \"?\" + qs : \"\"), { method: \"GET\" });\n\t}\n\tasync function getUser(userId) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId), { method: \"GET\" });\n\t}\n\tasync function createUser(data) {\n\t\treturn transport.request(adminPath + \"/users\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\tasync function updateUser(userId, data) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId), {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\tasync function deleteUser(userId) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId), { method: \"DELETE\" });\n\t}\n\tasync function resetPassword(userId, options) {\n\t\treturn transport.request(adminPath + \"/users/\" + encodeURIComponent(userId) + \"/reset-password\", {\n\t\t\tmethod: \"POST\",\n\t\t\t...options?.password ? { body: JSON.stringify({ password: options.password }) } : {}\n\t\t});\n\t}\n\tasync function listRoles() {\n\t\treturn transport.request(adminPath + \"/roles\", { method: \"GET\" });\n\t}\n\tasync function bootstrap() {\n\t\treturn transport.request(adminPath + \"/bootstrap\", { method: \"POST\" });\n\t}\n\treturn {\n\t\tlistUsers,\n\t\tlistUsersPaginated,\n\t\tgetUser,\n\t\tcreateUser,\n\t\tupdateUser,\n\t\tdeleteUser,\n\t\tresetPassword,\n\t\tlistRoles,\n\t\tbootstrap\n\t};\n}\n//#endregion\n//#region src/cron.ts\nfunction createCron(transport, options) {\n\tconst cronPath = options?.cronPath || \"/cron\";\n\tasync function listJobs() {\n\t\treturn transport.request(cronPath, { method: \"GET\" });\n\t}\n\tasync function getJob(jobId) {\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId), { method: \"GET\" });\n\t}\n\tasync function triggerJob(jobId) {\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId) + \"/trigger\", { method: \"POST\" });\n\t}\n\tasync function getJobLogs(jobId, options) {\n\t\tconst params = new URLSearchParams();\n\t\tif (options?.limit !== void 0) params.set(\"limit\", String(options.limit));\n\t\tconst qs = params.toString();\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId) + \"/logs\" + (qs ? \"?\" + qs : \"\"), { method: \"GET\" });\n\t}\n\tasync function toggleJob(jobId, enabled) {\n\t\treturn transport.request(cronPath + \"/\" + encodeURIComponent(jobId), {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: JSON.stringify({ enabled })\n\t\t});\n\t}\n\treturn {\n\t\tlistJobs,\n\t\tgetJob,\n\t\ttriggerJob,\n\t\tgetJobLogs,\n\t\ttoggleJob\n\t};\n}\n//#endregion\n//#region src/backups.ts\nfunction createBackups(transport, options) {\n\tconst backupsPath = options?.backupsPath || \"/admin/backups\";\n\tasync function list() {\n\t\treturn transport.request(backupsPath, { method: \"GET\" });\n\t}\n\t/**\n\t* Download a backup's bytes. Uses an authenticated fetch (not the JSON\n\t* transport) so the octet-stream response comes back as a Blob.\n\t*/\n\tasync function download(key) {\n\t\tconst token = await transport.resolveToken();\n\t\tconst url = `${transport.baseUrl}${transport.apiPath}${backupsPath}/download?key=${encodeURIComponent(key)}`;\n\t\tconst res = await fetch(url, {\n\t\t\tmethod: \"GET\",\n\t\t\theaders: token ? { Authorization: `Bearer ${token}` } : {}\n\t\t});\n\t\tif (!res.ok) throw new Error(`Failed to download backup (${res.status})`);\n\t\treturn res.blob();\n\t}\n\treturn {\n\t\tlist,\n\t\tdownload\n\t};\n}\n//#endregion\n//#region src/api-keys.ts\n/**\n* Creates a client for managing API keys via the admin routes.\n*\n* @param transport - The shared HTTP transport created by `createTransport`.\n* @param options - Optional overrides (e.g. a custom base path).\n*/\nfunction createApiKeys(transport, options) {\n\tconst apiKeysPath = options?.apiKeysPath || \"/admin/api-keys\";\n\t/** List all API keys (masked). */\n\tasync function listKeys() {\n\t\treturn transport.request(apiKeysPath, { method: \"GET\" });\n\t}\n\t/** Get a single API key by ID (masked). */\n\tasync function getKey(id) {\n\t\treturn transport.request(apiKeysPath + \"/\" + encodeURIComponent(id), { method: \"GET\" });\n\t}\n\t/** Create a new API key. The full secret is included in the response. */\n\tasync function createKey(data) {\n\t\treturn transport.request(apiKeysPath, {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\t/** Update an existing API key. */\n\tasync function updateKey(id, data) {\n\t\treturn transport.request(apiKeysPath + \"/\" + encodeURIComponent(id), {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: JSON.stringify(data)\n\t\t});\n\t}\n\t/** Revoke (soft-delete) an API key. */\n\tasync function revokeKey(id) {\n\t\treturn transport.request(apiKeysPath + \"/\" + encodeURIComponent(id), { method: \"DELETE\" });\n\t}\n\treturn {\n\t\tlistKeys,\n\t\tgetKey,\n\t\tcreateKey,\n\t\tupdateKey,\n\t\trevokeKey\n\t};\n}\n//#endregion\n//#region src/sdk_query_builder.ts\n/**\n* SDK Query Builder — returns flat rows (`FindResult<M>`) instead of\n* Entity-wrapped results (`FindResponse<M>`).\n*\n* @example\n* const { data } = await rebase.data.posts\n* .where(\"status\", \"==\", \"published\")\n* .orderBy(\"created_at\", \"desc\")\n* .limit(10)\n* .find();\n*\n* console.log(data[0].title); // flat access\n*/\nvar SDKQueryBuilder = class {\n\tcollection;\n\tparams = { where: {} };\n\tconstructor(collection) {\n\t\tthis.collection = collection;\n\t}\n\twhere(columnOrCondition, operator, value) {\n\t\tif (typeof columnOrCondition === \"object\" && columnOrCondition !== null && \"type\" in columnOrCondition) {\n\t\t\tthis.params.logical = columnOrCondition;\n\t\t\treturn this;\n\t\t}\n\t\tif (!this.params.where) this.params.where = {};\n\t\tconst column = columnOrCondition;\n\t\tconst condition = [operator, value];\n\t\tconst existing = this.params.where[column];\n\t\tif (existing === void 0) this.params.where[column] = condition;\n\t\telse if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) this.params.where[column].push(condition);\n\t\telse {\n\t\t\tlet firstCondition;\n\t\t\tif (Array.isArray(existing) && existing.length === 2 && typeof existing[0] === \"string\") firstCondition = existing;\n\t\t\telse firstCondition = [\"==\", existing];\n\t\t\tthis.params.where[column] = [firstCondition, condition];\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Order the results by a specific column.\n\t*/\n\torderBy(column, direction = \"asc\") {\n\t\tthis.params.orderBy = [column, direction];\n\t\treturn this;\n\t}\n\t/**\n\t* Limit the number of results returned.\n\t*/\n\tlimit(count) {\n\t\tthis.params.limit = count;\n\t\treturn this;\n\t}\n\t/**\n\t* Skip the first N results.\n\t*/\n\toffset(count) {\n\t\tthis.params.offset = count;\n\t\treturn this;\n\t}\n\t/**\n\t* Set a free-text search string if supported by the backend.\n\t*/\n\tsearch(searchString) {\n\t\tthis.params.searchString = searchString;\n\t\treturn this;\n\t}\n\t/**\n\t* Include related entities in the response.\n\t* Relations will be populated with full data instead of just IDs.\n\t*\n\t* @param relations - Relation names to include, or \"*\" for all.\n\t* @example\n\t* client.data.posts.include(\"tags\", \"author\").find()\n\t*/\n\tinclude(...relations) {\n\t\tthis.params.include = relations;\n\t\treturn this;\n\t}\n\t/**\n\t* Execute the find query and return the results as flat rows.\n\t*/\n\tasync find() {\n\t\treturn this.collection.find(this.params);\n\t}\n\t/**\n\t* Count the records matching this query.\n\t*/\n\tasync count() {\n\t\tif (!this.collection.count) throw new Error(\"count() is not supported by this collection client.\");\n\t\treturn this.collection.count(this.params);\n\t}\n\t/**\n\t* Listen to realtime updates matching this query.\n\t*/\n\tlisten(onUpdate, onError) {\n\t\tif (!this.collection.listen) throw new Error(\"Listen is only available when RebaseClient is configured with a websocketUrl, and not when it was created with realtime: false.\");\n\t\treturn this.collection.listen(this.params, onUpdate, onError);\n\t}\n};\n//#endregion\n//#region src/collection.ts\nfunction createCollectionClient(transport, slug, ws) {\n\tconst basePath = `/data/${slug}`;\n\tconst client = {\n\t\tasync find(params) {\n\t\t\tconst qs = buildQueryString(params);\n\t\t\tconst raw = await transport.request(basePath + qs, { method: \"GET\" });\n\t\t\treturn {\n\t\t\t\tdata: raw.data || [],\n\t\t\t\tmeta: raw.meta\n\t\t\t};\n\t\t},\n\t\titerate(params) {\n\t\t\treturn paginateFind((p) => client.find(p), params, slug);\n\t\t},\n\t\tfindAll(params) {\n\t\t\treturn collectAllPages((p) => client.find(p), params, slug);\n\t\t},\n\t\tasync findById(id) {\n\t\t\ttry {\n\t\t\t\tconst raw = await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, { method: \"GET\" });\n\t\t\t\tif (!raw) return void 0;\n\t\t\t\treturn raw;\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof RebaseApiError && err.status === 404) return;\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t},\n\t\tasync create(data, id, options) {\n\t\t\tconst body = { ...data };\n\t\t\tif (id !== void 0) body.id = id;\n\t\t\treturn await transport.request(basePath, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\t...options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}\n\t\t\t});\n\t\t},\n\t\tasync createMany(data, options) {\n\t\t\tif (!Array.isArray(data)) throw new TypeError(\"createMany expects an array of records.\");\n\t\t\tif (data.length === 0) return [];\n\t\t\treturn (await transport.request(`${basePath}/bulk`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\trows: data,\n\t\t\t\t\t...options?.upsert ? { upsert: true } : {}\n\t\t\t\t})\n\t\t\t})).data || [];\n\t\t},\n\t\tasync update(id, data) {\n\t\t\treturn await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, {\n\t\t\t\tmethod: \"PUT\",\n\t\t\t\tbody: JSON.stringify(data)\n\t\t\t});\n\t\t},\n\t\tasync delete(id) {\n\t\t\tawait transport.request(`${basePath}/${encodeURIComponent(String(id))}`, { method: \"DELETE\" });\n\t\t},\n\t\tasync count(params) {\n\t\t\tconst qs = buildQueryString({\n\t\t\t\t...params,\n\t\t\t\tlimit: void 0,\n\t\t\t\toffset: void 0,\n\t\t\t\tinclude: void 0\n\t\t\t});\n\t\t\treturn (await transport.request(basePath + \"/count\" + qs, { method: \"GET\" })).count ?? 0;\n\t\t},\n\t\tobserve(params, onResult, onError, options) {\n\t\t\tlet closed = false;\n\t\t\tconst emit = (result) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tonResult({\n\t\t\t\t\t...result,\n\t\t\t\t\tfromCache: false,\n\t\t\t\t\thasPendingWrites: false,\n\t\t\t\t\tpartial: false\n\t\t\t\t});\n\t\t\t};\n\t\t\tclient.find(params).then(emit).catch((error) => {\n\t\t\t\tif (!closed) onError?.(error);\n\t\t\t});\n\t\t\tconst live = options?.realtime !== false && client.listen ? client.listen(params, emit, onError) : void 0;\n\t\t\treturn () => {\n\t\t\t\tclosed = true;\n\t\t\t\tlive?.();\n\t\t\t};\n\t\t},\n\t\tobserveById(id, onResult, onError, options) {\n\t\t\tlet closed = false;\n\t\t\tconst emit = (row) => {\n\t\t\t\tif (closed) return;\n\t\t\t\tonResult(row, {\n\t\t\t\t\tfromCache: false,\n\t\t\t\t\thasPendingWrites: false\n\t\t\t\t});\n\t\t\t};\n\t\t\tclient.findById(id).then(emit).catch((error) => {\n\t\t\t\tif (!closed) onError?.(error);\n\t\t\t});\n\t\t\tconst live = options?.realtime !== false && client.listenById ? client.listenById(id, emit, onError) : void 0;\n\t\t\treturn () => {\n\t\t\t\tclosed = true;\n\t\t\t\tlive?.();\n\t\t\t};\n\t\t},\n\t\twhere(columnOrCondition, operator, value) {\n\t\t\tconst builder = new SDKQueryBuilder(client);\n\t\t\tif (typeof columnOrCondition === \"object\") return builder.where(columnOrCondition);\n\t\t\treturn builder.where(columnOrCondition, operator, value);\n\t\t},\n\t\torderBy(column, direction) {\n\t\t\treturn new SDKQueryBuilder(client).orderBy(column, direction);\n\t\t},\n\t\tlimit(count) {\n\t\t\treturn new SDKQueryBuilder(client).limit(count);\n\t\t},\n\t\toffset(count) {\n\t\t\treturn new SDKQueryBuilder(client).offset(count);\n\t\t},\n\t\tsearch(searchString) {\n\t\t\treturn new SDKQueryBuilder(client).search(searchString);\n\t\t},\n\t\tinclude(...relations) {\n\t\t\treturn new SDKQueryBuilder(client).include(...relations);\n\t\t}\n\t};\n\tif (ws) {\n\t\tclient.listen = (params, onUpdate, onError) => {\n\t\t\tlet active = true;\n\t\t\tlet lastUpdateId = 0;\n\t\t\tconst unsub = ws.listenCollection({\n\t\t\t\tpath: slug,\n\t\t\t\tfilter: params?.where,\n\t\t\t\tlimit: params?.limit,\n\t\t\t\tstartAfter: params?.offset ? String(params.offset) : void 0,\n\t\t\t\torderBy: params?.orderBy?.[0],\n\t\t\t\torder: params?.orderBy?.[1],\n\t\t\t\tsearchString: params?.searchString\n\t\t\t}, (incomingRows) => {\n\t\t\t\tconst currentUpdateId = ++lastUpdateId;\n\t\t\t\tconst requestedLimit = params?.limit || 20;\n\t\t\t\tconst offset = params?.offset || 0;\n\t\t\t\tconst rows = incomingRows;\n\t\t\t\tconst heuristicTotal = rows.length;\n\t\t\t\tconst heuristicHasMore = rows.length >= requestedLimit;\n\t\t\t\tif (client.count) client.count(params).then((total) => {\n\t\t\t\t\tif (active && currentUpdateId === lastUpdateId) onUpdate({\n\t\t\t\t\t\tdata: rows,\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\ttotal,\n\t\t\t\t\t\t\tlimit: requestedLimit,\n\t\t\t\t\t\t\toffset,\n\t\t\t\t\t\t\thasMore: offset + rows.length < total\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}).catch(() => {\n\t\t\t\t\tif (active && currentUpdateId === lastUpdateId) onUpdate({\n\t\t\t\t\t\tdata: rows,\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\ttotal: heuristicTotal,\n\t\t\t\t\t\t\tlimit: requestedLimit,\n\t\t\t\t\t\t\toffset,\n\t\t\t\t\t\t\thasMore: heuristicHasMore\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\telse onUpdate({\n\t\t\t\t\tdata: rows,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\ttotal: heuristicTotal,\n\t\t\t\t\t\tlimit: requestedLimit,\n\t\t\t\t\t\toffset,\n\t\t\t\t\t\thasMore: heuristicHasMore\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}, onError);\n\t\t\treturn () => {\n\t\t\t\tactive = false;\n\t\t\t\tunsub();\n\t\t\t};\n\t\t};\n\t\tclient.listenById = (id, onUpdate, onError) => {\n\t\t\treturn ws.listenOne({\n\t\t\t\tpath: slug,\n\t\t\t\tid: String(id)\n\t\t\t}, (row) => {\n\t\t\t\tif (row) onUpdate(row);\n\t\t\t\telse onUpdate(void 0);\n\t\t\t}, onError);\n\t\t};\n\t}\n\treturn client;\n}\n//#endregion\n//#region src/functions.ts\n/**\n* Create a `FunctionsClient` backed by the given transport.\n*\n* The transport already handles:\n* - Base URL resolution\n* - JWT injection via `Authorization: Bearer`\n* - 401 retry / `onUnauthorized` flow\n* - Consistent error throwing via `RebaseApiError`\n*\n* @internal\n*/\nfunction createFunctionsClient(transport) {\n\treturn { async invoke(name, payload, options) {\n\t\tconst method = options?.method ?? \"POST\";\n\t\tconst rawPath = options?.path;\n\t\tconst subPath = rawPath ? /^[?#]/.test(rawPath) ? rawPath : `/${rawPath.replace(/^\\//, \"\")}` : \"\";\n\t\tconst routePath = `/functions/${encodeURIComponent(name)}${subPath}`;\n\t\tconst init = { method };\n\t\tif (payload !== void 0 && method !== \"GET\") init.body = JSON.stringify(payload);\n\t\tif (options?.headers) init.headers = options.headers;\n\t\treturn transport.request(routePath, init);\n\t} };\n}\n//#endregion\n//#region src/storage.ts\n/**\n* Create a StorageSource that talks to the Rebase backend REST API.\n*\n* @param transport - HTTP transport instance\n* @param storageId - Optional storage-source key for multi-backend routing.\n* When set, it is forwarded to the server so the correct\n* `StorageController` is resolved from the registry.\n*/\nfunction createStorage(transport, storageId) {\n\tconst urlsCache = /* @__PURE__ */ new Map();\n\t/**\n\t* Base for URLs the *browser* will fetch on its own (file downloads,\n\t* previews). API requests keep going to `baseUrl`; see\n\t* {@link RebaseClientConfig.storageUrlOrigin} for why these can differ.\n\t*/\n\tconst fileUrlBase = () => `${transport.storageUrlOrigin ?? transport.baseUrl}${transport.apiPath}`;\n\t/** Append ?storageId=... to a path when multi-backend routing is active. */\n\tconst withStorageId = (path) => {\n\t\tif (!storageId) return path;\n\t\treturn `${path}${path.includes(\"?\") ? \"&\" : \"?\"}storageId=${encodeURIComponent(storageId)}`;\n\t};\n\tasync function putObject({ file, key, metadata, bucket, public: isPublic }) {\n\t\tconst formData = new FormData();\n\t\tformData.append(\"file\", file);\n\t\tlet effectiveKey = key;\n\t\tif (isPublic && effectiveKey && !isPublicStoragePath(effectiveKey)) effectiveKey = `${PUBLIC_STORAGE_PREFIX}${effectiveKey.replace(/^\\/+/, \"\")}`;\n\t\tif (effectiveKey) formData.append(\"key\", effectiveKey);\n\t\tif (bucket) formData.append(\"bucket\", bucket);\n\t\tif (storageId) formData.append(\"storageId\", storageId);\n\t\tif (metadata) {\n\t\t\tfor (const [key, value] of Object.entries(metadata)) if (value !== void 0 && value !== null) formData.append(`metadata_${key}`, typeof value === \"string\" ? value : JSON.stringify(value));\n\t\t}\n\t\treturn (await transport.request(withStorageId(\"/storage/upload\"), {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: formData,\n\t\t\theaders: {}\n\t\t})).data;\n\t}\n\tasync function getSignedUrl(keyOrUrl, bucket) {\n\t\tconst cacheKey = bucket ? `${bucket}/${keyOrUrl}` : keyOrUrl;\n\t\tconst cachedEntry = urlsCache.get(cacheKey);\n\t\tif (cachedEntry) {\n\t\t\tif (!cachedEntry.expiresAt || cachedEntry.expiresAt > Date.now()) return cachedEntry.config;\n\t\t\turlsCache.delete(cacheKey);\n\t\t}\n\t\tlet filePath = keyOrUrl;\n\t\tif (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\") || filePath.startsWith(\"gs://\"))) filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n\t\tif (bucket && filePath && !filePath.startsWith(bucket)) filePath = `${bucket}/${filePath}`;\n\t\tif (!filePath || filePath.trim() === \"\" || filePath === \"/\") return {\n\t\t\turl: null,\n\t\t\tfileNotFound: true\n\t\t};\n\t\tif (isPublicStoragePath(filePath)) {\n\t\t\tconst publicConfig = { url: withStorageId(`${fileUrlBase()}/storage/file/${filePath}`) };\n\t\t\turlsCache.set(cacheKey, { config: publicConfig });\n\t\t\treturn publicConfig;\n\t\t}\n\t\ttry {\n\t\t\tconst result = await transport.request(withStorageId(`/storage/metadata/${filePath}`));\n\t\t\tif (result.data.public) {\n\t\t\t\tconst publicConfig = {\n\t\t\t\t\turl: withStorageId(`${fileUrlBase()}/storage/file/${filePath}`),\n\t\t\t\t\tmetadata: result.data\n\t\t\t\t};\n\t\t\t\turlsCache.set(cacheKey, { config: publicConfig });\n\t\t\t\treturn publicConfig;\n\t\t\t}\n\t\t\tconst scopedToken = result.data.token;\n\t\t\tconst tokenQuery = scopedToken ? `?token=${scopedToken}` : \"\";\n\t\t\tconst downloadConfig = {\n\t\t\t\turl: withStorageId(`${fileUrlBase()}/storage/file/${filePath}${tokenQuery}`),\n\t\t\t\tmetadata: result.data\n\t\t\t};\n\t\t\tconst expiresAt = result.data.tokenExpiresIn ? Date.now() + (result.data.tokenExpiresIn - 10) * 1e3 : void 0;\n\t\t\turlsCache.set(cacheKey, {\n\t\t\t\tconfig: downloadConfig,\n\t\t\t\texpiresAt\n\t\t\t});\n\t\t\treturn downloadConfig;\n\t\t} catch (e) {\n\t\t\tif (e instanceof Error && \"status\" in e && e.status === 404) return {\n\t\t\t\turl: null,\n\t\t\t\tfileNotFound: true\n\t\t\t};\n\t\t\tthrow e;\n\t\t}\n\t}\n\tasync function getObject(key, bucket) {\n\t\tconst downloadConfig = await getSignedUrl(key, bucket);\n\t\tif (downloadConfig.fileNotFound || !downloadConfig.url) return null;\n\t\tconst response = await transport.fetchFn(downloadConfig.url, { headers: {} });\n\t\tif (response.status === 404) return null;\n\t\tif (!response.ok) throw new Error(\"Failed to get file\");\n\t\tconst blob = await response.blob();\n\t\tconst fileName = (bucket ? `${bucket}/${key}` : key).split(\"/\").pop() || \"file\";\n\t\treturn new File([blob], fileName, { type: blob.type });\n\t}\n\tasync function deleteObject(key, bucket) {\n\t\tlet filePath = key;\n\t\tif (filePath && (filePath.startsWith(\"local://\") || filePath.startsWith(\"s3://\") || filePath.startsWith(\"gs://\"))) filePath = filePath.substring(filePath.indexOf(\"://\") + 3);\n\t\tif (bucket && filePath && !filePath.startsWith(bucket)) filePath = `${bucket}/${filePath}`;\n\t\tif (!filePath || filePath.trim() === \"\" || filePath === \"/\") return;\n\t\ttry {\n\t\t\tawait transport.request(withStorageId(`/storage/file/${filePath}`), { method: \"DELETE\" });\n\t\t} catch (e) {\n\t\t\tif (!(e instanceof Error && \"status\" in e && e.status === 404)) throw e;\n\t\t}\n\t\turlsCache.delete(bucket ? `${bucket}/${key}` : key);\n\t}\n\tasync function listObjects(prefix, options) {\n\t\tconst params = new URLSearchParams();\n\t\tif (prefix) params.set(\"prefix\", prefix);\n\t\tif (options?.bucket) params.set(\"bucket\", options.bucket);\n\t\tif (options?.maxResults) params.set(\"maxResults\", String(options.maxResults));\n\t\tif (options?.pageToken) params.set(\"pageToken\", options.pageToken);\n\t\tif (storageId) params.set(\"storageId\", storageId);\n\t\treturn (await transport.request(`/storage/list?${params.toString()}`)).data;\n\t}\n\treturn {\n\t\tputObject,\n\t\tgetSignedUrl,\n\t\tgetObject,\n\t\tdeleteObject,\n\t\tlistObjects\n\t};\n}\n//#endregion\n//#region src/storage-registry.ts\n/**\n* Default implementation of the client-side `StorageSourceRegistry`.\n*/\nvar ClientStorageSourceRegistry = class ClientStorageSourceRegistry {\n\tsources = /* @__PURE__ */ new Map();\n\t/**\n\t* Register a storage source.\n\t* @param key - Unique key matching a `StorageSourceDefinition.key`\n\t* @param source - The `StorageSource` instance\n\t*/\n\tregister(key, source) {\n\t\tthis.sources.set(key, source);\n\t}\n\tgetDefault() {\n\t\tconst source = this.sources.get(DEFAULT_STORAGE_SOURCE_KEY);\n\t\tif (!source) throw new Error(`[StorageSourceRegistry] No default storage source registered. Register one with key \"${DEFAULT_STORAGE_SOURCE_KEY}\".`);\n\t\treturn source;\n\t}\n\tget(key) {\n\t\tif (key === void 0 || key === null) return this.sources.get(DEFAULT_STORAGE_SOURCE_KEY);\n\t\treturn this.sources.get(key);\n\t}\n\tgetOrDefault(key) {\n\t\tif (key === void 0 || key === null) return this.getDefault();\n\t\tconst source = this.sources.get(key);\n\t\tif (source) return source;\n\t\tconsole.warn(`[StorageSourceRegistry] Storage source \"${key}\" not found, falling back to \"${DEFAULT_STORAGE_SOURCE_KEY}\".`);\n\t\treturn this.getDefault();\n\t}\n\thas(key) {\n\t\treturn this.sources.has(key);\n\t}\n\tlist() {\n\t\treturn Array.from(this.sources.keys());\n\t}\n\t/**\n\t* Build a registry from `StorageSourceDefinition[]` and an HTTP transport.\n\t*\n\t* - Sources with `transport: \"server\"` are auto-wired via `createStorage(transport, key)`.\n\t* - Sources with `transport: \"direct\"` are **not** auto-wired — they must\n\t* be registered manually after this call (e.g. via a Firebase hook).\n\t*\n\t* @param definitions - Array of storage source definitions\n\t* @param transport - HTTP transport for server-backed sources\n\t*/\n\tstatic fromDefinitions(definitions, transport) {\n\t\tconst registry = new ClientStorageSourceRegistry();\n\t\tfor (const def of definitions) if (def.transport === \"server\") {\n\t\t\tconst source = createStorage(transport, def.key === DEFAULT_STORAGE_SOURCE_KEY ? void 0 : def.key);\n\t\t\tregistry.register(def.key, source);\n\t\t}\n\t\treturn registry;\n\t}\n};\n//#endregion\n//#region src/websocket.ts\n/**\n* Extract error message and code from a WebSocket message payload.\n* Handles both `{ error: string }` and `{ error: { message, code } }` shapes.\n*/\nfunction extractMessageError(message) {\n\tconst payload = message.payload;\n\tconst errPayload = payload?.error;\n\tconst errorMessage = typeof errPayload === \"object\" ? errPayload.message : payload?.message || (typeof errPayload === \"string\" ? errPayload : void 0) || message.error || \"Unknown error\";\n\tconst errorCode = typeof errPayload === \"object\" ? errPayload.code : payload?.code;\n\treturn {\n\t\terrorMessage: typeof errorMessage === \"string\" ? errorMessage : errorMessage == null ? \"Unknown error\" : JSON.stringify(errorMessage),\n\t\terrorCode\n\t};\n}\n/**\n* Broadcast and presence frames.\n*\n* Fire-and-forget (the server sends no response envelope), and exempt from the\n* client-side auth gate — a public channel is usable without an account.\n*/\nvar CHANNEL_MESSAGE_TYPES = /* @__PURE__ */ new Set([\n\t\"join_channel\",\n\t\"leave_channel\",\n\t\"broadcast\",\n\t\"presence_track\",\n\t\"presence_untrack\",\n\t\"presence_state\",\n\t\"channel_history\"\n]);\n/**\n* Low-level realtime WebSocket client.\n*\n* @internal Not a stable app-facing API. `createRebaseClient()` constructs and\n* manages this internally (exposed as `client.ws`, typed by the minimal\n* `RebaseWebSocket` contract in `@rebasepro/types`). It is re-exported from the\n* package root only because the `@rebasepro/client-postgres` driver\n* instantiates it directly; its surface may change without a major bump.\n*/\nvar RebaseWebSocketClient = class {\n\twebsocketUrl;\n\tws = null;\n\tgetAuthToken;\n\tsubscriptions = /* @__PURE__ */ new Map();\n\tlisteners = /* @__PURE__ */ new Map();\n\t/** Channel-name → handlers, for broadcast and presence frames. */\n\tchannelHandlers = /* @__PURE__ */ new Map();\n\t/** Set by `close()`. Blocks any later operation from silently redialling. */\n\tclosedByCaller = false;\n\t/**\n\t* Set when the backoff budget ran out, cleared by anything that earns a\n\t* fresh one.\n\t*\n\t* Unlike {@link closedByCaller} this is not final — nobody *asked* for the\n\t* socket to stay down. Five attempts with exponential backoff is about a\n\t* minute, which a laptop lid, a wifi handover or a backend rollout all\n\t* exceed routinely; treating that as permanent meant realtime silently\n\t* stopped for the rest of the page's life, with a reload the only cure.\n\t*/\n\tgaveUp = false;\n\t/**\n\t* Whether a socket exists at all (open or still opening).\n\t*\n\t* Lets callers distinguish \"authenticate the live socket\" from \"there is\n\t* nothing to authenticate yet\", without that question forcing a dial.\n\t*/\n\tget hasSocket() {\n\t\treturn this.ws !== null;\n\t}\n\t/** So the \"no WebSocket in this environment\" warning is said once, not per call. */\n\twarnedNoWebSocket = false;\n\t/** Subscribe to broadcast/presence frames for one channel. */\n\tonChannelMessage(channel, handler) {\n\t\tif (!this.channelHandlers.has(channel)) this.channelHandlers.set(channel, /* @__PURE__ */ new Set());\n\t\tthis.channelHandlers.get(channel).add(handler);\n\t\treturn () => {\n\t\t\tconst handlers = this.channelHandlers.get(channel);\n\t\t\tif (!handlers) return;\n\t\t\thandlers.delete(handler);\n\t\t\tif (handlers.size === 0) this.channelHandlers.delete(channel);\n\t\t};\n\t}\n\t/** Notified after the socket comes back, so channels can re-join. */\n\tonReconnect(handler) {\n\t\treturn this.on(\"reconnect\", handler);\n\t}\n\ton(event, cb) {\n\t\tif (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());\n\t\tthis.listeners.get(event).add(cb);\n\t\treturn () => this.listeners.get(event).delete(cb);\n\t}\n\temit(event, ...args) {\n\t\tif (this.listeners.has(event)) this.listeners.get(event).forEach((cb) => cb(...args));\n\t}\n\tcollectionSubscriptions = /* @__PURE__ */ new Map();\n\tsingleSubscriptions = /* @__PURE__ */ new Map();\n\tbackendToCollectionKey = /* @__PURE__ */ new Map();\n\tbackendToEntityKey = /* @__PURE__ */ new Map();\n\tpendingRequests = /* @__PURE__ */ new Map();\n\treconnectAttempts = 0;\n\tmaxReconnectAttempts = 5;\n\tisConnected = false;\n\tmessageQueue = [];\n\trequestTimeoutMs = 3e4;\n\tsubscriptionTimeoutMs = 3e4;\n\treconnectTimeout = null;\n\tisAuthenticated = false;\n\tauthPromise = null;\n\tWebSocketConstructor;\n\tonUnauthorized;\n\trefreshInProgress = null;\n\tconstructor(config) {\n\t\tthis.websocketUrl = config.websocketUrl;\n\t\tthis.getAuthToken = config.getAuthToken;\n\t\tthis.onUnauthorized = config.onUnauthorized;\n\t\tthis.WebSocketConstructor = config.WebSocket || (typeof WebSocket !== \"undefined\" ? WebSocket : void 0);\n\t}\n\t/**\n\t* Open the socket if it is not open (or opening) already.\n\t*\n\t* Idempotent, synchronous, and safe to call on every operation that needs a\n\t* live socket — `initWebSocket` already no-ops on an open socket and is\n\t* re-entrant, since the reconnect path has always called it.\n\t*/\n\tensureConnected() {\n\t\tif (this.closedByCaller) return;\n\t\tif (!this.WebSocketConstructor) {\n\t\t\tif (!this.warnedNoWebSocket) {\n\t\t\t\tthis.warnedNoWebSocket = true;\n\t\t\t\tconsole.warn(\"WebSocket is not defined in this environment. Realtime subscriptions will not work unless you provide a WebSocket implementation in the config.\");\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tthis.installOnlineListener();\n\t\tif (this.ws || this.reconnectTimeout) return;\n\t\tif (this.gaveUp) {\n\t\t\tthis.gaveUp = false;\n\t\t\tthis.reconnectAttempts = 0;\n\t\t}\n\t\tthis.initWebSocket();\n\t}\n\t/**\n\t* The browser says the network is back — the usual reason the budget ran\n\t* out in the first place. Registered lazily so a Node client, or a page\n\t* that never subscribes, adds no listener.\n\t*/\n\tinstallOnlineListener() {\n\t\tif (this.onlineListener || typeof window === \"undefined\" || typeof window.addEventListener !== \"function\") return;\n\t\tthis.onlineListener = () => {\n\t\t\tif (this.closedByCaller || !this.gaveUp) return;\n\t\t\tconsole.debug(\"Network is back — retrying the realtime connection\");\n\t\t\tthis.ensureConnected();\n\t\t};\n\t\twindow.addEventListener(\"online\", this.onlineListener);\n\t}\n\tonlineListener = null;\n\t/**\n\t* Authenticate the WebSocket connection\n\t*/\n\tasync authenticate(token) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst requestId = `auth_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\tconst timeout = setTimeout(() => {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\treject(/* @__PURE__ */ new Error(\"Authentication timeout\"));\n\t\t\t}, 3e4);\n\t\t\tthis.pendingRequests.set(requestId, {\n\t\t\t\tresolve: () => {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\tthis.isAuthenticated = true;\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tclearTimeout(timeout);\n\t\t\t\t\treject(error);\n\t\t\t\t}\n\t\t\t});\n\t\t\tconst message = {\n\t\t\t\ttype: \"AUTHENTICATE\",\n\t\t\t\trequestId,\n\t\t\t\tpayload: { token }\n\t\t\t};\n\t\t\tif (!this.isConnected || !this.ws) this.messageQueue.unshift(message);\n\t\t\telse this.ws.send(JSON.stringify(message));\n\t\t});\n\t}\n\t/**\n\t* Set the auth token getter function\n\t*/\n\tsetAuthTokenGetter(getAuthToken) {\n\t\tthis.getAuthToken = getAuthToken;\n\t\tif (this.isConnected && !this.isAuthenticated && !this.authPromise) {\n\t\t\tconsole.debug(\"WebSocket auto-authenticating after token getter set\");\n\t\t\tthis.getAuthToken().then((token) => {\n\t\t\t\tif (!this.ws) return;\n\t\t\t\tif (token) this.authenticate(token).catch((e) => {\n\t\t\t\t\tif (this.ws) console.debug(\"WebSocket auto-auth skipped:\", e?.message || e);\n\t\t\t\t});\n\t\t\t}).catch((e) => {\n\t\t\t\tif (this.ws) console.debug(\"WebSocket auto-auth skipped:\", e?.message || e);\n\t\t\t});\n\t\t}\n\t}\n\t/**\n\t* Drop the socket.\n\t*\n\t* `permanent` distinguishes the two callers. Signing out drops the socket\n\t* but the client stays usable — a later subscribe should reconnect\n\t* anonymously. `client.close()` is the caller saying they are done, and\n\t* must not be undone by a stray queued frame.\n\t*/\n\tdisconnect(permanent = false) {\n\t\tif (permanent) this.closedByCaller = true;\n\t\tif (permanent && this.onlineListener && typeof window !== \"undefined\") {\n\t\t\twindow.removeEventListener(\"online\", this.onlineListener);\n\t\t\tthis.onlineListener = null;\n\t\t}\n\t\tthis.isAuthenticated = false;\n\t\tthis.authPromise = null;\n\t\tif (this.reconnectTimeout) {\n\t\t\tclearTimeout(this.reconnectTimeout);\n\t\t\tthis.reconnectTimeout = null;\n\t\t}\n\t\tif (this.ws) {\n\t\t\tthis.ws.onclose = null;\n\t\t\tthis.ws.onerror = null;\n\t\t\tthis.ws.onopen = null;\n\t\t\tthis.ws.onmessage = null;\n\t\t\tthis.ws.close();\n\t\t\tthis.ws = null;\n\t\t}\n\t}\n\tinitWebSocket() {\n\t\tif (!this.WebSocketConstructor) return;\n\t\tif (this.ws?.readyState === this.WebSocketConstructor.OPEN) return;\n\t\tif (this.ws) {\n\t\t\tthis.ws.onclose = null;\n\t\t\tthis.ws.close();\n\t\t\tthis.ws = null;\n\t\t}\n\t\ttry {\n\t\t\tconst socket = new this.WebSocketConstructor(this.websocketUrl);\n\t\t\tthis.ws = socket;\n\t\t\tthis.ws.onopen = async () => {\n\t\t\t\tconsole.debug(\"Connected to PostgreSQL backend\");\n\t\t\t\tconst wasReconnect = this.reconnectAttempts > 0;\n\t\t\t\tthis.isConnected = true;\n\t\t\t\tthis.reconnectAttempts = 0;\n\t\t\t\tif (this.getAuthToken && !this.isAuthenticated) try {\n\t\t\t\t\tconst token = await this.getAuthToken();\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tawait this.authenticate(token);\n\t\t\t\t\t\tconsole.debug(\"WebSocket auto-authenticated\");\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.debug(\"WebSocket connected without auth:\", error?.message || error);\n\t\t\t\t}\n\t\t\t\tthis.emit(wasReconnect ? \"reconnect\" : \"connect\");\n\t\t\t\tthis.processMessageQueue();\n\t\t\t\tif (wasReconnect) this.resubscribeAll();\n\t\t\t\tthis.armPendingSubscribeWatchdogs();\n\t\t\t};\n\t\t\tthis.ws.onmessage = (event) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst message = JSON.parse(event.data, rebaseReviver);\n\t\t\t\t\tthis.handleWebSocketMessage(message);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(\"Error parsing WebSocket message:\", error);\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.ws.onclose = () => {\n\t\t\t\tconsole.debug(\"Disconnected from PostgreSQL backend\");\n\t\t\t\tif (this.ws === socket) this.ws = null;\n\t\t\t\tthis.isConnected = false;\n\t\t\t\tthis.isAuthenticated = false;\n\t\t\t\tthis.authPromise = null;\n\t\t\t\tthis.suspendSubscribeWatchdogs();\n\t\t\t\tthis.emit(\"disconnect\");\n\t\t\t\tfor (const [reqId, request] of this.pendingRequests.entries()) {\n\t\t\t\t\tif (reqId.startsWith(\"auth_\")) request.reject(/* @__PURE__ */ new Error(\"Connection closed during authentication\"));\n\t\t\t\t\telse if (request.message) {\n\t\t\t\t\t\trequest.message._queuedResolve = request.resolve;\n\t\t\t\t\t\trequest.message._queuedReject = request.reject;\n\t\t\t\t\t\tthis.messageQueue.push(request.message);\n\t\t\t\t\t} else request.reject(new RebaseApiError$1(\"Connection closed\"));\n\t\t\t\t\tthis.pendingRequests.delete(reqId);\n\t\t\t\t}\n\t\t\t\tthis.attemptReconnect();\n\t\t\t};\n\t\t\tthis.ws.onerror = (error) => {\n\t\t\t\tconsole.error(\"WebSocket error:\", error);\n\t\t\t\tthis.isConnected = false;\n\t\t\t\tthis.emit(\"error\", error);\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Failed to initialize WebSocket:\", error);\n\t\t\tthis.attemptReconnect();\n\t\t}\n\t}\n\tprocessMessageQueue() {\n\t\twhile (this.messageQueue.length > 0 && this.isConnected) {\n\t\t\tconst message = this.messageQueue.shift();\n\t\t\tif (message) this.sendMessage(message);\n\t\t}\n\t}\n\tattemptReconnect() {\n\t\tif (this.reconnectAttempts >= this.maxReconnectAttempts) {\n\t\t\tconsole.error(\"Max reconnection attempts reached\");\n\t\t\tthis.gaveUp = true;\n\t\t\tthis.failAllPendingSubscriptions(new RebaseApiError$1(\"Connection lost\", { code: \"CONNECTION_LOST\" }));\n\t\t\treturn;\n\t\t}\n\t\tthis.reconnectAttempts++;\n\t\tconst delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);\n\t\tconsole.debug(`Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts})`);\n\t\tif (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);\n\t\tthis.reconnectTimeout = setTimeout(() => {\n\t\t\tthis.reconnectTimeout = null;\n\t\t\tthis.initWebSocket();\n\t\t}, delay);\n\t}\n\tisAuthError(message) {\n\t\tif (message.type === \"AUTH_ERROR\") return true;\n\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\tif (errorCode === \"UNAUTHORIZED\" || errorCode === \"JWT_EXPIRED\" || errorCode === \"AUTH_ERROR\") return true;\n\t\tconst lowerMessage = errorMessage.toLowerCase();\n\t\treturn lowerMessage.includes(\"unauthorized\") || lowerMessage.includes(\"token expired\") || lowerMessage.includes(\"token is expired\") || lowerMessage.includes(\"invalid token\") || lowerMessage.includes(\"session expired\") || lowerMessage.includes(\"auth error\");\n\t}\n\tasync handleAuthFailure() {\n\t\tif (this.refreshInProgress) return this.refreshInProgress;\n\t\tthis.refreshInProgress = (async () => {\n\t\t\tthis.isAuthenticated = false;\n\t\t\tthis.authPromise = null;\n\t\t\tif (this.onUnauthorized) try {\n\t\t\t\tif (await this.onUnauthorized() && this.getAuthToken) {\n\t\t\t\t\tconst token = await this.getAuthToken();\n\t\t\t\t\tif (token) {\n\t\t\t\t\t\tawait this.authenticate(token);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"WebSocket auth refresh failed:\", error);\n\t\t\t}\n\t\t\treturn false;\n\t\t})();\n\t\ttry {\n\t\t\treturn await this.refreshInProgress;\n\t\t} finally {\n\t\t\tthis.refreshInProgress = null;\n\t\t}\n\t}\n\t/**\n\t* Shared logic for re-subscribing a collection or row subscription\n\t* after an auth error is resolved by refreshing credentials.\n\t*/\n\tresubscribeAfterAuthRefresh(message, subscription, subscriptionKey, idPrefix, backendKeyMap, messageType) {\n\t\tthis.handleAuthFailure().then((refreshed) => {\n\t\t\tif (refreshed) {\n\t\t\t\tconst oldBackendId = subscription.backendSubscriptionId;\n\t\t\t\tconst newBackendId = `${idPrefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\t\tsubscription.backendSubscriptionId = newBackendId;\n\t\t\t\tbackendKeyMap.delete(oldBackendId);\n\t\t\t\tbackendKeyMap.set(newBackendId, subscriptionKey);\n\t\t\t\tif (messageType === \"subscribe_collection\") this.sendCollectionSubscribe(subscriptionKey);\n\t\t\t\telse this.sendEntitySubscribe(subscriptionKey);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\tconst error = new RebaseApiError$1(errorMessage, { code: errorCode });\n\t\t\tif (messageType === \"subscribe_collection\") this.failCollectionSubscription(subscriptionKey, error);\n\t\t\telse this.failEntitySubscription(subscriptionKey, error);\n\t\t}).catch((err) => {\n\t\t\tconst error = err instanceof Error ? err : new Error(String(err));\n\t\t\tif (messageType === \"subscribe_collection\") this.failCollectionSubscription(subscriptionKey, error);\n\t\t\telse this.failEntitySubscription(subscriptionKey, error);\n\t\t});\n\t}\n\thandleWebSocketMessage(message) {\n\t\tconst { type, requestId, subscriptionId } = message;\n\t\tif (requestId && this.pendingRequests.has(requestId)) {\n\t\t\tconst pendingReq = this.pendingRequests.get(requestId);\n\t\t\tif (type === \"ERROR\" || type === \"AUTH_ERROR\" || message.error) if (this.isAuthError(message)) {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\tthis.handleAuthFailure().then((refreshed) => {\n\t\t\t\t\tif (refreshed && pendingReq.message) this.doSendMessage(pendingReq.message, pendingReq.resolve, pendingReq.reject).catch(pendingReq.reject);\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\t\tpendingReq.reject(new RebaseApiError$1(errorMessage, { code: errorCode }));\n\t\t\t\t\t}\n\t\t\t\t}).catch((err) => {\n\t\t\t\t\tpendingReq.reject(err);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\tpendingReq.reject(new RebaseApiError$1(errorMessage, { code: errorCode }));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\tpendingReq.resolve(message.payload || message);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (typeof message.channel === \"string\" && (type === \"broadcast\" || type === \"presence_state\" || type === \"presence_diff\" || type === \"channel_history\")) {\n\t\t\tconst handlers = this.channelHandlers.get(message.channel);\n\t\t\tif (handlers) for (const handler of [...handlers]) try {\n\t\t\t\thandler(message);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Error in channel handler:\", error);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (subscriptionId && type === \"collection_update\") {\n\t\t\tconst subscriptionKey = this.backendToCollectionKey.get(subscriptionId);\n\t\t\tif (subscriptionKey) {\n\t\t\t\tconst collectionSub = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\t\tif (collectionSub) {\n\t\t\t\t\tconst incomingRows = message.rows || [];\n\t\t\t\t\tconst updatePks = message.pks;\n\t\t\t\t\tif (updatePks) collectionSub.pks = updatePks;\n\t\t\t\t\tconst rows = this.mergeRows(collectionSub.latestData, incomingRows, collectionSub.pks);\n\t\t\t\t\tcollectionSub.latestData = rows;\n\t\t\t\t\tcollectionSub.lastUpdated = Date.now();\n\t\t\t\t\tcollectionSub.isInitialDataReceived = true;\n\t\t\t\t\tif (collectionSub.subscribeTimeout) clearTimeout(collectionSub.subscribeTimeout);\n\t\t\t\t\tcollectionSub.subscribeTimeout = void 0;\n\t\t\t\t\tcollectionSub.subscribeInFlight = false;\n\t\t\t\t\tcollectionSub.callbacks.forEach((callback) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcallback.onUpdate(rows);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Error in collection subscription callback:\", error);\n\t\t\t\t\t\t\tif (callback.onError) callback.onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && type === \"collection_patch\") {\n\t\t\tconst subscriptionKey = this.backendToCollectionKey.get(subscriptionId);\n\t\t\tif (subscriptionKey) {\n\t\t\t\tconst collectionSub = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\t\tif (collectionSub && collectionSub.isInitialDataReceived && collectionSub.latestData) {\n\t\t\t\t\tconst patchWireEntity = message.row ?? null;\n\t\t\t\t\tconst patchMessage = message;\n\t\t\t\t\tconst patchEntityId = patchMessage.id;\n\t\t\t\t\tif (patchMessage.pks) collectionSub.pks = patchMessage.pks;\n\t\t\t\t\tconst patchRow = patchWireEntity ? patchWireEntity : null;\n\t\t\t\t\tlet updated;\n\t\t\t\t\tif (patchRow === null) updated = collectionSub.latestData.filter((e) => this.rowAddress(e, collectionSub.pks) !== String(patchEntityId));\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst idx = collectionSub.latestData.findIndex((e) => this.rowAddress(e, collectionSub.pks) === String(patchEntityId));\n\t\t\t\t\t\tif (idx >= 0) {\n\t\t\t\t\t\t\tupdated = [...collectionSub.latestData];\n\t\t\t\t\t\t\tupdated[idx] = patchRow;\n\t\t\t\t\t\t} else updated = [patchRow, ...collectionSub.latestData];\n\t\t\t\t\t}\n\t\t\t\t\tcollectionSub.latestData = updated;\n\t\t\t\t\tcollectionSub.lastUpdated = Date.now();\n\t\t\t\t\tcollectionSub.callbacks.forEach((callback) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcallback.onUpdate(updated);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Error in collection patch callback:\", error);\n\t\t\t\t\t\t\tif (callback.onError) callback.onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && type === \"single_update\") {\n\t\t\tconst subscriptionKey = this.backendToEntityKey.get(subscriptionId);\n\t\t\tif (subscriptionKey) {\n\t\t\t\tconst entitySub = this.singleSubscriptions.get(subscriptionKey);\n\t\t\t\tif (entitySub) {\n\t\t\t\t\tconst wireEntity = message.row ?? null;\n\t\t\t\t\tconst row = wireEntity ? wireEntity : null;\n\t\t\t\t\tentitySub.latestData = row;\n\t\t\t\t\tentitySub.lastUpdated = Date.now();\n\t\t\t\t\tentitySub.isInitialDataReceived = true;\n\t\t\t\t\tif (entitySub.subscribeTimeout) clearTimeout(entitySub.subscribeTimeout);\n\t\t\t\t\tentitySub.subscribeTimeout = void 0;\n\t\t\t\t\tentitySub.subscribeInFlight = false;\n\t\t\t\t\tentitySub.callbacks.forEach((callback) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcallback.onUpdate(row);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tconsole.error(\"Error in row subscription callback:\", error);\n\t\t\t\t\t\t\tif (callback.onError) callback.onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && (type === \"ERROR\" || message.error)) {\n\t\t\tconst collectionKey = this.backendToCollectionKey.get(subscriptionId);\n\t\t\tif (collectionKey) {\n\t\t\t\tconst collectionSub = this.collectionSubscriptions.get(collectionKey);\n\t\t\t\tif (collectionSub) {\n\t\t\t\t\tif (this.isAuthError(message)) {\n\t\t\t\t\t\tthis.resubscribeAfterAuthRefresh(message, collectionSub, collectionKey, \"collection\", this.backendToCollectionKey, \"subscribe_collection\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (collectionSub.subscribeTimeout) clearTimeout(collectionSub.subscribeTimeout);\n\t\t\t\t\tcollectionSub.subscribeTimeout = void 0;\n\t\t\t\t\tcollectionSub.subscribeInFlight = false;\n\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\tconst error = new RebaseApiError$1(errorMessage, { code: errorCode });\n\t\t\t\t\tcollectionSub.callbacks.forEach((callback) => {\n\t\t\t\t\t\tif (callback.onError) callback.onError(error);\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst entityKey = this.backendToEntityKey.get(subscriptionId);\n\t\t\tif (entityKey) {\n\t\t\t\tconst entitySub = this.singleSubscriptions.get(entityKey);\n\t\t\t\tif (entitySub) {\n\t\t\t\t\tif (this.isAuthError(message)) {\n\t\t\t\t\t\tthis.resubscribeAfterAuthRefresh(message, entitySub, entityKey, \"row\", this.backendToEntityKey, \"subscribe_one\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (entitySub.subscribeTimeout) clearTimeout(entitySub.subscribeTimeout);\n\t\t\t\t\tentitySub.subscribeTimeout = void 0;\n\t\t\t\t\tentitySub.subscribeInFlight = false;\n\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\tconst error = new RebaseApiError$1(errorMessage, { code: errorCode });\n\t\t\t\t\tentitySub.callbacks.forEach((callback) => {\n\t\t\t\t\t\tif (callback.onError) callback.onError(error);\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (subscriptionId && this.subscriptions.has(subscriptionId)) {\n\t\t\tconst callback = this.subscriptions.get(subscriptionId);\n\t\t\tif (!callback) throw new Error(`Subscription callback not found for subscriptionId: ${subscriptionId}`);\n\t\t\tif (message.type === \"ERROR\" || message.error) {\n\t\t\t\tif (callback.onError) {\n\t\t\t\t\tconst { errorMessage, errorCode } = extractMessageError(message);\n\t\t\t\t\tcallback.onError(new RebaseApiError$1(errorMessage, { code: errorCode }));\n\t\t\t\t}\n\t\t\t} else callback.onUpdate(message);\n\t\t}\n\t}\n\tasync ensureAuthenticated(retryCount = 3) {\n\t\tif (this.isAuthenticated || !this.getAuthToken) return;\n\t\tif (!this.authPromise) {\n\t\t\tthis.authPromise = this.runAuthentication(retryCount);\n\t\t\tthis.authPromise.finally(() => {\n\t\t\t\tthis.authPromise = null;\n\t\t\t}).catch(() => void 0);\n\t\t}\n\t\tawait this.authPromise;\n\t}\n\tasync runAuthentication(retryCount) {\n\t\tlet lastError = null;\n\t\tfor (let attempt = 0; attempt < retryCount; attempt++) try {\n\t\t\tconst token = await this.getAuthToken();\n\t\t\tif (!token) throw new Error(\"user not logged in\");\n\t\t\tawait this.authenticate(token);\n\t\t\tconsole.debug(\"WebSocket authenticated on demand\");\n\t\t\treturn;\n\t\t} catch (error) {\n\t\t\tlastError = error;\n\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errMsg.includes(\"not logged in\") || errMsg.includes(\"Session expired\")) {\n\t\t\t\tconsole.warn(\"WebSocket auth failed: user not logged in\");\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (errMsg.includes(\"still loading\")) {\n\t\t\t\tif (attempt < retryCount - 1) {\n\t\t\t\t\tconst delay = Math.min(500 * (attempt + 1), 2e3);\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (attempt < retryCount - 1) {\n\t\t\t\tconst delay = Math.min(1e3 * (attempt + 1), 3e3);\n\t\t\t\tconsole.debug(`WebSocket auth attempt ${attempt + 1} failed, retrying in ${delay}ms...`);\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t}\n\t\t}\n\t\tconsole.warn(\"WebSocket on-demand auth failed after retries:\", lastError);\n\t\tthrow lastError;\n\t}\n\tasync reauthenticate() {\n\t\tif (!this.getAuthToken) return;\n\t\tthis.isAuthenticated = false;\n\t\ttry {\n\t\t\tconst token = await this.getAuthToken();\n\t\t\tif (!token) throw new Error(\"user not logged in\");\n\t\t\tawait this.authenticate(token);\n\t\t\tconsole.debug(\"WebSocket reauthenticated successfully\");\n\t\t} catch (error) {\n\t\t\tconsole.error(\"WebSocket reauthentication failed:\", error);\n\t\t\tthrow error;\n\t\t}\n\t}\n\t/**\n\t* Public because `RebaseRealtimeChannel` sends channel frames through it.\n\t* Not part of the stable surface — prefer `client.realtime.channel(name)`.\n\t*/\n\tsendMessage(message) {\n\t\tconst queuedMsg = message;\n\t\tif (queuedMsg._queuedResolve && queuedMsg._queuedReject) return this.doSendMessage(message, queuedMsg._queuedResolve, queuedMsg._queuedReject);\n\t\tif (!this.isConnected || !this.ws) {\n\t\t\tthis.ensureConnected();\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst queueable = message;\n\t\t\t\tqueueable._queuedResolve = resolve;\n\t\t\t\tqueueable._queuedReject = reject;\n\t\t\t\tthis.messageQueue.push(message);\n\t\t\t});\n\t\t}\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.doSendMessage(message, resolve, reject);\n\t\t});\n\t}\n\tasync doSendMessage(message, resolve, reject) {\n\t\tif (message.type !== \"AUTHENTICATE\" && !CHANNEL_MESSAGE_TYPES.has(message.type) && this.getAuthToken && !this.isAuthenticated) try {\n\t\t\tawait this.ensureAuthenticated();\n\t\t} catch (error) {\n\t\t\treject(new RebaseApiError$1(error instanceof Error ? error.message : \"Authentication required\"));\n\t\t\treturn;\n\t\t}\n\t\tconst requestId = message.requestId || `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tmessage.requestId = requestId;\n\t\tconst expectsResponse = !(message.type === \"subscribe_collection\" || message.type === \"subscribe_one\" || message.type === \"unsubscribe\" || CHANNEL_MESSAGE_TYPES.has(message.type));\n\t\tif (expectsResponse && !this.pendingRequests.has(requestId)) {\n\t\t\tconst timeoutHandle = setTimeout(() => {\n\t\t\t\tif (this.pendingRequests.has(requestId)) {\n\t\t\t\t\tthis.pendingRequests.delete(requestId);\n\t\t\t\t\treject(new RebaseApiError$1(\"Request timed out\"));\n\t\t\t\t}\n\t\t\t}, this.requestTimeoutMs);\n\t\t\tthis.pendingRequests.set(requestId, {\n\t\t\t\tresolve: (value) => {\n\t\t\t\t\tclearTimeout(timeoutHandle);\n\t\t\t\t\tresolve(value);\n\t\t\t\t},\n\t\t\t\treject: (error) => {\n\t\t\t\t\tclearTimeout(timeoutHandle);\n\t\t\t\t\treject(error);\n\t\t\t\t},\n\t\t\t\tmessage\n\t\t\t});\n\t\t}\n\t\ttry {\n\t\t\tthis.ws.send(JSON.stringify(message));\n\t\t\tif (!expectsResponse) resolve(void 0);\n\t\t} catch (error) {\n\t\t\tif (expectsResponse) this.pendingRequests.delete(requestId);\n\t\t\treject(new RebaseApiError$1(\"Failed to send message\", { cause: error }));\n\t\t}\n\t}\n\tasync fetchCollection(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_COLLECTION\",\n\t\t\tpayload: props\n\t\t})).rows || [];\n\t}\n\tasync fetchOne(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_ONE\",\n\t\t\tpayload: props\n\t\t})).row ?? void 0;\n\t}\n\tasync save(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"SAVE\",\n\t\t\tpayload: props\n\t\t})).row;\n\t}\n\tasync delete(props) {\n\t\tawait this.sendMessage({\n\t\t\ttype: \"DELETE\",\n\t\t\tpayload: props\n\t\t});\n\t}\n\tasync executeSql(sql, options) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"EXECUTE_SQL\",\n\t\t\tpayload: {\n\t\t\t\tsql,\n\t\t\t\toptions\n\t\t\t}\n\t\t})).result || [];\n\t}\n\tasync fetchAvailableDatabases() {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_DATABASES\",\n\t\t\tpayload: {}\n\t\t})).databases || [];\n\t}\n\tasync fetchAvailableRoles() {\n\t\treturn (await this.sendMessage({ type: \"FETCH_ROLES\" })).roles || [];\n\t}\n\tasync fetchApplicationRoles() {\n\t\treturn (await this.sendMessage({ type: \"FETCH_APPLICATION_ROLES\" })).roles || [];\n\t}\n\tasync fetchCurrentDatabase() {\n\t\treturn (await this.sendMessage({ type: \"FETCH_CURRENT_DATABASE\" })).database;\n\t}\n\tasync checkUniqueField(path, name, value, id, collection) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"CHECK_UNIQUE_FIELD\",\n\t\t\tpayload: {\n\t\t\t\tpath,\n\t\t\t\tname,\n\t\t\t\tvalue,\n\t\t\t\tid,\n\t\t\t\tcollection\n\t\t\t}\n\t\t})).isUnique;\n\t}\n\tasync count(props) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"COUNT\",\n\t\t\tpayload: props\n\t\t})).count;\n\t}\n\tasync fetchUnmappedTables(mappedPaths) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_UNMAPPED_TABLES\",\n\t\t\tpayload: { mappedPaths }\n\t\t})).tables || [];\n\t}\n\tasync fetchTableMetadata(tableName) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"FETCH_TABLE_METADATA\",\n\t\t\tpayload: { tableName }\n\t\t})).metadata || {\n\t\t\tcolumns: [],\n\t\t\tforeignKeys: [],\n\t\t\tjunctions: [],\n\t\t\tpolicies: []\n\t\t};\n\t}\n\tasync createBranch(name, options) {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"CREATE_BRANCH\",\n\t\t\tpayload: {\n\t\t\t\tname,\n\t\t\t\toptions\n\t\t\t}\n\t\t})).branch;\n\t}\n\tasync deleteBranch(name) {\n\t\tawait this.sendMessage({\n\t\t\ttype: \"DELETE_BRANCH\",\n\t\t\tpayload: { name }\n\t\t});\n\t}\n\tasync listBranches() {\n\t\treturn (await this.sendMessage({\n\t\t\ttype: \"LIST_BRANCHES\",\n\t\t\tpayload: {}\n\t\t})).branches || [];\n\t}\n\t/**\n\t* Recursively compare two values for structural equality.\n\t* Handles primitives, null, undefined, Date, RegExp, arrays, and plain objects.\n\t*/\n\tdeepEqual(a, b) {\n\t\tif (a === b) return true;\n\t\tif (a === null || b === null || a === void 0 || b === void 0) return false;\n\t\tif (typeof a !== typeof b) return false;\n\t\tif (typeof a !== \"object\") return false;\n\t\tif (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();\n\t\tif (a instanceof Date || b instanceof Date) return false;\n\t\tif (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;\n\t\tif (a instanceof RegExp || b instanceof RegExp) return false;\n\t\tconst aIsArray = Array.isArray(a);\n\t\tconst bIsArray = Array.isArray(b);\n\t\tif (aIsArray !== bIsArray) return false;\n\t\tif (aIsArray && bIsArray) {\n\t\t\tif (a.length !== b.length) return false;\n\t\t\tfor (let i = 0; i < a.length; i++) if (!this.deepEqual(a[i], b[i])) return false;\n\t\t\treturn true;\n\t\t}\n\t\tconst aObj = a;\n\t\tconst bObj = b;\n\t\tconst aKeys = Object.keys(aObj);\n\t\tconst bKeys = Object.keys(bObj);\n\t\tif (aKeys.length !== bKeys.length) return false;\n\t\tfor (const key of aKeys) {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(bObj, key)) return false;\n\t\t\tif (!this.deepEqual(aObj[key], bObj[key])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\tnormalizeForComparison(val) {\n\t\tif (!val) return val;\n\t\tif (Array.isArray(val)) return val.map((item) => this.normalizeForComparison(item));\n\t\tif (typeof val === \"object\") {\n\t\t\tif (val instanceof Date) return val;\n\t\t\tif (val instanceof RegExp) return val;\n\t\t\tconst obj = val;\n\t\t\tif (obj.__type === \"relation\") {\n\t\t\t\tconst { data, ...rest } = obj;\n\t\t\t\treturn rest;\n\t\t\t}\n\t\t\tconst result = {};\n\t\t\tfor (const [k, v] of Object.entries(obj)) result[k] = this.normalizeForComparison(v);\n\t\t\treturn result;\n\t\t}\n\t\treturn val;\n\t}\n\t/**\n\t* The address of a row, for matching it against another copy of itself.\n\t*\n\t* A row is exactly its columns and carries no address, so it is derived\n\t* from the key columns the server named — including the ordinary case where\n\t* that key is `id`, which the server reports like any other.\n\t*\n\t* Undefined when there are no keys, which means the server could not\n\t* resolve any: such rows genuinely cannot be recognised, and guessing at a\n\t* column called `id` would be inventing an identity for a table that has\n\t* none.\n\t*/\n\trowAddress(row, pks) {\n\t\tif (!pks || pks.length === 0) return void 0;\n\t\tconst address = buildCompositeId(row, pks);\n\t\tif (!address || address.split(COMPOSITE_ID_SEPARATOR).every((part) => part === \"\")) return void 0;\n\t\treturn address;\n\t}\n\t/**\n\t* Merge incoming rows with cached data, preserving cached references\n\t* for rows whose values haven't changed. This avoids unnecessary\n\t* React re-renders when the server refetches all rows but most\n\t* haven't actually changed.\n\t*/\n\tmergeRows(cached, incoming, pks) {\n\t\tif (!cached || cached.length === 0) return incoming;\n\t\tconst cachedById = /* @__PURE__ */ new Map();\n\t\tfor (const row of cached) {\n\t\t\tconst address = this.rowAddress(row, pks);\n\t\t\tif (address !== void 0) cachedById.set(address, row);\n\t\t}\n\t\treturn incoming.map((incomingRow) => {\n\t\t\tconst address = this.rowAddress(incomingRow, pks);\n\t\t\tconst cachedRow = address === void 0 ? void 0 : cachedById.get(address);\n\t\t\tif (!cachedRow) return incomingRow;\n\t\t\tconst normCached = this.normalizeForComparison(cachedRow);\n\t\t\tconst normIncoming = this.normalizeForComparison(incomingRow);\n\t\t\tif (this.deepEqual(normCached, normIncoming)) return cachedRow;\n\t\t\telse {\n\t\t\t\tconst mismatches = {};\n\t\t\t\tconst allKeys = /* @__PURE__ */ new Set([...Object.keys(normCached), ...Object.keys(normIncoming)]);\n\t\t\t\tfor (const key of allKeys) if (!this.deepEqual(normCached[key], normIncoming[key])) mismatches[key] = {\n\t\t\t\t\tcached: normCached[key],\n\t\t\t\t\tincoming: normIncoming[key]\n\t\t\t\t};\n\t\t\t\tconsole.debug(`[RebaseWS] Row ${address} refetch mismatch:\\n`, JSON.stringify(mismatches, null, 2));\n\t\t\t}\n\t\t\treturn incomingRow;\n\t\t});\n\t}\n\tlistenCollection(props, onUpdate, onError) {\n\t\tthis.ensureConnected();\n\t\tconst subscriptionKey = this.createCollectionSubscriptionKey(props);\n\t\tconst callbackId = `callback_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst existingSubscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (existingSubscription) {\n\t\t\tconst callbackMap = existingSubscription.callbacks;\n\t\t\tcallbackMap.set(callbackId, {\n\t\t\t\tonUpdate,\n\t\t\t\tonError\n\t\t\t});\n\t\t\tif (existingSubscription.latestData !== void 0 && existingSubscription.isInitialDataReceived) try {\n\t\t\t\tonUpdate(existingSubscription.latestData);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Error in collection subscription callback:\", error);\n\t\t\t\tif (onError) onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t}\n\t\t\telse if (!existingSubscription.subscribeInFlight) this.sendCollectionSubscribe(subscriptionKey);\n\t\t\treturn () => {\n\t\t\t\tcallbackMap.delete(callbackId);\n\t\t\t\tif (callbackMap.size === 0) {\n\t\t\t\t\tif (this.collectionSubscriptions.get(subscriptionKey) !== existingSubscription) return;\n\t\t\t\t\tif (existingSubscription.subscribeTimeout) clearTimeout(existingSubscription.subscribeTimeout);\n\t\t\t\t\tthis.collectionSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToCollectionKey.delete(existingSubscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: existingSubscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tconst backendSubscriptionId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst callbackMap = /* @__PURE__ */ new Map();\n\t\tcallbackMap.set(callbackId, {\n\t\t\tonUpdate,\n\t\t\tonError\n\t\t});\n\t\tthis.collectionSubscriptions.set(subscriptionKey, {\n\t\t\tbackendSubscriptionId,\n\t\t\tcallbacks: callbackMap,\n\t\t\tprops\n\t\t});\n\t\tthis.backendToCollectionKey.set(backendSubscriptionId, subscriptionKey);\n\t\tthis.sendCollectionSubscribe(subscriptionKey);\n\t\treturn () => {\n\t\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\tif (subscription) {\n\t\t\t\tconst callbacks = subscription.callbacks;\n\t\t\t\tcallbacks.delete(callbackId);\n\t\t\t\tif (callbacks.size === 0) {\n\t\t\t\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\t\t\t\tthis.collectionSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToCollectionKey.delete(subscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: subscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\tlistenOne(props, onUpdate, onError) {\n\t\tthis.ensureConnected();\n\t\tconst subscriptionKey = this.createSingleSubscriptionKey(props);\n\t\tconst callbackId = `callback_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst existingSubscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (existingSubscription) {\n\t\t\tconst callbackMap = existingSubscription.callbacks;\n\t\t\tcallbackMap.set(callbackId, {\n\t\t\t\tonUpdate,\n\t\t\t\tonError\n\t\t\t});\n\t\t\tif (existingSubscription.latestData !== void 0 && existingSubscription.isInitialDataReceived) try {\n\t\t\t\tonUpdate(existingSubscription.latestData);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Error in row subscription callback:\", error);\n\t\t\t\tif (onError) onError(error instanceof Error ? error : new Error(String(error)));\n\t\t\t}\n\t\t\telse if (!existingSubscription.subscribeInFlight) this.sendEntitySubscribe(subscriptionKey);\n\t\t\treturn () => {\n\t\t\t\tcallbackMap.delete(callbackId);\n\t\t\t\tif (callbackMap.size === 0) {\n\t\t\t\t\tif (this.singleSubscriptions.get(subscriptionKey) !== existingSubscription) return;\n\t\t\t\t\tif (existingSubscription.subscribeTimeout) clearTimeout(existingSubscription.subscribeTimeout);\n\t\t\t\t\tthis.singleSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToEntityKey.delete(existingSubscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: existingSubscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\tconst backendSubscriptionId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\tconst callbackMap = /* @__PURE__ */ new Map();\n\t\tcallbackMap.set(callbackId, {\n\t\t\tonUpdate,\n\t\t\tonError\n\t\t});\n\t\tthis.singleSubscriptions.set(subscriptionKey, {\n\t\t\tbackendSubscriptionId,\n\t\t\tcallbacks: callbackMap,\n\t\t\tprops\n\t\t});\n\t\tthis.backendToEntityKey.set(backendSubscriptionId, subscriptionKey);\n\t\tthis.sendEntitySubscribe(subscriptionKey);\n\t\treturn () => {\n\t\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\t\tif (subscription) {\n\t\t\t\tconst callbacks = subscription.callbacks;\n\t\t\t\tcallbacks.delete(callbackId);\n\t\t\t\tif (callbacks.size === 0) {\n\t\t\t\t\tthis.singleSubscriptions.delete(subscriptionKey);\n\t\t\t\t\tthis.backendToEntityKey.delete(subscription.backendSubscriptionId);\n\t\t\t\t\tif (this.isConnected && this.ws) this.sendMessage({\n\t\t\t\t\t\ttype: \"unsubscribe\",\n\t\t\t\t\t\tpayload: { subscriptionId: subscription.backendSubscriptionId }\n\t\t\t\t\t}).catch(console.error);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t* Send a `subscribe_collection` for an already-registered subscription and\n\t* arm its watchdog.\n\t*\n\t* Every path that registers a collection subscription goes through here, so\n\t* that a subscribe which never lands — a rejected send, or a server that\n\t* never answers — always ends up in `failCollectionSubscription` rather than\n\t* leaving the entry parked with `isInitialDataReceived === false` forever.\n\t*/\n\tsendCollectionSubscribe(subscriptionKey) {\n\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeInFlight = true;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeTimeout = void 0;\n\t\tif (this.isConnected) this.sendCollectionSubscribeWatchdog(subscriptionKey);\n\t\tthis.sendMessage({\n\t\t\ttype: \"subscribe_collection\",\n\t\t\tpayload: {\n\t\t\t\t...subscription.props,\n\t\t\t\tsubscriptionId: backendSubscriptionId\n\t\t\t}\n\t\t}).catch((error) => {\n\t\t\tconst current = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tthis.failCollectionSubscription(subscriptionKey, error instanceof Error ? error : new Error(String(error)));\n\t\t});\n\t}\n\t/** The `listenOne` counterpart of {@link sendCollectionSubscribe}. */\n\tsendEntitySubscribe(subscriptionKey) {\n\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeInFlight = true;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeTimeout = void 0;\n\t\tif (this.isConnected) this.sendEntitySubscribeWatchdog(subscriptionKey);\n\t\tthis.sendMessage({\n\t\t\ttype: \"subscribe_one\",\n\t\t\tpayload: {\n\t\t\t\t...subscription.props,\n\t\t\t\tsubscriptionId: backendSubscriptionId\n\t\t\t}\n\t\t}).catch((error) => {\n\t\t\tconst current = this.singleSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tthis.failEntitySubscription(subscriptionKey, error instanceof Error ? error : new Error(String(error)));\n\t\t});\n\t}\n\t/**\n\t* Report a subscribe failure to every listener and drop the registration.\n\t*\n\t* Dropping it is the point: the callbacks stay live (their components are\n\t* still mounted and have been told), but the next `listenCollection` for\n\t* these params finds no entry and issues a fresh subscribe instead of\n\t* silently attaching to a dead one.\n\t*/\n\tfailCollectionSubscription(subscriptionKey, error) {\n\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeInFlight = false;\n\t\tthis.collectionSubscriptions.delete(subscriptionKey);\n\t\tthis.backendToCollectionKey.delete(subscription.backendSubscriptionId);\n\t\tsubscription.callbacks.forEach((callback) => {\n\t\t\tif (callback.onError) try {\n\t\t\t\tcallback.onError(error);\n\t\t\t} catch (callbackError) {\n\t\t\t\tconsole.error(\"Error in collection subscription error callback:\", callbackError);\n\t\t\t}\n\t\t});\n\t}\n\t/** The `listenOne` counterpart of {@link failCollectionSubscription}. */\n\tfailEntitySubscription(subscriptionKey, error) {\n\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tif (subscription.subscribeTimeout) clearTimeout(subscription.subscribeTimeout);\n\t\tsubscription.subscribeInFlight = false;\n\t\tthis.singleSubscriptions.delete(subscriptionKey);\n\t\tthis.backendToEntityKey.delete(subscription.backendSubscriptionId);\n\t\tsubscription.callbacks.forEach((callback) => {\n\t\t\tif (callback.onError) try {\n\t\t\t\tcallback.onError(error);\n\t\t\t} catch (callbackError) {\n\t\t\t\tconsole.error(\"Error in row subscription error callback:\", callbackError);\n\t\t\t}\n\t\t});\n\t}\n\t/**\n\t* Stop the watchdogs without failing anything — used when the socket drops,\n\t* since the reconnect path re-subscribes everything anyway and a watchdog\n\t* firing mid-reconnect would tear down healthy subscriptions.\n\t*/\n\tsuspendSubscribeWatchdogs() {\n\t\tfor (const sub of this.collectionSubscriptions.values()) {\n\t\t\tif (sub.subscribeTimeout) clearTimeout(sub.subscribeTimeout);\n\t\t\tsub.subscribeTimeout = void 0;\n\t\t\tsub.subscribeInFlight = false;\n\t\t}\n\t\tfor (const sub of this.singleSubscriptions.values()) {\n\t\t\tif (sub.subscribeTimeout) clearTimeout(sub.subscribeTimeout);\n\t\t\tsub.subscribeTimeout = void 0;\n\t\t\tsub.subscribeInFlight = false;\n\t\t}\n\t}\n\t/**\n\t* Arm watchdogs for subscribes that were requested while offline and have\n\t* just been flushed to the socket. Their timers were deliberately not set at\n\t* request time, so without this they would have no timeout at all.\n\t*/\n\tarmPendingSubscribeWatchdogs() {\n\t\tfor (const [key, sub] of this.collectionSubscriptions.entries()) if (sub.subscribeInFlight && !sub.subscribeTimeout) this.sendCollectionSubscribeWatchdog(key);\n\t\tfor (const [key, sub] of this.singleSubscriptions.entries()) if (sub.subscribeInFlight && !sub.subscribeTimeout) this.sendEntitySubscribeWatchdog(key);\n\t}\n\tsendCollectionSubscribeWatchdog(subscriptionKey) {\n\t\tconst subscription = this.collectionSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeTimeout = setTimeout(() => {\n\t\t\tconst current = this.collectionSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tif (!current.subscribeInFlight) return;\n\t\t\tthis.failCollectionSubscription(subscriptionKey, new RebaseApiError$1(\"Subscription timed out\", { code: \"SUBSCRIPTION_TIMEOUT\" }));\n\t\t}, this.subscriptionTimeoutMs);\n\t}\n\tsendEntitySubscribeWatchdog(subscriptionKey) {\n\t\tconst subscription = this.singleSubscriptions.get(subscriptionKey);\n\t\tif (!subscription) return;\n\t\tconst backendSubscriptionId = subscription.backendSubscriptionId;\n\t\tsubscription.subscribeTimeout = setTimeout(() => {\n\t\t\tconst current = this.singleSubscriptions.get(subscriptionKey);\n\t\t\tif (!current || current.backendSubscriptionId !== backendSubscriptionId) return;\n\t\t\tif (!current.subscribeInFlight) return;\n\t\t\tthis.failEntitySubscription(subscriptionKey, new RebaseApiError$1(\"Subscription timed out\", { code: \"SUBSCRIPTION_TIMEOUT\" }));\n\t\t}, this.subscriptionTimeoutMs);\n\t}\n\t/**\n\t* Fail every subscription that never received data. Called when reconnection\n\t* is given up on, so views surface an error instead of spinning forever.\n\t*/\n\tfailAllPendingSubscriptions(error) {\n\t\tfor (const key of [...this.collectionSubscriptions.keys()]) {\n\t\t\tconst sub = this.collectionSubscriptions.get(key);\n\t\t\tif (sub && !sub.isInitialDataReceived) this.failCollectionSubscription(key, error);\n\t\t}\n\t\tfor (const key of [...this.singleSubscriptions.keys()]) {\n\t\t\tconst sub = this.singleSubscriptions.get(key);\n\t\t\tif (sub && !sub.isInitialDataReceived) this.failEntitySubscription(key, error);\n\t\t}\n\t}\n\t/**\n\t* Re-send all active subscriptions to the backend after a reconnect.\n\t* The server wipes subscription state when a client disconnects, so\n\t* we need to re-register everything to resume receiving updates.\n\t*/\n\tresubscribeAll() {\n\t\tconsole.debug(`[WS] Re-subscribing: ${this.collectionSubscriptions.size} collection(s), ${this.singleSubscriptions.size} row(ies)`);\n\t\tfor (const [key, sub] of this.collectionSubscriptions.entries()) {\n\t\t\tconst oldBackendId = sub.backendSubscriptionId;\n\t\t\tconst newBackendId = `collection_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\tsub.backendSubscriptionId = newBackendId;\n\t\t\tthis.backendToCollectionKey.delete(oldBackendId);\n\t\t\tthis.backendToCollectionKey.set(newBackendId, key);\n\t\t\tthis.sendCollectionSubscribe(key);\n\t\t}\n\t\tfor (const [key, sub] of this.singleSubscriptions.entries()) {\n\t\t\tconst oldBackendId = sub.backendSubscriptionId;\n\t\t\tconst newBackendId = `entity_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n\t\t\tsub.backendSubscriptionId = newBackendId;\n\t\t\tthis.backendToEntityKey.delete(oldBackendId);\n\t\t\tthis.backendToEntityKey.set(newBackendId, key);\n\t\t\tthis.sendEntitySubscribe(key);\n\t\t}\n\t}\n\tcreateCollectionSubscriptionKey(props) {\n\t\tconst key = {\n\t\t\tpath: props.path,\n\t\t\tfilter: props.filter,\n\t\t\tlimit: props.limit,\n\t\t\tstartAfter: props.startAfter,\n\t\t\torderBy: props.orderBy,\n\t\t\torder: props.order,\n\t\t\tsearchString: props.searchString,\n\t\t\tcollection: props.collection?.name\n\t\t};\n\t\treturn JSON.stringify(key, (_, value) => {\n\t\t\tif (value && typeof value === \"object\" && !Array.isArray(value)) return Object.keys(value).sort().reduce((sorted, k) => {\n\t\t\t\tsorted[k] = value[k];\n\t\t\t\treturn sorted;\n\t\t\t}, {});\n\t\t\treturn value;\n\t\t});\n\t}\n\tcreateSingleSubscriptionKey(props) {\n\t\treturn `${props.path}|${props.id}`;\n\t}\n};\n//#endregion\n//#region src/realtime-channel.ts\n/**\n* Re-send presence comfortably inside the server's 30s expiry.\n*\n* Two-thirds of the window: one lost heartbeat still leaves time for the next\n* before the entry is reaped, so a single dropped frame is not a disappearance.\n*/\nvar PRESENCE_HEARTBEAT_MS = 2e4;\n/**\n* How long live messages are held back waiting for a catch-up response.\n*\n* Short, because the cost of waiting is visible — on a collaborative document\n* this is a stall in everyone else's edits appearing. Long enough that a slow\n* replay of a busy channel is not abandoned needlessly.\n*/\nvar CATCH_UP_TIMEOUT_MS = 1e4;\nvar RebaseRealtimeChannel = class {\n\tname;\n\ttransport;\n\tpresenceHandlers = /* @__PURE__ */ new Set();\n\tbroadcastHandlers = /* @__PURE__ */ new Set();\n\tunsubscribers = [];\n\t/** Last known roster, kept so handlers always get a full picture. */\n\tpresences = {};\n\t/** What this client last tracked, replayed on reconnect and heartbeat. */\n\ttrackedState = null;\n\theartbeat = null;\n\tjoined = false;\n\t/** Whether this handle asks the server to replay missed messages. */\n\twantsHistory;\n\t/**\n\t* Highest sequence number delivered to handlers so far.\n\t*\n\t* This is the resume point sent as `sinceSeq`, and the watermark that makes\n\t* replay idempotent: catch-up ranges overlap with what arrived live, and\n\t* anything at or below this has already been seen.\n\t*/\n\tlastSeq = 0;\n\t/**\n\t* Live messages that arrived while a catch-up was in flight.\n\t*\n\t* Without this they would be delivered ahead of the older messages being\n\t* fetched, and — worse — would advance {@link lastSeq} past them, so the\n\t* catch-up response would then be discarded as already-seen and those\n\t* messages would be lost for good. Held here and flushed, in order, once\n\t* the replay lands.\n\t*/\n\tpendingLive = [];\n\tcatchUpInFlight = false;\n\t/**\n\t* Deadline for a catch-up response.\n\t*\n\t* Buffering live messages is only safe because the wait is bounded. A\n\t* catch-up frame that never arrives — a server that dropped it, a socket\n\t* that died between request and reply — would otherwise leave the channel\n\t* silently holding every subsequent edit forever, which is a worse failure\n\t* than the one replay was added to fix.\n\t*/\n\tcatchUpTimeout = null;\n\t/**\n\t* Callers of {@link history} awaiting the next `channel_history` frame.\n\t*\n\t* These frames are addressed by channel rather than by request id, so they\n\t* are matched in arrival order. Requests on one channel are serialized by\n\t* the socket, so FIFO is the right correlation here.\n\t*/\n\thistoryWaiters = [];\n\tconstructor(name, transport, options = {}) {\n\t\tthis.name = name;\n\t\tthis.transport = transport;\n\t\tthis.wantsHistory = options.history ?? false;\n\t}\n\t/**\n\t* Turn on catch-up for a handle that was created without it.\n\t*\n\t* The client hands back the same channel object for a given name, so a\n\t* later `channel(name, { history: true })` has no new object to configure —\n\t* it upgrades this one instead. Idempotent, and never downgrades: one\n\t* caller asking for history must not be switched off by another that did\n\t* not ask.\n\t*/\n\tenableHistory() {\n\t\tif (this.wantsHistory) return;\n\t\tthis.wantsHistory = true;\n\t\tif (this.joined) this.requestHistory();\n\t}\n\t/**\n\t* Join the channel and ask for the current roster.\n\t*\n\t* Called automatically by `track`, `broadcast`, `onPresence` and\n\t* `onBroadcast`; calling it directly is only needed to start receiving\n\t* before there is anything to send.\n\t*/\n\t/**\n\t* Send a channel message.\n\t*\n\t* Every channel message is read by the server out of a `payload` envelope\n\t* (`payload?.channel`, `payload?.state`, `payload?.event`). Sending those\n\t* fields flat does not error: `payload?.channel` simply reads as\n\t* `undefined`, so the client is registered into channel `undefined` with\n\t* empty state, and the echo comes back with no `channel` for\n\t* `onChannelMessage` to match — presence and broadcast both go quiet with\n\t* nothing logged. Funnelled through one place so a new message type cannot\n\t* reintroduce that.\n\t*/\n\tsend(type, fields = {}) {\n\t\treturn this.transport.sendMessage({\n\t\t\ttype,\n\t\t\tpayload: {\n\t\t\t\tchannel: this.name,\n\t\t\t\t...fields\n\t\t\t}\n\t\t});\n\t}\n\tasync join() {\n\t\tif (this.joined) return;\n\t\tthis.joined = true;\n\t\tthis.unsubscribers.push(this.transport.onChannelMessage(this.name, (message) => this.handle(message)));\n\t\tthis.unsubscribers.push(this.transport.onReconnect(() => {\n\t\t\tthis.rejoin();\n\t\t}));\n\t\tawait this.send(\"join_channel\");\n\t\tawait this.send(\"presence_state\");\n\t\tif (this.wantsHistory) await this.requestHistory();\n\t}\n\tasync rejoin() {\n\t\ttry {\n\t\t\tawait this.send(\"join_channel\");\n\t\t\tawait this.send(\"presence_state\");\n\t\t\tif (this.trackedState) await this.send(\"presence_track\", { state: this.trackedState });\n\t\t\tif (this.wantsHistory) await this.requestHistory();\n\t\t} catch {}\n\t}\n\t/**\n\t* Ask the server for everything after {@link lastSeq}.\n\t*\n\t* Live messages are buffered from here until the answer arrives — see\n\t* {@link pendingLive}.\n\t*/\n\tasync requestHistory(limit) {\n\t\tthis.catchUpInFlight = true;\n\t\tif (this.catchUpTimeout) clearTimeout(this.catchUpTimeout);\n\t\tthis.catchUpTimeout = setTimeout(() => this.abandonCatchUp(), CATCH_UP_TIMEOUT_MS);\n\t\tthis.catchUpTimeout.unref?.();\n\t\ttry {\n\t\t\tawait this.send(\"channel_history\", {\n\t\t\t\tsinceSeq: this.lastSeq,\n\t\t\t\t...limit !== void 0 ? { limit } : {}\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.abandonCatchUp();\n\t\t}\n\t}\n\t/**\n\t* Give up waiting for a catch-up and release what was held back.\n\t*\n\t* The buffered messages are still the freshest thing this client has, so\n\t* they are delivered rather than dropped. Callers of {@link history} are\n\t* answered with `retained: false` — accurate in the sense that matters:\n\t* this client has no history to work from and has to resync.\n\t*/\n\tabandonCatchUp() {\n\t\tif (this.catchUpTimeout) {\n\t\t\tclearTimeout(this.catchUpTimeout);\n\t\t\tthis.catchUpTimeout = null;\n\t\t}\n\t\tif (!this.catchUpInFlight) return;\n\t\tthis.catchUpInFlight = false;\n\t\tfor (const resolve of this.historyWaiters.splice(0)) resolve({\n\t\t\tmessages: [],\n\t\t\tretained: false\n\t\t});\n\t\tthis.flushPendingLive();\n\t}\n\t/**\n\t* Publish this client's presence state, and keep publishing it.\n\t*\n\t* Calling `track` again replaces the state (and restarts the heartbeat),\n\t* which is how you update e.g. a cursor position.\n\t*/\n\tasync track(state) {\n\t\tawait this.join();\n\t\tthis.trackedState = state;\n\t\tawait this.send(\"presence_track\", { state });\n\t\tif (!this.heartbeat) {\n\t\t\tthis.heartbeat = setInterval(() => {\n\t\t\t\tif (!this.trackedState) return;\n\t\t\t\tthis.send(\"presence_track\", { state: this.trackedState }).catch(() => {});\n\t\t\t}, PRESENCE_HEARTBEAT_MS);\n\t\t\tthis.heartbeat.unref?.();\n\t\t}\n\t}\n\t/** Stop publishing presence, without leaving the channel. */\n\tasync untrack() {\n\t\tthis.stopHeartbeat();\n\t\tthis.trackedState = null;\n\t\tif (this.joined) await this.send(\"presence_untrack\");\n\t}\n\t/**\n\t* Observe the roster. The handler fires immediately with what is already\n\t* known, then on every change.\n\t*/\n\tonPresence(handler) {\n\t\tthis.presenceHandlers.add(handler);\n\t\tthis.join();\n\t\tif (Object.keys(this.presences).length > 0) handler({ ...this.presences });\n\t\treturn () => this.presenceHandlers.delete(handler);\n\t}\n\t/** Send a broadcast. The sender does not receive its own message. */\n\tasync broadcast(event, payload) {\n\t\tawait this.join();\n\t\tawait this.send(\"broadcast\", {\n\t\t\tevent,\n\t\t\tpayload\n\t\t});\n\t}\n\tonBroadcast(eventOrHandler, maybeHandler) {\n\t\tconst wrapped = typeof eventOrHandler === \"string\" ? (e) => {\n\t\t\tif (e.event === eventOrHandler) maybeHandler(e.payload);\n\t\t} : eventOrHandler;\n\t\tthis.broadcastHandlers.add(wrapped);\n\t\tthis.join();\n\t\treturn () => this.broadcastHandlers.delete(wrapped);\n\t}\n\t/**\n\t* The last sequence number this channel has delivered.\n\t*\n\t* Zero on a channel that retains nothing. Persist it if you want catch-up\n\t* to survive a page reload as well as a reconnect, and pass it back via\n\t* {@link history}.\n\t*/\n\tget sequence() {\n\t\treturn this.lastSeq;\n\t}\n\t/**\n\t* Fetch retained messages explicitly, instead of waiting for join or\n\t* reconnect to do it.\n\t*\n\t* Defaults to resuming from {@link sequence}. Messages are delivered to\n\t* `onBroadcast` handlers as usual — the returned value is for callers that\n\t* want to inspect the batch, or to learn from `retained` that the channel\n\t* keeps no history at all.\n\t*/\n\tasync history(options = {}) {\n\t\tawait this.join();\n\t\tif (options.sinceSeq !== void 0) this.lastSeq = options.sinceSeq;\n\t\tconst result = new Promise((resolve) => {\n\t\t\tthis.historyWaiters.push(resolve);\n\t\t});\n\t\tawait this.requestHistory(options.limit);\n\t\treturn result;\n\t}\n\t/** Leave the channel and release every listener and timer. */\n\tasync leave() {\n\t\tthis.stopHeartbeat();\n\t\tthis.trackedState = null;\n\t\tthis.presences = {};\n\t\tthis.presenceHandlers.clear();\n\t\tthis.broadcastHandlers.clear();\n\t\tthis.lastSeq = 0;\n\t\tthis.pendingLive = [];\n\t\tthis.catchUpInFlight = false;\n\t\tif (this.catchUpTimeout) {\n\t\t\tclearTimeout(this.catchUpTimeout);\n\t\t\tthis.catchUpTimeout = null;\n\t\t}\n\t\tfor (const resolve of this.historyWaiters.splice(0)) resolve({\n\t\t\tmessages: [],\n\t\t\tretained: false\n\t\t});\n\t\tfor (const off of this.unsubscribers) off();\n\t\tthis.unsubscribers = [];\n\t\tif (this.joined) {\n\t\t\tthis.joined = false;\n\t\t\tawait this.send(\"leave_channel\");\n\t\t}\n\t}\n\tstopHeartbeat() {\n\t\tif (this.heartbeat) {\n\t\t\tclearInterval(this.heartbeat);\n\t\t\tthis.heartbeat = null;\n\t\t}\n\t}\n\t/** Fold an incoming frame into the roster and fan it out. */\n\thandle(message) {\n\t\tswitch (message.type) {\n\t\t\tcase \"presence_state\":\n\t\t\t\tthis.presences = message.presences ?? {};\n\t\t\t\tthis.emitPresence();\n\t\t\t\tbreak;\n\t\t\tcase \"presence_diff\": {\n\t\t\t\tconst joins = message.joins ?? {};\n\t\t\t\tconst leaves = message.leaves ?? {};\n\t\t\t\tfor (const [id, state] of Object.entries(joins)) this.presences[id] = state;\n\t\t\t\tfor (const id of Object.keys(leaves)) delete this.presences[id];\n\t\t\t\tthis.emitPresence({\n\t\t\t\t\tjoins,\n\t\t\t\t\tleaves\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"broadcast\": {\n\t\t\t\tconst seq = typeof message.seq === \"number\" ? message.seq : void 0;\n\t\t\t\tconst event = {\n\t\t\t\t\tevent: message.event,\n\t\t\t\t\tpayload: message.payload,\n\t\t\t\t\t...seq !== void 0 ? { seq } : {}\n\t\t\t\t};\n\t\t\t\tif (seq === void 0) {\n\t\t\t\t\tthis.deliver(event);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (this.catchUpInFlight) {\n\t\t\t\t\tthis.pendingLive.push(event);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (seq <= this.lastSeq) break;\n\t\t\t\tthis.lastSeq = seq;\n\t\t\t\tthis.deliver(event);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"channel_history\": {\n\t\t\t\tthis.catchUpInFlight = false;\n\t\t\t\tif (this.catchUpTimeout) {\n\t\t\t\t\tclearTimeout(this.catchUpTimeout);\n\t\t\t\t\tthis.catchUpTimeout = null;\n\t\t\t\t}\n\t\t\t\tconst entries = message.messages ?? [];\n\t\t\t\tconst retained = message.retained === true;\n\t\t\t\tconst latestSeq = typeof message.latestSeq === \"number\" ? message.latestSeq : void 0;\n\t\t\t\tfor (const resolve of this.historyWaiters.splice(0)) resolve({\n\t\t\t\t\tmessages: entries,\n\t\t\t\t\tretained,\n\t\t\t\t\tlatestSeq\n\t\t\t\t});\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tif (entry.seq <= this.lastSeq) continue;\n\t\t\t\t\tthis.lastSeq = entry.seq;\n\t\t\t\t\tthis.deliver({\n\t\t\t\t\t\tevent: entry.event,\n\t\t\t\t\t\tpayload: entry.payload,\n\t\t\t\t\t\tseq: entry.seq,\n\t\t\t\t\t\treplayed: true\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthis.flushPendingLive();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\t/** Deliver everything held back during a catch-up, in sequence order. */\n\tflushPendingLive() {\n\t\tif (this.pendingLive.length === 0) return;\n\t\tconst buffered = this.pendingLive.sort((a, b) => (a.seq ?? 0) - (b.seq ?? 0));\n\t\tthis.pendingLive = [];\n\t\tfor (const event of buffered) {\n\t\t\tconst seq = event.seq;\n\t\t\tif (seq !== void 0) {\n\t\t\t\tif (seq <= this.lastSeq) continue;\n\t\t\t\tthis.lastSeq = seq;\n\t\t\t}\n\t\t\tthis.deliver(event);\n\t\t}\n\t}\n\tdeliver(event) {\n\t\tfor (const handler of [...this.broadcastHandlers]) handler(event);\n\t}\n\temitPresence(diff) {\n\t\tconst snapshot = { ...this.presences };\n\t\tfor (const handler of this.presenceHandlers) handler(snapshot, diff);\n\t}\n};\n//#endregion\n//#region src/offline-codec.ts\n/**\n* Lossless round-tripping of rows through the offline store.\n*\n* Both persistence backends move values by structured clone, which keeps\n* `Date` but flattens every class instance to a plain object. For\n* `EntityReference`/`EntityRelation` that is harmless — they carry their own\n* `__type` discriminator, so the JSON reviver can rebuild them — but\n* `GeoPoint` and `Vector` do not, and would come back out of the cache as\n* anonymous `{ latitude, longitude }` / `{ value }` bags. A row read from the\n* cache must be indistinguishable from the same row read from the network, so\n* those two are tagged on the way in and revived on the way out.\n*\n* Type tests here are structural rather than `instanceof`, because a structured\n* clone can arrive from another realm — an iframe, a worker, or the polyfill\n* the tests run against — where the constructor identity differs but the value\n* is the real thing. Only *plain* objects are walked; anything else is passed\n* through whole, so a class instance is never quietly reduced to `{}`.\n*/\nfunction isDate(value) {\n\treturn Object.prototype.toString.call(value) === \"[object Date]\";\n}\n/** An object literal — not a Date, RegExp, Map, or any class instance. */\nfunction isPlainObject(value) {\n\tif (value === null || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto === null || proto === Object.prototype) return true;\n\treturn proto.constructor?.name === \"Object\";\n}\nfunction dehydrateValue(value) {\n\tif (value === null || value === void 0) return value;\n\tif (value instanceof GeoPoint) return {\n\t\t__type: \"GeoPoint\",\n\t\tlatitude: value.latitude,\n\t\tlongitude: value.longitude\n\t};\n\tif (value instanceof Vector) return {\n\t\t__type: \"Vector\",\n\t\tvalue: [...value.value]\n\t};\n\tif (value instanceof EntityReference || value instanceof EntityRelation) return value;\n\tif (Array.isArray(value)) return value.map(dehydrateValue);\n\tif (isPlainObject(value)) {\n\t\tconst out = {};\n\t\tfor (const [key, inner] of Object.entries(value)) out[key] = dehydrateValue(inner);\n\t\treturn out;\n\t}\n\treturn value;\n}\nfunction hydrateValue(value) {\n\tif (value === null || value === void 0 || isDate(value)) return value;\n\tif (Array.isArray(value)) return value.map(hydrateValue);\n\tif (typeof value === \"object\") {\n\t\tconst revived = rebaseReviver(\"\", value);\n\t\tif (revived !== value) return revived;\n\t\tif (!isPlainObject(value)) return value;\n\t\tconst out = {};\n\t\tfor (const [key, inner] of Object.entries(value)) out[key] = hydrateValue(inner);\n\t\treturn out;\n\t}\n\treturn value;\n}\n/** Prepare a row for the store. */\nfunction dehydrateRow(row) {\n\treturn dehydrateValue(row);\n}\n/** Restore a row read back from the store. */\nfunction hydrateRow(row) {\n\treturn hydrateValue(row);\n}\n//#endregion\n//#region src/offline-connectivity.ts\n/**\n* Whether the network is worth trying, and when to try again after it wasn't.\n*\n* `navigator.onLine` is necessary but not sufficient: it reports the state of\n* the network interface, so it stays `true` behind a captive portal, on a\n* connection that resolves DNS but reaches nothing, and while the API itself\n* is down. This tracks what actually happened to requests as well, so the\n* first failure is the only one an app pays for — everything after it inside\n* the backoff window skips the doomed round trip and answers from the local\n* store immediately, which is the difference between an app that freezes when\n* the wifi drops and one that does not.\n*/\n/** The request never reached the server, so nothing was decided by it. */\nfunction isNetworkError(error) {\n\tif (error instanceof RebaseApiError) return error.status === 0;\n\tif (error instanceof TypeError) return true;\n\tconst name = error?.name;\n\treturn name === \"AbortError\" || name === \"TimeoutError\" || name === \"NetworkError\";\n}\n/**\n* Statuses that mean \"not now\" rather than \"not ever\": a queued write that\n* gets one of these is worth replaying, while a 400 or a 403 never will be.\n* 500 is deliberately absent — an unhandled server error is far more often a\n* bug the same payload will hit again than a blip, and retrying it forever\n* jams every write behind it.\n*/\nvar RETRYABLE_STATUSES = /* @__PURE__ */ new Set([\n\t408,\n\t425,\n\t429,\n\t502,\n\t503,\n\t504\n]);\n/** Is this failure worth another attempt later? */\nfunction isRetryableError(error) {\n\tif (isNetworkError(error)) return true;\n\tif (error instanceof RebaseApiError) return error.status !== void 0 && RETRYABLE_STATUSES.has(error.status);\n\treturn false;\n}\n/**\n* Did this write fail because the row is already there?\n*\n* Matched on the SQLSTATE the server passes through (`23505`, unique_violation)\n* and on 409, never on the message — a duplicate-key message names the\n* constraint and the values, so it is neither stable nor safe to parse.\n*\n* The queue uses this to recognise its own earlier attempt. A create whose\n* response was lost is replayed, and for a row carrying an id the SDK generated\n* the server can only be rejecting it because the first attempt actually landed.\n*/\nfunction isDuplicateKeyError(error) {\n\tif (!(error instanceof RebaseApiError)) return false;\n\treturn error.code === \"23505\" || error.status === 409;\n}\nvar ConnectivityMonitor = class {\n\tstate = \"online\";\n\tbackoffMs;\n\tinitialBackoffMs;\n\tmaxBackoffMs;\n\tretryAt = 0;\n\ttimer;\n\tlisteners = /* @__PURE__ */ new Set();\n\trespectBackoff;\n\tnow;\n\tsetTimer;\n\tclearTimer;\n\t/** Called when the backoff window expires, to drive an automatic retry. */\n\tonRetryDue;\n\thandleOnline = () => {\n\t\tthis.retryAt = 0;\n\t\tthis.backoffMs = this.initialBackoffMs;\n\t\tthis.clearPendingTimer();\n\t\tthis.setState(\"online\");\n\t\tthis.onRetryDue?.();\n\t};\n\thandleOffline = () => {\n\t\tthis.setState(\"offline\");\n\t};\n\tconstructor(options = {}) {\n\t\tthis.initialBackoffMs = options.initialBackoffMs ?? 1e3;\n\t\tthis.maxBackoffMs = Math.max(this.initialBackoffMs, options.maxBackoffMs ?? 6e4);\n\t\tthis.backoffMs = this.initialBackoffMs;\n\t\tthis.respectBackoff = options.respectBackoff ?? true;\n\t\tthis.now = options.now ?? (() => Date.now());\n\t\tthis.setTimer = options.setTimer ?? ((fn, ms) => setTimeout(fn, ms));\n\t\tthis.clearTimer = options.clearTimer ?? ((handle) => clearTimeout(handle));\n\t\tif (typeof window !== \"undefined\" && typeof window.addEventListener === \"function\") {\n\t\t\twindow.addEventListener(\"online\", this.handleOnline);\n\t\t\twindow.addEventListener(\"offline\", this.handleOffline);\n\t\t}\n\t\tif (typeof navigator !== \"undefined\" && navigator.onLine === false) this.state = \"offline\";\n\t}\n\t/** What the app should be told: are we connected? */\n\tisOnline() {\n\t\tif (typeof navigator !== \"undefined\" && navigator.onLine === false) return false;\n\t\treturn this.state === \"online\";\n\t}\n\t/**\n\t* Should this request even be sent? False means \"answer from the local\n\t* store instead\" — the request would only burn a timeout to reach the same\n\t* conclusion the last one already did.\n\t*/\n\tshouldAttempt() {\n\t\tif (typeof navigator !== \"undefined\" && navigator.onLine === false) return false;\n\t\tif (this.state === \"online\" || !this.respectBackoff) return true;\n\t\treturn this.now() >= this.retryAt;\n\t}\n\t/** A request reached the server. */\n\tmarkSuccess() {\n\t\tthis.backoffMs = this.initialBackoffMs;\n\t\tthis.retryAt = 0;\n\t\tthis.clearPendingTimer();\n\t\tthis.setState(\"online\");\n\t}\n\t/** A request did not reach the server: we are offline until proven otherwise. */\n\tmarkFailure() {\n\t\tthis.deferRetry();\n\t\tthis.setState(\"offline\");\n\t}\n\t/**\n\t* Back off and try again later without claiming the connection is gone.\n\t* This is what a 429 or a 503 deserves — the server answered, so the app\n\t* is demonstrably online; it just should not hammer.\n\t*/\n\tdeferRetry() {\n\t\tconst jitter = .8 + Math.random() * .4;\n\t\tthis.retryAt = this.now() + this.backoffMs * jitter;\n\t\tconst delay = Math.max(0, this.retryAt - this.now());\n\t\tthis.backoffMs = Math.min(this.maxBackoffMs, this.backoffMs * 2);\n\t\tthis.scheduleRetry(delay);\n\t}\n\t/** Milliseconds until the next attempt is allowed; 0 when one is allowed now. */\n\tmsUntilRetry() {\n\t\tif (this.state === \"online\") return 0;\n\t\treturn Math.max(0, this.retryAt - this.now());\n\t}\n\tonChange(listener) {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\tdispose() {\n\t\tif (typeof window !== \"undefined\" && typeof window.removeEventListener === \"function\") {\n\t\t\twindow.removeEventListener(\"online\", this.handleOnline);\n\t\t\twindow.removeEventListener(\"offline\", this.handleOffline);\n\t\t}\n\t\tthis.clearPendingTimer();\n\t\tthis.listeners.clear();\n\t\tthis.onRetryDue = void 0;\n\t}\n\tscheduleRetry(delay) {\n\t\tthis.clearPendingTimer();\n\t\tif (!this.onRetryDue) return;\n\t\tthis.timer = this.setTimer(() => {\n\t\t\tthis.timer = void 0;\n\t\t\tthis.onRetryDue?.();\n\t\t}, delay);\n\t\tthis.timer.unref?.();\n\t}\n\tclearPendingTimer() {\n\t\tif (this.timer !== void 0) {\n\t\t\tthis.clearTimer(this.timer);\n\t\t\tthis.timer = void 0;\n\t\t}\n\t}\n\tsetState(next) {\n\t\tif (this.state === next) return;\n\t\tthis.state = next;\n\t\tconst online = this.isOnline();\n\t\tfor (const listener of this.listeners) listener(online);\n\t}\n};\n//#endregion\n//#region src/offline-store.ts\n/**\n* Monotonic within a tab, unique across tabs, and sortable as a plain string:\n* `<ms base36, padded>-<counter>-<random>`. The padding is what keeps\n* lexicographic order equal to chronological order, and the random suffix is\n* what stops two tabs from writing the same queue key in the same millisecond\n* — which would silently drop one of the two writes.\n*/\nvar mutationCounter = 0;\nfunction createMutationId(now = Date.now()) {\n\treturn `${now.toString(36).padStart(10, \"0\")}-${(mutationCounter = (mutationCounter + 1) % 1679616).toString(36).padStart(4, \"0\")}-${Math.random().toString(36).slice(2, 10).padStart(8, \"0\")}`;\n}\n/**\n* In-memory store: the default outside the browser and the workhorse of the\n* test suite. Values are deep-copied on the way in and out so a caller\n* mutating a returned row cannot silently edit the \"persisted\" copy — the\n* IndexedDB implementation gets the same guarantee for free from structured\n* cloning, and the two must not differ in aliasing behaviour.\n*/\nvar MemoryOfflineStore = class {\n\tcache = /* @__PURE__ */ new Map();\n\tqueue = /* @__PURE__ */ new Map();\n\tasync getCache(key) {\n\t\tconst entry = this.cache.get(key);\n\t\treturn entry ? structuredClone(entry) : void 0;\n\t}\n\tasync setCache(key, entry) {\n\t\tthis.cache.set(key, structuredClone(entry));\n\t}\n\tasync setCacheMany(entries) {\n\t\tfor (const { key, entry } of entries) this.cache.set(key, structuredClone(entry));\n\t}\n\tasync deleteCache(keys) {\n\t\tfor (const key of keys) this.cache.delete(key);\n\t}\n\tasync listCache(prefix) {\n\t\tconst out = [];\n\t\tfor (const [key, entry] of this.cache) if (key.startsWith(prefix)) out.push({\n\t\t\tkey,\n\t\t\tcachedAt: entry.cachedAt\n\t\t});\n\t\treturn out;\n\t}\n\tasync listCacheEntries(prefix) {\n\t\tconst out = [];\n\t\tfor (const [key, entry] of this.cache) if (key.startsWith(prefix)) out.push({\n\t\t\tkey,\n\t\t\t...structuredClone(entry)\n\t\t});\n\t\tout.sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);\n\t\treturn out;\n\t}\n\tasync enqueue(key, mutation) {\n\t\tthis.queue.set(key, structuredClone(mutation));\n\t}\n\tasync dequeue(key) {\n\t\tthis.queue.delete(key);\n\t}\n\tasync listQueue(prefix) {\n\t\treturn [...this.queue.entries()].filter(([key]) => key.startsWith(prefix)).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([, mutation]) => structuredClone(mutation));\n\t}\n\tasync clear(prefix) {\n\t\tfor (const key of [...this.cache.keys()]) if (key.startsWith(prefix)) this.cache.delete(key);\n\t\tfor (const key of [...this.queue.keys()]) if (key.startsWith(prefix)) this.queue.delete(key);\n\t}\n};\nvar IDB_NAME = \"rebase-offline\";\n/**\n* v2 introduced the normalized row cache and string mutation ids. A v1\n* database holds whole-response blobs under keys this version cannot read and\n* queue entries ordered by a numeric `seq` this version no longer writes, so\n* the upgrade drops both stores rather than trying to translate them. Offline\n* support had not shipped in a release when v2 landed, so nothing in the wild\n* loses a queued write to this.\n*/\nvar IDB_VERSION = 2;\nvar CACHE_STORE = \"cache\";\nvar QUEUE_STORE = \"queue\";\n/** The exclusive upper bound of an IDBKeyRange covering every key under `prefix`. */\nfunction prefixRange(prefix) {\n\treturn IDBKeyRange.bound(prefix, prefix + \"\", false, false);\n}\nfunction requestToPromise(request) {\n\treturn new Promise((resolve, reject) => {\n\t\trequest.onsuccess = () => resolve(request.result);\n\t\trequest.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error(\"IndexedDB request failed\"));\n\t});\n}\n/** Resolve when the whole transaction commits, not just when the last request returns. */\nfunction transactionDone(tx) {\n\treturn new Promise((resolve, reject) => {\n\t\ttx.oncomplete = () => resolve();\n\t\ttx.onabort = tx.onerror = () => reject(tx.error ?? /* @__PURE__ */ new Error(\"IndexedDB transaction failed\"));\n\t});\n}\n/**\n* IndexedDB-backed store — the browser default, so cached rows and queued\n* writes survive a reload or a browser restart. Everything lives in one\n* database with two object stores; keys are the manager's full prefixed\n* strings, so multiple users (scopes) share the database without ever\n* sharing entries.\n*/\nvar IndexedDBOfflineStore = class {\n\tdbPromise;\n\topen() {\n\t\tif (!this.dbPromise) this.dbPromise = new Promise((resolve, reject) => {\n\t\t\tconst request = indexedDB.open(IDB_NAME, IDB_VERSION);\n\t\t\trequest.onupgradeneeded = (event) => {\n\t\t\t\tconst db = request.result;\n\t\t\t\tif (event.oldVersion > 0 && event.oldVersion < 2) {\n\t\t\t\t\tif (db.objectStoreNames.contains(CACHE_STORE)) db.deleteObjectStore(CACHE_STORE);\n\t\t\t\t\tif (db.objectStoreNames.contains(QUEUE_STORE)) db.deleteObjectStore(QUEUE_STORE);\n\t\t\t\t}\n\t\t\t\tif (!db.objectStoreNames.contains(CACHE_STORE)) db.createObjectStore(CACHE_STORE);\n\t\t\t\tif (!db.objectStoreNames.contains(QUEUE_STORE)) db.createObjectStore(QUEUE_STORE);\n\t\t\t};\n\t\t\trequest.onsuccess = () => {\n\t\t\t\tconst db = request.result;\n\t\t\t\tdb.onversionchange = () => {\n\t\t\t\t\tdb.close();\n\t\t\t\t\tthis.dbPromise = void 0;\n\t\t\t\t};\n\t\t\t\tresolve(db);\n\t\t\t};\n\t\t\trequest.onerror = () => {\n\t\t\t\tthis.dbPromise = void 0;\n\t\t\t\treject(request.error ?? /* @__PURE__ */ new Error(\"Failed to open IndexedDB\"));\n\t\t\t};\n\t\t\trequest.onblocked = () => {\n\t\t\t\tthis.dbPromise = void 0;\n\t\t\t\treject(/* @__PURE__ */ new Error(\"IndexedDB upgrade blocked by another tab\"));\n\t\t\t};\n\t\t});\n\t\treturn this.dbPromise;\n\t}\n\tasync store(name, mode) {\n\t\treturn (await this.open()).transaction(name, mode).objectStore(name);\n\t}\n\tasync getCache(key) {\n\t\treturn await requestToPromise((await this.store(CACHE_STORE, \"readonly\")).get(key));\n\t}\n\tasync setCache(key, entry) {\n\t\tawait requestToPromise((await this.store(CACHE_STORE, \"readwrite\")).put(entry, key));\n\t}\n\tasync setCacheMany(entries) {\n\t\tif (entries.length === 0) return;\n\t\tconst store = await this.store(CACHE_STORE, \"readwrite\");\n\t\tfor (const { key, entry } of entries) store.put(entry, key);\n\t\tawait transactionDone(store.transaction);\n\t}\n\tasync deleteCache(keys) {\n\t\tif (keys.length === 0) return;\n\t\tconst store = await this.store(CACHE_STORE, \"readwrite\");\n\t\tfor (const key of keys) store.delete(key);\n\t\tawait transactionDone(store.transaction);\n\t}\n\tasync listCache(prefix) {\n\t\tconst store = await this.store(CACHE_STORE, \"readonly\");\n\t\tconst [keys, entries] = await Promise.all([requestToPromise(store.getAllKeys(prefixRange(prefix))), requestToPromise(store.getAll(prefixRange(prefix)))]);\n\t\treturn keys.map((key, i) => ({\n\t\t\tkey: String(key),\n\t\t\tcachedAt: entries[i]?.cachedAt ?? 0\n\t\t}));\n\t}\n\tasync listCacheEntries(prefix) {\n\t\tconst store = await this.store(CACHE_STORE, \"readonly\");\n\t\tconst [keys, entries] = await Promise.all([requestToPromise(store.getAllKeys(prefixRange(prefix))), requestToPromise(store.getAll(prefixRange(prefix)))]);\n\t\treturn keys.map((key, i) => {\n\t\t\tconst entry = entries[i];\n\t\t\treturn {\n\t\t\t\tkey: String(key),\n\t\t\t\tvalue: entry?.value,\n\t\t\t\tcachedAt: entry?.cachedAt ?? 0\n\t\t\t};\n\t\t});\n\t}\n\tasync enqueue(key, mutation) {\n\t\tawait requestToPromise((await this.store(QUEUE_STORE, \"readwrite\")).put(mutation, key));\n\t}\n\tasync dequeue(key) {\n\t\tawait requestToPromise((await this.store(QUEUE_STORE, \"readwrite\")).delete(key));\n\t}\n\tasync listQueue(prefix) {\n\t\treturn await requestToPromise((await this.store(QUEUE_STORE, \"readonly\")).getAll(prefixRange(prefix)));\n\t}\n\tasync clear(prefix) {\n\t\tawait requestToPromise((await this.store(CACHE_STORE, \"readwrite\")).delete(prefixRange(prefix)));\n\t\tawait requestToPromise((await this.store(QUEUE_STORE, \"readwrite\")).delete(prefixRange(prefix)));\n\t}\n};\n//#endregion\n//#region src/offline-query.ts\n/**\n* A local evaluator for `FindParams`, so cached rows can answer a query the\n* client has never sent to the server — and so a row written offline shows up\n* in every filtered list it belongs to, not just in unfiltered ones.\n*\n* This mirrors the Postgres driver's semantics rather than JavaScript's:\n*\n* - Comparing against NULL is *unknown*, not false-or-true. `status != \"done\"`\n* excludes rows where `status` is null, exactly as SQL does — a JS `!==`\n* would have included them.\n* - `ORDER BY` puts nulls last ascending and first descending, which is the\n* Postgres default.\n* - The wire format carries no types, so values arriving as strings are\n* compared numerically against numeric columns and as instants against\n* date columns. `[\"==\", \"3\"]` matches the number `3`, as it does server-side.\n*\n* Two things it deliberately approximates, both flagged by\n* {@link isExactlyEvaluable}: `searchString` becomes a case-insensitive\n* substring scan over the row's string fields (the server runs real full-text\n* search over the collection's configured columns), and `include` cannot be\n* evaluated at all, because the related rows live in collections this query\n* knows nothing about.\n*/\nvar collator = typeof Intl !== \"undefined\" && typeof Intl.Collator === \"function\" ? new Intl.Collator(void 0, {\n\tnumeric: false,\n\tsensitivity: \"variant\"\n}) : void 0;\nfunction isNullish(value) {\n\treturn value === null || value === void 0;\n}\n/**\n* Reduce a value to something comparable. Relations compare by the id they\n* point at — the column holds a foreign key, so that is what the server\n* compares too.\n*/\nfunction toComparable(value) {\n\tif (value instanceof Date) return value.getTime();\n\tif (value instanceof EntityRelation) return value.id;\n\tif (value && typeof value === \"object\") {\n\t\tconst record = value;\n\t\tif (typeof record.__type === \"string\" && \"id\" in record) return record.id;\n\t}\n\treturn value;\n}\n/**\n* Three-way compare with SQL's type coercion but not its collation. Returns\n* `undefined` when the two values are not ordered relative to each other,\n* which is how NULL propagates through a comparison.\n*/\nfunction compareValues(a, b) {\n\tconst left = toComparable(a);\n\tconst right = toComparable(b);\n\tif (isNullish(left) || isNullish(right)) return void 0;\n\tif (typeof left === \"boolean\" || typeof right === \"boolean\") return (left === true || left === \"true\" || left === 1 ? 1 : 0) - (right === true || right === \"true\" || right === 1 ? 1 : 0);\n\tconst leftNum = typeof left === \"number\" ? left : numericOrNaN(left);\n\tconst rightNum = typeof right === \"number\" ? right : numericOrNaN(right);\n\tif (!Number.isNaN(leftNum) && !Number.isNaN(rightNum)) return leftNum < rightNum ? -1 : leftNum > rightNum ? 1 : 0;\n\tif (typeof left === \"number\" || typeof right === \"number\") {\n\t\tconst leftTime = toTime(left);\n\t\tconst rightTime = toTime(right);\n\t\tif (leftTime !== void 0 && rightTime !== void 0) return leftTime < rightTime ? -1 : leftTime > rightTime ? 1 : 0;\n\t}\n\tconst leftStr = String(left);\n\tconst rightStr = String(right);\n\tif (collator) return collator.compare(leftStr, rightStr);\n\treturn leftStr < rightStr ? -1 : leftStr > rightStr ? 1 : 0;\n}\nfunction numericOrNaN(value) {\n\tif (typeof value === \"number\") return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst n = Number(value);\n\t\treturn Number.isNaN(n) ? NaN : n;\n\t}\n\tif (typeof value === \"bigint\") return Number(value);\n\treturn NaN;\n}\nfunction toTime(value) {\n\tif (typeof value === \"number\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst t = Date.parse(value);\n\t\treturn Number.isNaN(t) ? void 0 : t;\n\t}\n}\n/** Equality with the wire's type erasure allowed for, but never across NULL. */\nfunction looseEquals(a, b) {\n\tconst left = toComparable(a);\n\tconst right = toComparable(b);\n\tif (isNullish(left) || isNullish(right)) return isNullish(left) && isNullish(right);\n\tif (left === right) return true;\n\treturn compareValues(left, right) === 0;\n}\n/**\n* Translate a SQL `LIKE` pattern to an anchored regular expression.\n* `%` matches any run of characters, `_` exactly one, and a backslash escapes\n* either of them.\n*/\nfunction likeToRegExp(pattern, caseInsensitive) {\n\tlet source = \"^\";\n\tfor (let i = 0; i < pattern.length; i++) {\n\t\tconst char = pattern[i];\n\t\tif (char === \"\\\\\" && i + 1 < pattern.length) {\n\t\t\tsource += pattern[i + 1].replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\t\t\ti++;\n\t\t} else if (char === \"%\") source += \"[\\\\s\\\\S]*\";\n\t\telse if (char === \"_\") source += \"[\\\\s\\\\S]\";\n\t\telse source += char.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\t}\n\treturn new RegExp(source + \"$\", caseInsensitive ? \"i\" : \"\");\n}\nfunction asArray(value) {\n\tif (Array.isArray(value)) return value;\n\tif (value === void 0) return [];\n\treturn [value];\n}\n/** Evaluate one canonical operator against one row value. */\nfunction matchesOperator(rowValue, op, filterValue) {\n\tswitch (op) {\n\t\tcase \"is-null\": return isNullish(rowValue);\n\t\tcase \"is-not-null\": return !isNullish(rowValue);\n\t\tcase \"==\": return looseEquals(rowValue, filterValue);\n\t\tcase \"!=\":\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\treturn !looseEquals(rowValue, filterValue);\n\t\tcase \"<\":\n\t\tcase \"<=\":\n\t\tcase \">\":\n\t\tcase \">=\": {\n\t\t\tconst cmp = compareValues(rowValue, filterValue);\n\t\t\tif (cmp === void 0) return false;\n\t\t\tif (op === \"<\") return cmp < 0;\n\t\t\tif (op === \"<=\") return cmp <= 0;\n\t\t\tif (op === \">\") return cmp > 0;\n\t\t\treturn cmp >= 0;\n\t\t}\n\t\tcase \"in\":\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\treturn asArray(filterValue).some((v) => looseEquals(rowValue, v));\n\t\tcase \"not-in\":\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\treturn !asArray(filterValue).some((v) => looseEquals(rowValue, v));\n\t\tcase \"array-contains\":\n\t\t\tif (!Array.isArray(rowValue)) return false;\n\t\t\treturn rowValue.some((v) => looseEquals(v, filterValue));\n\t\tcase \"array-contains-any\": {\n\t\t\tif (!Array.isArray(rowValue)) return false;\n\t\t\tconst wanted = asArray(filterValue);\n\t\t\treturn rowValue.some((v) => wanted.some((w) => looseEquals(v, w)));\n\t\t}\n\t\tcase \"like\":\n\t\tcase \"not-like\":\n\t\tcase \"ilike\":\n\t\tcase \"not-ilike\": {\n\t\t\tif (isNullish(rowValue)) return false;\n\t\t\tconst insensitive = op === \"ilike\" || op === \"not-ilike\";\n\t\t\tconst negated = op === \"not-like\" || op === \"not-ilike\";\n\t\t\tconst matched = likeToRegExp(String(filterValue), insensitive).test(String(rowValue));\n\t\t\treturn negated ? !matched : matched;\n\t\t}\n\t\tdefault: return true;\n\t}\n}\nfunction isTuple(value) {\n\treturn Array.isArray(value) && value.length === 2 && typeof value[0] === \"string\" && toCanonicalOp(value[0]) !== void 0;\n}\n/** Evaluate a `where` clause: every field, and every tuple on a field, AND-ed. */\nfunction matchesWhere(row, where) {\n\tif (!where) return true;\n\tfor (const [field, condition] of Object.entries(where)) {\n\t\tif (condition === void 0) continue;\n\t\tconst tuples = isTuple(condition) ? [condition] : Array.isArray(condition) ? condition.filter(isTuple) : [];\n\t\tfor (const [rawOp, value] of tuples) {\n\t\t\tconst op = toCanonicalOp(rawOp) ?? rawOp;\n\t\t\tif (!matchesOperator(row[field], op, value)) return false;\n\t\t}\n\t}\n\treturn true;\n}\n/** Evaluate a nested and/or tree. */\nfunction matchesLogical(row, condition) {\n\tif (!condition) return true;\n\tif (\"type\" in condition) {\n\t\tconst children = condition.conditions ?? [];\n\t\tif (children.length === 0) return true;\n\t\treturn condition.type === \"or\" ? children.some((c) => matchesLogical(row, c)) : children.every((c) => matchesLogical(row, c));\n\t}\n\tconst op = toCanonicalOp(condition.operator) ?? condition.operator;\n\treturn matchesOperator(row[condition.column], op, condition.value);\n}\n/**\n* Approximate the server's full-text search with a case-insensitive substring\n* scan over the row's own string fields. Narrower than the real thing (no\n* stemming, no configured search columns), and it never matches a field the\n* cached row does not carry — a local list may therefore be missing rows the\n* server would have returned, which is why {@link isExactlyEvaluable} refuses\n* to call a search query exact.\n*/\nfunction matchesSearch(row, searchString) {\n\tif (!searchString) return true;\n\tconst needle = searchString.trim().toLowerCase();\n\tif (!needle) return true;\n\tfor (const value of Object.values(row)) {\n\t\tif (typeof value === \"string\" && value.toLowerCase().includes(needle)) return true;\n\t\tif (typeof value === \"number\" && String(value).includes(needle)) return true;\n\t}\n\treturn false;\n}\n/** Does this row belong in the result set for `params`, ignoring pagination? */\nfunction matchesParams(row, params) {\n\tif (!params) return true;\n\treturn matchesWhere(row, params.where) && matchesLogical(row, params.logical) && matchesSearch(row, params.searchString);\n}\n/**\n* Sort in place, Postgres-style: nulls last ascending, first descending, with\n* the row id as a tiebreak so paging through an unsorted-but-equal run does\n* not shuffle rows between pages.\n*/\nfunction sortRows(rows, orderBy) {\n\tif (!orderBy) return rows;\n\tconst [field, direction = \"asc\"] = orderBy;\n\tconst sign = direction === \"desc\" ? -1 : 1;\n\treturn rows.sort((a, b) => {\n\t\tconst av = a[field];\n\t\tconst bv = b[field];\n\t\tconst aNull = isNullish(toComparable(av));\n\t\tconst bNull = isNullish(toComparable(bv));\n\t\tif (aNull || bNull) {\n\t\t\tif (aNull && bNull) return tiebreak(a, b);\n\t\t\treturn (aNull ? 1 : -1) * (direction === \"desc\" ? -1 : 1);\n\t\t}\n\t\tconst cmp = compareValues(av, bv);\n\t\tif (cmp === void 0 || cmp === 0) return tiebreak(a, b);\n\t\treturn cmp * sign;\n\t});\n}\nfunction tiebreak(a, b) {\n\treturn compareValues(a.id, b.id) ?? 0;\n}\n/** Resolve `page`/`offset`/`limit` the way the server does. */\nfunction resolvePagination(params) {\n\tconst limit = params?.limit ?? 20;\n\treturn {\n\t\tlimit,\n\t\toffset: params?.page != null ? Math.max(0, (params.page - 1) * limit) : params?.offset ?? 0\n\t};\n}\n/**\n* Can a locally evaluated answer to `params` be trusted to match the server's,\n* assuming the cache holds every row of the collection?\n*\n* `include` pulls in rows from other collections that this evaluator never\n* sees, and `searchString` is only approximated — both make the local answer a\n* best effort rather than an equivalent one.\n*/\nfunction isExactlyEvaluable(params) {\n\tif (!params) return true;\n\tif (params.include && params.include.length > 0) return false;\n\tif (params.searchString) return false;\n\treturn true;\n}\n/** Run a full query — filter, sort, paginate — over a set of rows. */\nfunction runLocalQuery(rows, params) {\n\tconst matched = rows.filter((row) => matchesParams(row, params));\n\tsortRows(matched, params?.orderBy);\n\tconst { limit, offset } = resolvePagination(params);\n\tconst page = matched.slice(offset, offset + limit);\n\treturn {\n\t\tdata: page,\n\t\tmeta: {\n\t\t\ttotal: matched.length,\n\t\t\tlimit,\n\t\t\toffset,\n\t\t\thasMore: offset + page.length < matched.length\n\t\t}\n\t};\n}\n//#endregion\n//#region src/offline.ts\n/** True when a read failed because there was neither network nor local data. */\nfunction isOfflineError(error) {\n\treturn error instanceof RebaseApiError && error.code === \"offline\";\n}\nfunction offlineError(message) {\n\treturn new RebaseApiError(message, {\n\t\tstatus: 0,\n\t\tcode: \"offline\"\n\t});\n}\nfunction generateOfflineId() {\n\tif (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return crypto.randomUUID();\n\treturn `off-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\nvar MISSING = \"\\0missing\";\nvar OfflineManager = class {\n\tstore;\n\tmaxCachedQueries;\n\tmaxCachedRows;\n\tmaxRetries;\n\tonSyncError;\n\tcreateInner;\n\tinners = /* @__PURE__ */ new Map();\n\tconnectivity;\n\tscope = \"anon\";\n\t/** The local database: normalized rows and query snapshots per collection. */\n\tcollections = /* @__PURE__ */ new Map();\n\t/** In-memory mirror of the current scope's queue, in replay order. */\n\tqueue = [];\n\t/**\n\t* The mutation currently on the wire, if any.\n\t*\n\t* `flush` awaits `replay(op)` with `op` still at the head of `queue`, so for\n\t* the whole duration of that request the in-flight op is also the queue's\n\t* *tail* whenever it is the only entry. Both shortcuts in `enqueue` reach\n\t* for the tail, and neither may touch an op the server is already reading:\n\t*\n\t* - Coalescing an update into it mutates a payload that has already been\n\t* serialized and sent, and `drop` then removes the whole entry on ACK —\n\t* so the second edit is neither sent nor kept. A silently lost write.\n\t* - Cancelling it out against a delete assumes the server never saw the\n\t* create. It is seeing it right now, so the row would be created and the\n\t* delete never queued — an orphan row nothing will ever remove.\n\t*\n\t* Guarding on the id rather than on a boolean keeps this correct if the\n\t* flush loop ever sends more than one op at a time.\n\t*/\n\tinFlightId = null;\n\tqueueLoad;\n\t/** Serializes enqueues so concurrent writes keep the order the app made them. */\n\tenqueueChain = Promise.resolve();\n\tflushPromise;\n\tqueueListeners = /* @__PURE__ */ new Set();\n\tstatusListeners = /* @__PURE__ */ new Set();\n\tobservers = /* @__PURE__ */ new Map();\n\trefreshPending = /* @__PURE__ */ new Set();\n\trevCounter = 0;\n\tdisposed = false;\n\tcurrentStatus = {\n\t\tonline: true,\n\t\tsyncing: false,\n\t\tpending: 0\n\t};\n\tchannel;\n\ttabId = createMutationId();\n\tapi;\n\tconstructor(config, createInner) {\n\t\tthis.store = config.store ?? (typeof indexedDB !== \"undefined\" ? new IndexedDBOfflineStore() : new MemoryOfflineStore());\n\t\tthis.maxCachedQueries = config.maxCachedQueriesPerCollection ?? 50;\n\t\tthis.maxCachedRows = config.maxCachedRowsPerCollection ?? 5e3;\n\t\tthis.maxRetries = config.maxRetries ?? 5;\n\t\tthis.onSyncError = config.onSyncError;\n\t\tthis.createInner = createInner;\n\t\tconst maxBackoffMs = config.syncIntervalMs ?? 6e4;\n\t\tthis.connectivity = new ConnectivityMonitor({\n\t\t\tmaxBackoffMs: Math.max(1e3, maxBackoffMs),\n\t\t\trespectBackoff: maxBackoffMs > 0\n\t\t});\n\t\tif (maxBackoffMs > 0) this.connectivity.onRetryDue = () => {\n\t\t\tthis.sync().catch(() => void 0);\n\t\t};\n\t\tthis.connectivity.onChange((online) => {\n\t\t\tthis.patchStatus({ online });\n\t\t\tif (online) this.revalidateAll();\n\t\t});\n\t\tthis.currentStatus.online = this.connectivity.isOnline();\n\t\tif ((config.crossTab ?? this.store instanceof IndexedDBOfflineStore) && typeof BroadcastChannel !== \"undefined\") try {\n\t\t\tthis.channel = new BroadcastChannel(\"rebase-offline\");\n\t\t\tthis.channel.onmessage = (event) => this.onBroadcast(event.data);\n\t\t\tthis.channel.unref?.();\n\t\t} catch {}\n\t\tthis.api = {\n\t\t\tsync: () => this.sync(),\n\t\t\tpending: async () => {\n\t\t\t\tawait this.ensureQueueLoaded();\n\t\t\t\treturn this.queue.map((m) => structuredClone(m));\n\t\t\t},\n\t\t\tstatus: () => ({ ...this.currentStatus }),\n\t\t\tonStatusChange: (listener) => {\n\t\t\t\tthis.statusListeners.add(listener);\n\t\t\t\treturn () => this.statusListeners.delete(listener);\n\t\t\t},\n\t\t\tclear: async () => {\n\t\t\t\tawait this.store.clear(`${this.scope}|`);\n\t\t\t\tthis.queue = [];\n\t\t\t\tthis.resetCollections();\n\t\t\t\tthis.patchStatus({\n\t\t\t\t\tpending: 0,\n\t\t\t\t\tlastError: void 0\n\t\t\t\t});\n\t\t\t\tthis.notifyQueue();\n\t\t\t\tfor (const slug of this.observers.keys()) this.notifyCollection(slug, false);\n\t\t\t},\n\t\t\tonQueueChange: (listener) => {\n\t\t\t\tthis.queueListeners.add(listener);\n\t\t\t\treturn () => this.queueListeners.delete(listener);\n\t\t\t}\n\t\t};\n\t}\n\t/**\n\t* Cache and queue are partitioned per signed-in user: cached rows are\n\t* RLS-filtered for the user who fetched them, and queued writes must\n\t* replay under the credentials that made them — so neither may ever leak\n\t* across a sign-out/sign-in on a shared browser.\n\t*/\n\tsetScope(uid) {\n\t\tconst next = uid || \"anon\";\n\t\tif (next === this.scope) return;\n\t\tthis.scope = next;\n\t\tthis.queueLoad = void 0;\n\t\tthis.queue = [];\n\t\tthis.resetCollections();\n\t\tthis.patchStatus({\n\t\t\tpending: 0,\n\t\t\tlastError: void 0\n\t\t});\n\t\tthis.notifyQueue();\n\t\tfor (const slug of this.observers.keys()) this.notifyCollection(slug, false);\n\t\tthis.revalidateAll();\n\t\tthis.sync().catch(() => void 0);\n\t}\n\t/**\n\t* Throw away every local row, for a scope change or an explicit clear.\n\t*\n\t* The state objects are replaced rather than emptied, so a load still in\n\t* flight for the previous user fails its identity check and discards what\n\t* it read instead of grafting it onto the new one. The replacements are\n\t* marked ready: nothing needs loading until something asks, and observers\n\t* have to be told *now* that the rows they are showing are gone.\n\t*/\n\tresetCollections() {\n\t\tconst slugs = [...this.collections.keys()];\n\t\tthis.collections = /* @__PURE__ */ new Map();\n\t\tfor (const slug of slugs) this.collections.set(slug, {\n\t\t\trows: /* @__PURE__ */ new Map(),\n\t\t\tsnapshots: /* @__PURE__ */ new Map(),\n\t\t\tfresh: /* @__PURE__ */ new Set(),\n\t\t\tfreshRows: /* @__PURE__ */ new Set(),\n\t\t\tabsent: /* @__PURE__ */ new Set(),\n\t\t\tready: true\n\t\t});\n\t}\n\t/** Release listeners, timers and the cross-tab channel (client.close()). */\n\tdispose() {\n\t\tthis.disposed = true;\n\t\tthis.connectivity.dispose();\n\t\ttry {\n\t\t\tthis.channel?.close();\n\t\t} catch {}\n\t\tthis.observers.clear();\n\t\tthis.queueListeners.clear();\n\t\tthis.statusListeners.clear();\n\t}\n\twrap(slug, inner) {\n\t\tthis.inners.set(slug, inner);\n\t\tconst wrapped = {\n\t\t\tfind: async (params) => {\n\t\t\t\tconst state = await this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst res = await inner.find(params);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, res.data ?? []);\n\t\t\t\t\tconst snapshot = this.recordSnapshot(slug, params, res);\n\t\t\t\t\tconst answer = this.answer(slug, params, snapshot);\n\t\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: answer.data,\n\t\t\t\t\t\tmeta: answer.meta\n\t\t\t\t\t};\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) {\n\t\t\t\t\t\tif (isRetryableError(error) && this.hasLocalAnswer(state, slug, params)) {\n\t\t\t\t\t\t\tconst answer = this.answer(slug, params, this.snapshotFor(slug, params));\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tdata: answer.data,\n\t\t\t\t\t\t\t\tmeta: answer.meta\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst answer = this.localFind(slug, params);\n\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\treturn {\n\t\t\t\t\tdata: answer.data,\n\t\t\t\t\tmeta: answer.meta\n\t\t\t\t};\n\t\t\t},\n\t\t\titerate: (params) => paginateFind((p) => wrapped.find(p), params, slug),\n\t\t\tfindAll: (params) => collectAllPages((p) => wrapped.find(p), params, slug),\n\t\t\tfindById: async (id) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst row = await inner.findById(id);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tif (row !== void 0) await this.ingest(slug, [row]);\n\t\t\t\t\telse if (!this.hasPending(slug, id)) this.removeLocalRow(slug, id, true);\n\t\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\t\treturn this.localRow(slug, id);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst local = this.localRow(slug, id);\n\t\t\t\tif (local !== void 0 || this.hasPending(slug, id)) return local;\n\t\t\t\tif (this.collections.get(slug)?.absent.has(String(id))) return void 0;\n\t\t\t\tthrow offlineError(`Offline: \"${slug}\" row ${String(id)} is not in the local database.`);\n\t\t\t},\n\t\t\tcreate: async (data, id) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst row = await inner.create(data, id);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, [row]);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t\t\treturn row;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst providedId = id ?? data.id;\n\t\t\t\tconst rowId = providedId ?? generateOfflineId();\n\t\t\t\tconst row = {\n\t\t\t\t\t...data,\n\t\t\t\t\tid: rowId\n\t\t\t\t};\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"create\",\n\t\t\t\t\tid: rowId,\n\t\t\t\t\tdata: row,\n\t\t\t\t\tgeneratedId: providedId === void 0,\n\t\t\t\t\trollback: { rows: { [String(rowId)]: this.rawLocalRow(slug, rowId) ?? null } }\n\t\t\t\t});\n\t\t\t\tthis.setLocalRow(slug, rowId, row);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\treturn row;\n\t\t\t},\n\t\t\tcreateMany: async (data, options) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (!Array.isArray(data)) throw new TypeError(\"createMany expects an array of records.\");\n\t\t\t\tif (data.length === 0) return [];\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst rows = await inner.createMany(data, options);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, rows);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t\t\treturn rows;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst rows = data.map((r) => ({\n\t\t\t\t\t...r,\n\t\t\t\t\tid: r.id ?? generateOfflineId()\n\t\t\t\t}));\n\t\t\t\tconst rollback = {};\n\t\t\t\tfor (const row of rows) {\n\t\t\t\t\tconst key = String(row.id);\n\t\t\t\t\trollback[key] = this.rawLocalRow(slug, row.id) ?? null;\n\t\t\t\t}\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"createMany\",\n\t\t\t\t\tdata: rows,\n\t\t\t\t\tupsert: options?.upsert,\n\t\t\t\t\trollback: { rows: rollback }\n\t\t\t\t});\n\t\t\t\tfor (const row of rows) this.setLocalRow(slug, row.id, row);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\treturn rows;\n\t\t\t},\n\t\t\tupdate: async (id, data) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt() && !this.hasPending(slug, id)) try {\n\t\t\t\t\tconst row = await inner.update(id, data);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.ingest(slug, [row]);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\treturn row;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst base = this.rawLocalRow(slug, id);\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"update\",\n\t\t\t\t\tid,\n\t\t\t\t\tdata,\n\t\t\t\t\trollback: { rows: { [String(id)]: base ?? null } }\n\t\t\t\t});\n\t\t\t\tconst optimistic = {\n\t\t\t\t\t...base ?? {},\n\t\t\t\t\t...data,\n\t\t\t\t\tid\n\t\t\t\t};\n\t\t\t\tthis.setLocalRow(slug, id, optimistic);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\treturn optimistic;\n\t\t\t},\n\t\t\tdelete: async (id) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt() && !this.hasPending(slug, id)) try {\n\t\t\t\t\tawait inner.delete(id);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tthis.removeLocalRow(slug, id, true);\n\t\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tawait this.enqueue({\n\t\t\t\t\tcollection: slug,\n\t\t\t\t\ttype: \"delete\",\n\t\t\t\t\tid,\n\t\t\t\t\trollback: { rows: { [String(id)]: this.rawLocalRow(slug, id) ?? null } }\n\t\t\t\t});\n\t\t\t\tthis.removeLocalRow(slug, id);\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t},\n\t\t\tcount: async (params) => {\n\t\t\t\tawait this.ensureCollection(slug);\n\t\t\t\tif (this.connectivity.shouldAttempt()) try {\n\t\t\t\t\tconst n = await inner.count(params);\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tthis.writeCache(this.countKey(slug, params), n);\n\t\t\t\t\treturn Math.max(0, n + this.pendingDelta(slug, params));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isNetworkError(error)) throw error;\n\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t}\n\t\t\t\tconst cached = await this.readCache(this.countKey(slug, params));\n\t\t\t\tif (cached !== void 0) return Math.max(0, cached + this.pendingDelta(slug, params));\n\t\t\t\tconst state = this.collections.get(slug);\n\t\t\t\tif (state && state.rows.size > 0) return runLocalQuery([...state.rows.values()].map((e) => e.row), params).meta.total;\n\t\t\t\tthrow offlineError(`Offline: no cached count for \"${slug}\".`);\n\t\t\t},\n\t\t\tobserve: (params, onResult, onError, options) => this.observe(slug, wrapped, inner, params, onResult, onError, options),\n\t\t\tobserveById: (id, onResult, onError, options) => this.observeById(slug, wrapped, inner, id, onResult, onError, options),\n\t\t\twhere(columnOrCondition, operator, value) {\n\t\t\t\tconst builder = new SDKQueryBuilder(wrapped);\n\t\t\t\tif (typeof columnOrCondition === \"object\") return builder.where(columnOrCondition);\n\t\t\t\treturn builder.where(columnOrCondition, operator, value);\n\t\t\t},\n\t\t\torderBy: (column, direction) => new SDKQueryBuilder(wrapped).orderBy(column, direction),\n\t\t\tlimit: (count) => new SDKQueryBuilder(wrapped).limit(count),\n\t\t\toffset: (count) => new SDKQueryBuilder(wrapped).offset(count),\n\t\t\tsearch: (searchString) => new SDKQueryBuilder(wrapped).search(searchString),\n\t\t\tinclude: (...relations) => new SDKQueryBuilder(wrapped).include(...relations)\n\t\t};\n\t\tif (inner.listen) wrapped.listen = (params, onUpdate, onError) => inner.listen(params, (response) => {\n\t\t\tthis.ingest(slug, response.data ?? []).then(() => this.notifyCollection(slug, false));\n\t\t\tonUpdate(response);\n\t\t}, onError);\n\t\tif (inner.listenById) wrapped.listenById = (id, onUpdate, onError) => inner.listenById(id, (row) => {\n\t\t\tif (row) this.ingest(slug, [row]).then(() => this.notifyCollection(slug, false));\n\t\t\tonUpdate(row);\n\t\t}, onError);\n\t\treturn wrapped;\n\t}\n\tobserve(slug, wrapped, inner, params, onResult, onError, options) {\n\t\tlet closed = false;\n\t\tlet unlisten;\n\t\tconst observer = {\n\t\t\tslug,\n\t\t\tparams,\n\t\t\tsettled: false,\n\t\t\trefresh: () => wrapped.find(params).catch(() => void 0),\n\t\t\temit: () => {\n\t\t\t\tif (closed || !this.collections.get(slug)?.ready) return;\n\t\t\t\tconst result = this.answer(slug, params, this.snapshotFor(slug, params));\n\t\t\t\tconst signature = `${result.fromCache ? \"c\" : \"s\"}${result.hasPendingWrites ? \"p\" : \"-\"}` + this.signature(slug, result.data, result.meta.total);\n\t\t\t\tif (observer.settled && signature === observer.signature) return;\n\t\t\t\tobserver.signature = signature;\n\t\t\t\tobserver.settled = true;\n\t\t\t\tonResult(observer.error ? {\n\t\t\t\t\t...result,\n\t\t\t\t\terror: observer.error\n\t\t\t\t} : result);\n\t\t\t}\n\t\t};\n\t\tthis.observersFor(slug).add(observer);\n\t\t(async () => {\n\t\t\tawait this.ensureCollection(slug);\n\t\t\tif (closed) return;\n\t\t\tif (this.hasLocalAnswer(this.collections.get(slug), slug, params)) observer.emit();\n\t\t\ttry {\n\t\t\t\tawait wrapped.find(params);\n\t\t\t\tobserver.error = void 0;\n\t\t\t} catch (error) {\n\t\t\t\tobserver.error = error;\n\t\t\t\tif (closed) return;\n\t\t\t\tif (!observer.settled) {\n\t\t\t\t\tonError?.(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!closed) observer.emit();\n\t\t})();\n\t\tif (options?.realtime !== false && inner.listen) unlisten = inner.listen(params, (response) => {\n\t\t\tthis.ingest(slug, response.data ?? []).then(() => {\n\t\t\t\tthis.recordSnapshot(slug, params, response);\n\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t});\n\t\t}, onError);\n\t\treturn () => {\n\t\t\tclosed = true;\n\t\t\tthis.observersFor(slug).delete(observer);\n\t\t\tunlisten?.();\n\t\t};\n\t}\n\tobserveById(slug, wrapped, inner, id, onResult, onError, options) {\n\t\tlet closed = false;\n\t\tlet unlisten;\n\t\tconst observer = {\n\t\t\tslug,\n\t\t\tid,\n\t\t\tsettled: false,\n\t\t\trefresh: () => wrapped.findById(id).catch(() => void 0),\n\t\t\temit: () => {\n\t\t\t\tif (closed || !this.collections.get(slug)?.ready) return;\n\t\t\t\tconst row = this.localRow(slug, id);\n\t\t\t\tconst entry = this.collections.get(slug)?.rows.get(String(id));\n\t\t\t\tconst fromCache = !this.collections.get(slug)?.freshRows.has(String(id));\n\t\t\t\tconst hasPendingWrites = this.hasPending(slug, id);\n\t\t\t\tconst signature = `${fromCache ? \"c\" : \"s\"}${hasPendingWrites ? \"p\" : \"-\"}|` + (row === void 0 ? MISSING : `${String(id)}:${entry?.rev ?? 0}`);\n\t\t\t\tif (observer.settled && signature === observer.signature) return;\n\t\t\t\tobserver.signature = signature;\n\t\t\t\tobserver.settled = true;\n\t\t\t\tonResult(row, {\n\t\t\t\t\tfromCache,\n\t\t\t\t\thasPendingWrites\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t\tthis.observersFor(slug).add(observer);\n\t\t(async () => {\n\t\t\tawait this.ensureCollection(slug);\n\t\t\tif (closed) return;\n\t\t\tif (this.localRow(slug, id) !== void 0) observer.emit();\n\t\t\ttry {\n\t\t\t\tawait wrapped.findById(id);\n\t\t\t} catch (error) {\n\t\t\t\tif (closed) return;\n\t\t\t\tif (!observer.settled) {\n\t\t\t\t\tonError?.(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!closed) observer.emit();\n\t\t})();\n\t\tif (options?.realtime !== false && inner.listenById) unlisten = inner.listenById(id, (row) => {\n\t\t\tif (!row) {\n\t\t\t\tif (!this.hasPending(slug, id)) this.removeLocalRow(slug, id, true);\n\t\t\t\tthis.notifyCollection(slug, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.ingest(slug, [row]).then(() => this.notifyCollection(slug, false));\n\t\t}, onError);\n\t\treturn () => {\n\t\t\tclosed = true;\n\t\t\tthis.observersFor(slug).delete(observer);\n\t\t\tunlisten?.();\n\t\t};\n\t}\n\tobserversFor(slug) {\n\t\tlet set = this.observers.get(slug);\n\t\tif (!set) {\n\t\t\tset = /* @__PURE__ */ new Set();\n\t\t\tthis.observers.set(slug, set);\n\t\t}\n\t\treturn set;\n\t}\n\t/** Cheap change detection: which rows, in what order, at which revision. */\n\tsignature(slug, rows, total) {\n\t\tconst state = this.collections.get(slug);\n\t\treturn `${total}|${rows.map((row) => {\n\t\t\tconst key = String(row.id);\n\t\t\treturn `${key}:${state?.rows.get(key)?.rev ?? 0}`;\n\t\t}).join(\",\")}`;\n\t}\n\tnotifyCollection(slug, broadcast = true) {\n\t\tconst set = this.observers.get(slug);\n\t\tif (set) for (const observer of [...set]) observer.emit();\n\t\tif (broadcast) this.broadcast({\n\t\t\ttype: \"rows\",\n\t\t\tslugs: [slug]\n\t\t});\n\t}\n\t/** Connectivity came back (or the user changed): re-read everything live. */\n\trevalidateAll() {\n\t\tfor (const slug of this.observers.keys()) {\n\t\t\tthis.notifyCollection(slug, false);\n\t\t\tthis.scheduleRefresh(slug);\n\t\t}\n\t}\n\tcollectionState(slug) {\n\t\tlet state = this.collections.get(slug);\n\t\tif (!state) {\n\t\t\tstate = {\n\t\t\t\trows: /* @__PURE__ */ new Map(),\n\t\t\t\tsnapshots: /* @__PURE__ */ new Map(),\n\t\t\t\tfresh: /* @__PURE__ */ new Set(),\n\t\t\t\tfreshRows: /* @__PURE__ */ new Set(),\n\t\t\t\tabsent: /* @__PURE__ */ new Set(),\n\t\t\t\tready: false\n\t\t\t};\n\t\t\tthis.collections.set(slug, state);\n\t\t}\n\t\treturn state;\n\t}\n\tensureCollection(slug) {\n\t\tconst state = this.collectionState(slug);\n\t\tif (!state.loaded) {\n\t\t\tconst scope = this.scope;\n\t\t\tstate.loaded = (async () => {\n\t\t\t\tawait this.ensureQueueLoaded();\n\t\t\t\tconst [rows, snapshots, absent] = await Promise.all([\n\t\t\t\t\tthis.store.listCacheEntries(`${scope}|row|${slug}|`).catch(() => []),\n\t\t\t\t\tthis.store.listCacheEntries(`${scope}|q|${slug}|`).catch(() => []),\n\t\t\t\t\tthis.store.listCache(`${scope}|abs|${slug}|`).catch(() => [])\n\t\t\t\t]);\n\t\t\t\tif (this.scope !== scope || this.collections.get(slug) !== state) return;\n\t\t\t\tfor (const entry of rows) {\n\t\t\t\t\tconst row = entry.value;\n\t\t\t\t\tif (!row || row.id === void 0 || row.id === null) continue;\n\t\t\t\t\tstate.rows.set(String(row.id), {\n\t\t\t\t\t\trow: hydrateRow(row),\n\t\t\t\t\t\tcachedAt: entry.cachedAt,\n\t\t\t\t\t\trev: ++this.revCounter\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tfor (const entry of snapshots) {\n\t\t\t\t\tconst key = entry.key.slice(`${scope}|q|${slug}|`.length);\n\t\t\t\t\tif (entry.value) state.snapshots.set(key, entry.value);\n\t\t\t\t}\n\t\t\t\tfor (const entry of absent) state.absent.add(entry.key.slice(`${scope}|abs|${slug}|`.length));\n\t\t\t})().catch(() => void 0).finally(() => {\n\t\t\t\tstate.ready = true;\n\t\t\t});\n\t\t}\n\t\treturn state.loaded.then(() => state);\n\t}\n\tsnapshotFor(slug, params) {\n\t\treturn this.collections.get(slug)?.snapshots.get(buildQueryString(params));\n\t}\n\thasLocalAnswer(state, slug, params) {\n\t\tif (!state) return false;\n\t\treturn state.snapshots.has(buildQueryString(params)) || state.rows.size > 0;\n\t}\n\t/**\n\t* Answer a query from the local database.\n\t*\n\t* With a snapshot, the server's own page — its ids, order and total — is\n\t* the skeleton, and the local rows fill it in: rows deleted locally drop\n\t* out, rows edited locally show the edit, and rows *created* locally join\n\t* the first page if they match. Without one, the query is evaluated\n\t* outright over every cached row, which is the best that can be done for a\n\t* query the server has never answered here.\n\t*/\n\tanswer(slug, params, snapshot) {\n\t\tconst state = this.collections.get(slug);\n\t\tconst exact = isExactlyEvaluable(params);\n\t\tconst fromCache = !state?.fresh.has(buildQueryString(params));\n\t\tif (!state) return {\n\t\t\tdata: [],\n\t\t\tmeta: {\n\t\t\t\ttotal: 0,\n\t\t\t\tlimit: params?.limit ?? 20,\n\t\t\t\toffset: params?.offset ?? 0,\n\t\t\t\thasMore: false\n\t\t\t},\n\t\t\tfromCache: true,\n\t\t\thasPendingWrites: false,\n\t\t\tpartial: true\n\t\t};\n\t\tif (!snapshot) {\n\t\t\tconst local = runLocalQuery([...state.rows.values()].map((e) => e.row), params);\n\t\t\treturn {\n\t\t\t\t...local,\n\t\t\t\tfromCache,\n\t\t\t\thasPendingWrites: local.data.some((row) => this.hasPending(slug, row.id)),\n\t\t\t\tpartial: true\n\t\t\t};\n\t\t}\n\t\tconst rows = [];\n\t\tconst seen = /* @__PURE__ */ new Set();\n\t\t/** Rows the server counted that we know are no longer in the result. */\n\t\tlet removed = 0;\n\t\tfor (const id of snapshot.ids) {\n\t\t\tconst key = String(id);\n\t\t\tconst entry = state.rows.get(key);\n\t\t\tif (!entry) {\n\t\t\t\tif (state.absent.has(key) || this.hasPending(slug, key)) removed++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (exact && this.hasPending(slug, key) && !matchesParams(entry.row, params)) {\n\t\t\t\tremoved++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\trows.push(entry.row);\n\t\t\tseen.add(key);\n\t\t}\n\t\tlet added = 0;\n\t\tconst offset = snapshot.offset ?? 0;\n\t\tif (exact && offset === 0) {\n\t\t\tfor (const [key, entry] of state.rows) {\n\t\t\t\tif (seen.has(key) || !this.hasPending(slug, key)) continue;\n\t\t\t\tif (!this.isLocallyCreated(slug, key)) continue;\n\t\t\t\tif (!matchesParams(entry.row, params)) continue;\n\t\t\t\trows.push(entry.row);\n\t\t\t\tadded++;\n\t\t\t}\n\t\t\tif (added > 0 && params?.orderBy) sortRows(rows, params.orderBy);\n\t\t}\n\t\treturn {\n\t\t\tdata: rows,\n\t\t\tmeta: {\n\t\t\t\ttotal: Math.max(rows.length, snapshot.total - removed + added),\n\t\t\t\tlimit: snapshot.limit,\n\t\t\t\toffset,\n\t\t\t\thasMore: snapshot.hasMore\n\t\t\t},\n\t\t\tfromCache,\n\t\t\thasPendingWrites: rows.some((row) => this.hasPending(slug, row.id)),\n\t\t\tpartial: !exact\n\t\t};\n\t}\n\tlocalFind(slug, params) {\n\t\tconst state = this.collections.get(slug);\n\t\tconst snapshot = this.snapshotFor(slug, params);\n\t\tstate?.fresh.delete(buildQueryString(params));\n\t\tif (!snapshot && (!state || state.rows.size === 0)) throw offlineError(`Offline: no cached data for \"${slug}\".`);\n\t\tconst answer = this.answer(slug, params, snapshot);\n\t\treturn snapshot ? answer : {\n\t\t\t...answer,\n\t\t\tpartial: true\n\t\t};\n\t}\n\trawLocalRow(slug, id) {\n\t\tconst entry = this.collections.get(slug)?.rows.get(String(id));\n\t\treturn entry ? { ...entry.row } : void 0;\n\t}\n\tlocalRow(slug, id) {\n\t\treturn this.collections.get(slug)?.rows.get(String(id))?.row;\n\t}\n\tsetLocalRow(slug, id, row) {\n\t\tconst state = this.collectionState(slug);\n\t\tconst key = String(id);\n\t\tconst cachedAt = Date.now();\n\t\tstate.rows.set(key, {\n\t\t\trow: { ...row },\n\t\t\tcachedAt,\n\t\t\trev: ++this.revCounter\n\t\t});\n\t\tstate.freshRows.delete(key);\n\t\tthis.forgetTombstone(slug, key);\n\t\tthis.writeCache(this.rowKey(slug, key), dehydrateRow(row), cachedAt);\n\t\tthis.evictRows(slug);\n\t}\n\t/**\n\t* Drop a row and, when the server is the one saying it is gone, remember\n\t* that. \"I looked it up and it does not exist\" is real knowledge: without\n\t* it, opening a deleted row while offline would report a missing local\n\t* database instead of a missing row.\n\t*/\n\tremoveLocalRow(slug, id, known = false) {\n\t\tconst state = this.collectionState(slug);\n\t\tconst key = String(id);\n\t\tconst existed = state.rows.delete(key);\n\t\tif (known) {\n\t\t\tstate.absent.add(key);\n\t\t\tstate.freshRows.add(key);\n\t\t\tthis.writeCache(this.absentKey(slug, key), true);\n\t\t} else state.freshRows.delete(key);\n\t\tif (existed) this.deleteCache([this.rowKey(slug, key)]);\n\t}\n\tforgetTombstone(slug, key) {\n\t\tif (!this.collectionState(slug).absent.delete(key)) return;\n\t\tthis.deleteCache([this.absentKey(slug, key)]);\n\t}\n\t/**\n\t* Merge server rows into the local database. A row with unsynced local\n\t* writes keeps them: the server's copy is the base the queued mutations\n\t* are re-applied to, not a replacement for what the user did.\n\t*\n\t* Rows that came back unchanged keep their identity and revision, so a\n\t* refetch that changed nothing does not re-render every live query that\n\t* touches them — or rewrite them all to disk.\n\t*/\n\tasync ingest(slug, rows) {\n\t\tif (rows.length === 0) return;\n\t\tconst state = await this.ensureCollection(slug);\n\t\tconst cachedAt = Date.now();\n\t\tconst writes = [];\n\t\tconst deletes = [];\n\t\tfor (const raw of rows) {\n\t\t\tif (!raw || raw.id === void 0 || raw.id === null) continue;\n\t\t\tconst key = String(raw.id);\n\t\t\tconst merged = this.hasPending(slug, key) ? this.applyPendingToRow(slug, key, { ...raw }) : { ...raw };\n\t\t\tif (merged === void 0) {\n\t\t\t\tstate.rows.delete(key);\n\t\t\t\tdeletes.push(this.rowKey(slug, key));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.forgetTombstone(slug, key);\n\t\t\tstate.freshRows.add(key);\n\t\t\tconst existing = state.rows.get(key);\n\t\t\tif (existing && JSON.stringify(existing.row) === JSON.stringify(merged)) {\n\t\t\t\texisting.cachedAt = cachedAt;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstate.rows.set(key, {\n\t\t\t\trow: merged,\n\t\t\t\tcachedAt,\n\t\t\t\trev: ++this.revCounter\n\t\t\t});\n\t\t\twrites.push({\n\t\t\t\tkey: this.rowKey(slug, key),\n\t\t\t\tentry: {\n\t\t\t\t\tvalue: dehydrateRow(merged),\n\t\t\t\t\tcachedAt\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif (writes.length > 0) this.store.setCacheMany(writes).catch(() => void 0);\n\t\tif (deletes.length > 0) this.deleteCache(deletes);\n\t\tthis.evictRows(slug);\n\t}\n\t/**\n\t* Fold the queued mutations for one row over a base, newest last.\n\t* `afterMutationId` skips everything up to and including that mutation,\n\t* which is how a just-replayed write avoids being applied on top of the\n\t* server's response to it.\n\t*/\n\tapplyPendingToRow(slug, idKey, base, afterMutationId) {\n\t\tlet row = base;\n\t\tlet skipping = afterMutationId !== void 0;\n\t\tfor (const op of this.queue) {\n\t\t\tif (skipping) {\n\t\t\t\tif (op.mutationId === afterMutationId) skipping = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (op.collection !== slug) continue;\n\t\t\tif (op.type === \"createMany\") {\n\t\t\t\tconst match = op.data?.find((r) => String(r.id) === idKey);\n\t\t\t\tif (match) row = { ...match };\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (op.id === void 0 || String(op.id) !== idKey) continue;\n\t\t\tif (op.type === \"create\") row = { ...op.data };\n\t\t\telse if (op.type === \"update\") row = {\n\t\t\t\t...row ?? {},\n\t\t\t\t...op.data,\n\t\t\t\tid: op.id\n\t\t\t};\n\t\t\telse if (op.type === \"delete\") row = void 0;\n\t\t}\n\t\treturn row;\n\t}\n\trecordSnapshot(slug, params, result) {\n\t\tconst meta = result.meta ?? {\n\t\t\ttotal: result.data?.length ?? 0,\n\t\t\tlimit: 20,\n\t\t\toffset: 0,\n\t\t\thasMore: false\n\t\t};\n\t\tconst snapshot = {\n\t\t\tids: (result.data ?? []).map((row) => row.id).filter((id) => id !== void 0),\n\t\t\ttotal: meta.total ?? result.data?.length ?? 0,\n\t\t\tlimit: meta.limit ?? params?.limit ?? 20,\n\t\t\toffset: meta.offset ?? params?.offset ?? 0,\n\t\t\thasMore: meta.hasMore ?? false\n\t\t};\n\t\tconst state = this.collectionState(slug);\n\t\tconst key = buildQueryString(params);\n\t\tstate.snapshots.set(key, snapshot);\n\t\tstate.fresh.add(key);\n\t\tthis.writeCache(`${this.scope}|q|${slug}|${key}`, snapshot);\n\t\tthis.evictSnapshots(slug);\n\t\treturn snapshot;\n\t}\n\t/**\n\t* A write changed which rows belong in a list, and only the server can say\n\t* how — a row it generated is in no cached page, and the totals moved.\n\t* Re-run every live query on the collection; queries nobody is watching\n\t* are corrected by their next `find`.\n\t*\n\t* Coalesced per microtask so a burst of writes costs one round trip, and\n\t* skipped entirely while offline, where the local database is already the\n\t* best answer available.\n\t*/\n\tscheduleRefresh(slug) {\n\t\tif (this.refreshPending.has(slug)) return;\n\t\tconst observers = this.observers.get(slug);\n\t\tif (!observers || observers.size === 0) return;\n\t\tthis.refreshPending.add(slug);\n\t\tPromise.resolve().then(() => {\n\t\t\tthis.refreshPending.delete(slug);\n\t\t\tif (this.disposed || !this.connectivity.shouldAttempt()) return;\n\t\t\tfor (const observer of [...this.observers.get(slug) ?? []]) observer.refresh();\n\t\t});\n\t}\n\tevictRows(slug) {\n\t\tconst state = this.collections.get(slug);\n\t\tif (!state || state.rows.size <= this.maxCachedRows) return;\n\t\tconst evictable = [...state.rows.entries()].filter(([key]) => !this.hasPending(slug, key)).sort((a, b) => a[1].cachedAt - b[1].cachedAt);\n\t\tconst excess = state.rows.size - this.maxCachedRows;\n\t\tconst doomed = evictable.slice(0, excess);\n\t\tfor (const [key] of doomed) state.rows.delete(key);\n\t\tif (doomed.length > 0) this.deleteCache(doomed.map(([key]) => this.rowKey(slug, key)));\n\t\tif (state.absent.size > this.maxCachedRows) {\n\t\t\tconst stale = [...state.absent].slice(0, state.absent.size - this.maxCachedRows);\n\t\t\tfor (const key of stale) state.absent.delete(key);\n\t\t\tthis.deleteCache(stale.map((key) => this.absentKey(slug, key)));\n\t\t}\n\t}\n\tevictSnapshots(slug) {\n\t\tconst state = this.collections.get(slug);\n\t\tif (!state || state.snapshots.size <= this.maxCachedQueries) return;\n\t\tconst excess = state.snapshots.size - this.maxCachedQueries;\n\t\tconst doomed = [...state.snapshots.keys()].slice(0, excess);\n\t\tfor (const key of doomed) state.snapshots.delete(key);\n\t\tthis.deleteCache(doomed.map((key) => `${this.scope}|q|${slug}|${key}`));\n\t}\n\tensureQueueLoaded() {\n\t\tif (!this.queueLoad) {\n\t\t\tconst scope = this.scope;\n\t\t\tthis.queueLoad = this.store.listQueue(`${scope}|`).then((queue) => {\n\t\t\t\tif (this.scope !== scope) return;\n\t\t\t\tthis.queue = queue;\n\t\t\t\tthis.patchStatus({ pending: queue.length });\n\t\t\t\tthis.notifyQueue();\n\t\t\t}).catch(() => void 0);\n\t\t}\n\t\treturn this.queueLoad;\n\t}\n\tenqueue(mutation) {\n\t\tconst result = this.enqueueChain.then(async () => {\n\t\t\tawait this.ensureQueueLoaded();\n\t\t\tif (mutation.type === \"update\") {\n\t\t\t\tconst tail = this.queue[this.queue.length - 1];\n\t\t\t\tif (tail && tail.mutationId !== this.inFlightId && tail.collection === mutation.collection && (tail.type === \"create\" || tail.type === \"update\") && tail.id === mutation.id) {\n\t\t\t\t\ttail.data = {\n\t\t\t\t\t\t...tail.data,\n\t\t\t\t\t\t...mutation.data,\n\t\t\t\t\t\tid: tail.id\n\t\t\t\t\t};\n\t\t\t\t\tawait this.store.enqueue(this.queueKey(tail), tail);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (mutation.type === \"delete\") {\n\t\t\t\tif (this.queue.some((m) => m.collection === mutation.collection && m.type === \"create\" && m.id === mutation.id && m.generatedId === true && m.mutationId !== this.inFlightId)) {\n\t\t\t\t\tconst doomed = this.queue.filter((m) => m.collection === mutation.collection && m.id === mutation.id && (m.type === \"create\" || m.type === \"update\") && m.mutationId !== this.inFlightId);\n\t\t\t\t\tfor (const op of doomed) await this.store.dequeue(this.queueKey(op));\n\t\t\t\t\tthis.queue = this.queue.filter((m) => !doomed.includes(m));\n\t\t\t\t\tthis.afterQueueChange();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst full = {\n\t\t\t\t...mutation,\n\t\t\t\tmutationId: createMutationId(),\n\t\t\t\tqueuedAt: Date.now()\n\t\t\t};\n\t\t\tawait this.store.enqueue(this.queueKey(full), full);\n\t\t\tthis.queue.push(full);\n\t\t\tthis.afterQueueChange();\n\t\t});\n\t\tthis.enqueueChain = result.catch(() => void 0);\n\t\treturn result;\n\t}\n\thasPending(slug, id) {\n\t\tconst key = String(id);\n\t\treturn this.queue.some((op) => {\n\t\t\tif (op.collection !== slug) return false;\n\t\t\tif (op.type === \"createMany\") return op.data?.some((r) => String(r.id) === key) ?? false;\n\t\t\treturn op.id !== void 0 && String(op.id) === key;\n\t\t});\n\t}\n\t/** Is this row one the server has never been told about? */\n\tisLocallyCreated(slug, idKey) {\n\t\treturn this.queue.some((op) => {\n\t\t\tif (op.collection !== slug) return false;\n\t\t\tif (op.type === \"create\") return op.id !== void 0 && String(op.id) === idKey;\n\t\t\tif (op.type === \"createMany\") return op.data?.some((r) => String(r.id) === idKey) ?? false;\n\t\t\treturn false;\n\t\t});\n\t}\n\t/** How many rows the queue adds to (or removes from) a server-side count. */\n\tpendingDelta(slug, params) {\n\t\tif (!isExactlyEvaluable(params)) return 0;\n\t\tlet delta = 0;\n\t\tfor (const op of this.queue) {\n\t\t\tif (op.collection !== slug) continue;\n\t\t\tif (op.type === \"create\") {\n\t\t\t\tif (matchesParams(op.data, params)) delta++;\n\t\t\t} else if (op.type === \"createMany\") {\n\t\t\t\tfor (const row of op.data ?? []) if (matchesParams(row, params)) delta++;\n\t\t\t} else if (op.type === \"delete\") {\n\t\t\t\tconst before = op.rollback?.rows?.[String(op.id)];\n\t\t\t\tif (before && matchesParams(before, params)) delta--;\n\t\t\t}\n\t\t}\n\t\treturn delta;\n\t}\n\tsync() {\n\t\tif (this.flushPromise) return this.flushPromise;\n\t\tthis.flushPromise = this.withLock(() => this.flush()).finally(() => {\n\t\t\tthis.flushPromise = void 0;\n\t\t});\n\t\treturn this.flushPromise;\n\t}\n\tasync flush() {\n\t\tawait this.ensureQueueLoaded();\n\t\tawait this.reloadQueue();\n\t\tif (this.queue.length === 0) return {\n\t\t\tflushed: 0,\n\t\t\tremaining: 0\n\t\t};\n\t\tthis.patchStatus({ syncing: true });\n\t\tconst touched = /* @__PURE__ */ new Set();\n\t\tconst queuedAtStart = this.queue.length;\n\t\tlet flushed = 0;\n\t\ttry {\n\t\t\twhile (this.queue.length > 0 && !this.disposed) {\n\t\t\t\tconst op = this.queue[0];\n\t\t\t\ttouched.add(op.collection);\n\t\t\t\tthis.inFlightId = op.mutationId;\n\t\t\t\ttry {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.replay(op);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (isNetworkError(error)) {\n\t\t\t\t\t\t\tthis.connectivity.markFailure();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\top.attempts = (op.attempts ?? 0) + 1;\n\t\t\t\t\t\top.lastError = error?.message ?? String(error);\n\t\t\t\t\t\tif (isRetryableError(error) && op.attempts < this.maxRetries) {\n\t\t\t\t\t\t\tawait this.store.enqueue(this.queueKey(op), op).catch(() => void 0);\n\t\t\t\t\t\t\tthis.connectivity.deferRetry();\n\t\t\t\t\t\t\tthis.patchStatus({ lastError: op.lastError });\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait this.rejectMutation(op, error);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tthis.connectivity.markSuccess();\n\t\t\t\t\tawait this.drop(op);\n\t\t\t\t\tflushed++;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.inFlightId = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.patchStatus({ syncing: false });\n\t\t}\n\t\tif (this.queue.length !== queuedAtStart) {\n\t\t\tfor (const slug of touched) {\n\t\t\t\tthis.notifyCollection(slug);\n\t\t\t\tthis.scheduleRefresh(slug);\n\t\t\t}\n\t\t\tthis.broadcast({ type: \"queue\" });\n\t\t}\n\t\tif (this.queue.length === 0) this.patchStatus({ lastSyncedAt: Date.now() });\n\t\treturn {\n\t\t\tflushed,\n\t\t\tremaining: this.queue.length\n\t\t};\n\t}\n\tasync replay(op) {\n\t\tconst inner = this.innerFor(op.collection);\n\t\tif (op.type === \"create\") {\n\t\t\tlet row;\n\t\t\ttry {\n\t\t\t\trow = await inner.create(op.data, void 0, { idempotencyKey: op.mutationId });\n\t\t\t} catch (error) {\n\t\t\t\tif (!(op.generatedId === true && isDuplicateKeyError(error))) throw error;\n\t\t\t\trow = await inner.findById(op.id).catch(() => void 0);\n\t\t\t\tif (!row) return;\n\t\t\t}\n\t\t\tawait this.adoptServerRow(op, op.id, row);\n\t\t} else if (op.type === \"createMany\") {\n\t\t\tconst queued = op.data ?? [];\n\t\t\tconst rows = await inner.createMany(queued, op.upsert ? { upsert: true } : void 0);\n\t\t\tfor (let i = 0; i < rows.length; i++) await this.adoptServerRow(op, queued[i]?.id, rows[i]);\n\t\t} else if (op.type === \"update\") {\n\t\t\tconst row = await inner.update(op.id, op.data);\n\t\t\tawait this.ingestReplaced(op, op.id, row);\n\t\t} else if (op.type === \"delete\") {\n\t\t\tawait inner.delete(op.id);\n\t\t\tthis.removeLocalRow(op.collection, op.id, true);\n\t\t}\n\t}\n\t/**\n\t* Take the server's version of a row the client created offline.\n\t*\n\t* The server may have assigned a different id — a serial column ignores\n\t* the id we invented — in which case every local trace of the temporary id\n\t* has to move with it, including queued writes that were made against it\n\t* before it was ever sent.\n\t*/\n\tasync adoptServerRow(op, localId, row) {\n\t\tif (!row) return;\n\t\tconst slug = op.collection;\n\t\tconst serverId = row.id;\n\t\tif (localId !== void 0 && serverId !== void 0 && String(serverId) !== String(localId)) {\n\t\t\tconst oldKey = String(localId);\n\t\t\tthis.removeLocalRow(slug, localId);\n\t\t\tfor (const queued of this.queue) {\n\t\t\t\tif (queued.collection !== slug) continue;\n\t\t\t\tlet dirty = false;\n\t\t\t\tif (queued.id !== void 0 && String(queued.id) === oldKey) {\n\t\t\t\t\tqueued.id = serverId;\n\t\t\t\t\tif (queued.data && !Array.isArray(queued.data)) queued.data.id = serverId;\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t\tconst rollbackRows = queued.rollback?.rows;\n\t\t\t\tif (rollbackRows && oldKey in rollbackRows) {\n\t\t\t\t\trollbackRows[String(serverId)] = rollbackRows[oldKey];\n\t\t\t\t\tdelete rollbackRows[oldKey];\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t\tif (dirty) await this.store.enqueue(this.queueKey(queued), queued).catch(() => void 0);\n\t\t\t}\n\t\t}\n\t\tawait this.ingestReplaced(op, serverId ?? localId, row);\n\t}\n\t/**\n\t* Write a server row over the local one, ignoring the mutation that just\n\t* produced it — re-applying that would put the pre-server values back on\n\t* top of the server's answer — but keeping every write queued *after* it.\n\t* Those are still unsent, and dropping them here would make the row snap\n\t* back to the server's version in front of the user, only to change again\n\t* when they replay a moment later.\n\t*/\n\tasync ingestReplaced(op, id, row) {\n\t\tconst slug = op.collection;\n\t\tconst state = await this.ensureCollection(slug);\n\t\tconst key = String(id);\n\t\tconst merged = this.applyPendingToRow(slug, key, { ...row }, op.mutationId);\n\t\tif (merged === void 0) {\n\t\t\tthis.removeLocalRow(slug, key);\n\t\t\treturn;\n\t\t}\n\t\tconst cachedAt = Date.now();\n\t\tstate.rows.set(key, {\n\t\t\trow: merged,\n\t\t\tcachedAt,\n\t\t\trev: ++this.revCounter\n\t\t});\n\t\tif (this.applyPendingToRow(slug, key, void 0, op.mutationId) === void 0) state.freshRows.add(key);\n\t\tthis.writeCache(this.rowKey(slug, key), dehydrateRow(merged), cachedAt);\n\t}\n\t/**\n\t* The server refused a mutation. Put back what it changed, and discard the\n\t* queued writes that were built on top of it: an edit to a row whose\n\t* creation was rejected can only fail the same way, and applying it would\n\t* leave the local database claiming a row the server does not have.\n\t*\n\t* The cascade stops the moment a later write stops *depending* on the\n\t* rejected one. An `update` reads the row it edits, so it is doomed with\n\t* it; a `create` overwrites the row outright and a `delete` needs nothing\n\t* of it, so both stand on their own and are kept — dropping them would\n\t* silently lose writes the server would have accepted.\n\t*/\n\tasync rejectMutation(op, error) {\n\t\tconst ids = new Set(Object.keys(op.rollback?.rows ?? {}));\n\t\tif (op.id !== void 0) ids.add(String(op.id));\n\t\tconst doomed = [op];\n\t\tconst orphaned = new Set(ids);\n\t\tconst position = this.queue.indexOf(op);\n\t\tfor (const later of this.queue.slice(position + 1)) {\n\t\t\tif (later.collection !== op.collection) continue;\n\t\t\tconst hit = this.idsOf(later).filter((id) => orphaned.has(id));\n\t\t\tif (hit.length === 0) continue;\n\t\t\tif (later.type === \"update\") doomed.push(later);\n\t\t\telse for (const id of hit) orphaned.delete(id);\n\t\t}\n\t\tfor (const dropped of doomed) await this.drop(dropped);\n\t\tfor (const [idKey, previous] of Object.entries(op.rollback?.rows ?? {})) {\n\t\t\tconst restored = this.applyPendingToRow(op.collection, idKey, previous ?? void 0);\n\t\t\tif (restored === void 0) this.removeLocalRow(op.collection, idKey);\n\t\t\telse this.setLocalRow(op.collection, idKey, restored);\n\t\t}\n\t\tthis.patchStatus({ lastError: error.message });\n\t\tthis.notifyCollection(op.collection);\n\t\tthis.scheduleRefresh(op.collection);\n\t\tfor (const dropped of doomed) this.onSyncError?.(error, dropped);\n\t}\n\t/** Every row id a mutation writes to. */\n\tidsOf(op) {\n\t\tif (op.type === \"createMany\") return (op.data ?? []).map((r) => String(r.id));\n\t\treturn op.id === void 0 ? [] : [String(op.id)];\n\t}\n\tasync drop(op) {\n\t\tawait this.store.dequeue(this.queueKey(op)).catch(() => void 0);\n\t\tthis.queue = this.queue.filter((m) => m.mutationId !== op.mutationId);\n\t\tthis.afterQueueChange(false);\n\t}\n\t/** Replay uses unwrapped clients: a failure must never re-enqueue itself. */\n\tinnerFor(slug) {\n\t\tlet inner = this.inners.get(slug);\n\t\tif (!inner) {\n\t\t\tinner = this.createInner(slug);\n\t\t\tthis.inners.set(slug, inner);\n\t\t}\n\t\treturn inner;\n\t}\n\tasync withLock(fn) {\n\t\tconst locks = globalThis.navigator?.locks;\n\t\tif (!locks?.request) return fn();\n\t\ttry {\n\t\t\treturn await locks.request(`rebase-offline-sync:${this.scope}`, fn);\n\t\t} catch {\n\t\t\treturn fn();\n\t\t}\n\t}\n\tbroadcast(message) {\n\t\tif (!this.channel) return;\n\t\ttry {\n\t\t\tthis.channel.postMessage({\n\t\t\t\t...message,\n\t\t\t\tscope: this.scope,\n\t\t\t\tsender: this.tabId\n\t\t\t});\n\t\t} catch {}\n\t}\n\tonBroadcast(message) {\n\t\tif (this.disposed || !message || typeof message !== \"object\") return;\n\t\tconst msg = message;\n\t\tif (msg.sender === this.tabId || msg.scope !== this.scope) return;\n\t\tif (msg.type === \"rows\") for (const slug of msg.slugs ?? []) this.reloadCollection(slug);\n\t\telse if (msg.type === \"queue\") this.reloadQueue();\n\t}\n\t/** Re-read one collection from the store, replacing what is in memory. */\n\tasync reloadCollection(slug) {\n\t\tconst state = this.collections.get(slug);\n\t\tif (!state?.loaded) return;\n\t\tawait this.reloadQueue();\n\t\tconst scope = this.scope;\n\t\tconst [rows, snapshots, absent] = await Promise.all([\n\t\t\tthis.store.listCacheEntries(`${scope}|row|${slug}|`).catch(() => []),\n\t\t\tthis.store.listCacheEntries(`${scope}|q|${slug}|`).catch(() => []),\n\t\t\tthis.store.listCache(`${scope}|abs|${slug}|`).catch(() => [])\n\t\t]);\n\t\tif (this.scope !== scope || this.collections.get(slug) !== state) return;\n\t\tconst next = /* @__PURE__ */ new Map();\n\t\tfor (const entry of rows) {\n\t\t\tconst row = entry.value;\n\t\t\tif (!row || row.id === void 0 || row.id === null) continue;\n\t\t\tconst key = String(row.id);\n\t\t\tconst existing = state.rows.get(key);\n\t\t\tconst hydrated = hydrateRow(row);\n\t\t\tconst unchanged = existing && JSON.stringify(existing.row) === JSON.stringify(hydrated);\n\t\t\tnext.set(key, {\n\t\t\t\trow: hydrated,\n\t\t\t\tcachedAt: entry.cachedAt,\n\t\t\t\trev: unchanged ? existing.rev : ++this.revCounter\n\t\t\t});\n\t\t}\n\t\tstate.rows = next;\n\t\tstate.snapshots = /* @__PURE__ */ new Map();\n\t\tfor (const entry of snapshots) {\n\t\t\tconst key = entry.key.slice(`${scope}|q|${slug}|`.length);\n\t\t\tif (entry.value) state.snapshots.set(key, entry.value);\n\t\t}\n\t\tstate.absent = new Set(absent.map((entry) => entry.key.slice(`${scope}|abs|${slug}|`.length)));\n\t\tthis.notifyCollection(slug, false);\n\t}\n\tasync reloadQueue() {\n\t\tconst scope = this.scope;\n\t\tconst queue = await this.store.listQueue(`${scope}|`).catch(() => void 0);\n\t\tif (!queue || this.scope !== scope) return;\n\t\tthis.queue = queue;\n\t\tthis.afterQueueChange(false);\n\t}\n\tafterQueueChange(broadcast = true) {\n\t\tthis.patchStatus({ pending: this.queue.length });\n\t\tthis.notifyQueue();\n\t\tif (broadcast) this.broadcast({ type: \"queue\" });\n\t}\n\tnotifyQueue() {\n\t\tfor (const listener of this.queueListeners) listener(this.queue.length);\n\t}\n\tpatchStatus(patch) {\n\t\tlet changed = false;\n\t\tfor (const [key, value] of Object.entries(patch)) if (this.currentStatus[key] !== value) {\n\t\t\tthis.currentStatus[key] = value;\n\t\t\tchanged = true;\n\t\t}\n\t\tif (!changed) return;\n\t\tconst snapshot = { ...this.currentStatus };\n\t\tfor (const listener of this.statusListeners) listener(snapshot);\n\t}\n\tcountKey(slug, params) {\n\t\treturn `${this.scope}|count|${slug}|${buildQueryString(params)}`;\n\t}\n\trowKey(slug, id) {\n\t\treturn `${this.scope}|row|${slug}|${String(id)}`;\n\t}\n\tabsentKey(slug, id) {\n\t\treturn `${this.scope}|abs|${slug}|${String(id)}`;\n\t}\n\tqueueKey(mutation) {\n\t\treturn `${this.scope}|${mutation.mutationId}`;\n\t}\n\tasync readCache(key) {\n\t\ttry {\n\t\t\treturn (await this.store.getCache(key))?.value;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n\tasync writeCache(key, value, cachedAt = Date.now()) {\n\t\ttry {\n\t\t\tawait this.store.setCache(key, {\n\t\t\t\tvalue,\n\t\t\t\tcachedAt\n\t\t\t});\n\t\t} catch {}\n\t}\n\tasync deleteCache(keys) {\n\t\ttry {\n\t\t\tawait this.store.deleteCache(keys);\n\t\t} catch {}\n\t}\n};\n//#endregion\n//#region src/index.ts\n/**\n* Derive a WebSocket URL from an HTTP base URL.\n* `http://` → `ws://`, `https://` → `wss://`.\n*/\nfunction deriveWebSocketUrl(baseUrl) {\n\tif (typeof window !== \"undefined\") {\n\t\tlet absoluteUrl = \"\";\n\t\tif (!baseUrl) absoluteUrl = window.location.origin;\n\t\telse if (/^https?:\\/\\//i.test(baseUrl) || /^wss?:\\/\\//i.test(baseUrl)) absoluteUrl = baseUrl;\n\t\telse try {\n\t\t\tabsoluteUrl = new URL(baseUrl, window.location.href).origin;\n\t\t} catch {\n\t\t\tabsoluteUrl = window.location.origin;\n\t\t}\n\t\tconst protocol = absoluteUrl.startsWith(\"https:\") || absoluteUrl.startsWith(\"wss:\") ? \"wss:\" : \"ws:\";\n\t\treturn absoluteUrl.replace(/^https?:\\/\\//i, `${protocol}//`).replace(/^wss?:\\/\\//i, `${protocol}//`).replace(/\\/$/, \"\");\n\t}\n\tif (!baseUrl) return \"\";\n\tif (!/^https?:\\/\\//i.test(baseUrl) && !/^wss?:\\/\\//i.test(baseUrl)) return \"\";\n\treturn baseUrl.replace(/^https?:\\/\\//i, (match) => match.toLowerCase() === \"https://\" ? \"wss://\" : \"ws://\").replace(/\\/$/, \"\");\n}\nfunction createRebaseClient(options) {\n\tconst transport = createTransport(options, { credentialOutOfBand: options.auth?.authFlowMode === \"cookie\" });\n\tconst auth = createAuth(transport, options.auth);\n\tconst admin = createAdmin(transport, options.admin);\n\tconst cron = createCron(transport, options.cron);\n\tconst backups = createBackups(transport);\n\tconst apiKeys = createApiKeys(transport, options.apiKeys);\n\tconst storage = createStorage(transport);\n\tconst functions = createFunctionsClient(transport);\n\tconst createStorageSource = (storageId) => storageId === DEFAULT_STORAGE_SOURCE_KEY ? storage : createStorage(transport, storageId);\n\tconst storageRegistry = new ClientStorageSourceRegistry();\n\tstorageRegistry.register(DEFAULT_STORAGE_SOURCE_KEY, storage);\n\tfor (const def of options.storageSources ?? []) if (def.transport === \"server\" && def.key !== DEFAULT_STORAGE_SOURCE_KEY) storageRegistry.register(def.key, createStorageSource(def.key));\n\tlet storageSourcesPromise;\n\tconst fetchStorageSources = () => {\n\t\tif (storageSourcesPromise) return storageSourcesPromise;\n\t\tstorageSourcesPromise = transport.request(\"/storage/sources\").then((res) => {\n\t\t\tconst defs = res.data ?? [];\n\t\t\tfor (const def of defs) if (def.transport === \"server\" && def.key !== DEFAULT_STORAGE_SOURCE_KEY && !storageRegistry.has(def.key)) storageRegistry.register(def.key, createStorageSource(def.key));\n\t\t\treturn defs;\n\t\t}).catch((e) => {\n\t\t\tstorageSourcesPromise = void 0;\n\t\t\tthrow e;\n\t\t});\n\t\treturn storageSourcesPromise;\n\t};\n\tconst resolvedWsUrl = options.realtime !== false ? options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl) : void 0;\n\tlet ws;\n\t/** One channel object per name — see `realtime.channel`. */\n\tconst realtimeChannels = /* @__PURE__ */ new Map();\n\tif (resolvedWsUrl) {\n\t\tws = new RebaseWebSocketClient({\n\t\t\twebsocketUrl: resolvedWsUrl,\n\t\t\tgetAuthToken: async () => {\n\t\t\t\tlet session = auth.getSession();\n\t\t\t\tif (session && session.expiresAt <= Date.now() + 1e4) try {\n\t\t\t\t\tsession = await auth.refreshSession();\n\t\t\t\t} catch (e) {}\n\t\t\t\treturn session?.accessToken || options.token || \"\";\n\t\t\t},\n\t\t\tonUnauthorized: options.onUnauthorized || (() => auth.handleUnauthorized())\n\t\t});\n\t\tauth.onAuthStateChange((event, session) => {\n\t\t\tif (!ws) return;\n\t\t\tif (event === \"SIGNED_OUT\") ws.disconnect();\n\t\t\telse if (event === \"SIGNED_IN\" || event === \"TOKEN_REFRESHED\") {\n\t\t\t\tif (session?.accessToken && ws.hasSocket) ws.authenticate(session.accessToken).catch(console.warn);\n\t\t\t}\n\t\t});\n\t}\n\tif (!options.onUnauthorized) transport.setOnUnauthorized(() => auth.handleUnauthorized());\n\t/**\n\t* Suggest the closest known collection key for a mistyped accessor.\n\t* Uses edit-distance-1 and prefix matching — no external dependency.\n\t*/\n\tfunction suggestCollection(prop, knownKeys) {\n\t\tconst prefixMatch = knownKeys.find((k) => k.startsWith(prop) || prop.startsWith(k));\n\t\tif (prefixMatch) return prefixMatch;\n\t\tfor (const key of knownKeys) {\n\t\t\tif (Math.abs(key.length - prop.length) > 1) continue;\n\t\t\tlet diffs = 0;\n\t\t\tconst longer = key.length >= prop.length ? key : prop;\n\t\t\tconst shorter = key.length >= prop.length ? prop : key;\n\t\t\tif (longer.length === shorter.length) for (let i = 0; i < longer.length; i++) {\n\t\t\t\tif (longer[i] !== shorter[i]) {\n\t\t\t\t\tif (i + 1 < longer.length && longer[i] === shorter[i + 1] && longer[i + 1] === shorter[i]) {\n\t\t\t\t\t\tdiffs++;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\tif (diffs > 1) break;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tdiffs++;\n\t\t\t\t}\n\t\t\t\tif (diffs > 1) break;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlet li = 0;\n\t\t\t\tlet si = 0;\n\t\t\t\twhile (li < longer.length) {\n\t\t\t\t\tif (si < shorter.length && longer[li] === shorter[si]) si++;\n\t\t\t\t\telse diffs++;\n\t\t\t\t\tli++;\n\t\t\t\t\tif (diffs > 1) break;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (diffs <= 1) return key;\n\t\t}\n\t}\n\tconst offlineManager = options.offline ? new OfflineManager(typeof options.offline === \"object\" ? options.offline : {}, (slug) => createCollectionClient(transport, slug)) : void 0;\n\tif (offlineManager) {\n\t\tofflineManager.setScope(auth.getSession()?.user?.uid);\n\t\tauth.onAuthStateChange((event, session) => {\n\t\t\tofflineManager.setScope(event === \"SIGNED_OUT\" ? void 0 : session?.user?.uid);\n\t\t});\n\t}\n\tconst collectionClients = /* @__PURE__ */ new Map();\n\tlet untypedWarned = false;\n\tfunction collection(slug) {\n\t\tif (!collectionClients.has(slug)) {\n\t\t\tconst inner = createCollectionClient(transport, slug, ws);\n\t\t\tcollectionClients.set(slug, offlineManager ? offlineManager.wrap(slug, inner) : inner);\n\t\t}\n\t\treturn collectionClients.get(slug);\n\t}\n\tconst dataProxy = new Proxy({ collection }, { get(_target, prop) {\n\t\tif (prop === \"collection\") return collection;\n\t\tif (typeof prop === \"symbol\") return void 0;\n\t\tif (typeof prop === \"string\" && prop !== \"then\" && prop !== \"toJSON\" && prop !== \"$$typeof\") {\n\t\t\tif (options.collections) {\n\t\t\t\tif (prop in options.collections) return collection(options.collections[prop]);\n\t\t\t\tconst knownKeys = Object.keys(options.collections);\n\t\t\t\tconst suggestion = suggestCollection(prop, knownKeys);\n\t\t\t\tlet msg = `Unknown collection accessor \"${prop}\". Known collections: ${knownKeys.join(\", \")}.`;\n\t\t\t\tif (suggestion) msg += ` Did you mean \"${suggestion}\"?`;\n\t\t\t\tmsg += ` Use data.collection(\"<slug>\") for dynamic slugs.`;\n\t\t\t\tthrow new RebaseClientError(msg);\n\t\t\t}\n\t\t\tif (!untypedWarned) {\n\t\t\t\tuntypedWarned = true;\n\t\t\t\tconsole.warn(`[Rebase] Untyped data access detected (client.data.${prop}). Collection names are resolved via snake_case conversion, which may cause silent 404s at request time. Pass a \\`collections\\` dictionary to createRebaseClient() or use the generated SDK for type-safe access.`);\n\t\t\t}\n\t\t\treturn collection(toSnakeCase(prop));\n\t\t}\n\t} });\n\treturn {\n\t\tauth,\n\t\tadmin,\n\t\tcron,\n\t\tbackups,\n\t\tapiKeys,\n\t\tfunctions,\n\t\tstorage,\n\t\tstorageRegistry,\n\t\tcreateStorageSource,\n\t\tfetchStorageSources,\n\t\tws,\n\t\trealtime: { \n\t\t/**\n\t\t* Join a broadcast/presence channel.\n\t\t*\n\t\t* Repeated calls with the same name return the same channel, so\n\t\t* separate components can attach handlers without each opening its\n\t\t* own membership — and `leave()` from one would otherwise silently\n\t\t* cut off the others.\n\t\t*/\nchannel: (name, options) => {\n\t\t\tif (!ws) throw new RebaseClientError(\"Realtime is disabled on this client (realtime: false), so channels are unavailable.\");\n\t\t\tlet existing = realtimeChannels.get(name);\n\t\t\tif (!existing) {\n\t\t\t\texisting = new RebaseRealtimeChannel(name, ws, options);\n\t\t\t\trealtimeChannels.set(name, existing);\n\t\t\t} else if (options?.history) existing.enableHistory();\n\t\t\treturn existing;\n\t\t} },\n\t\t/**\n\t\t* Release every handle that can keep a process alive — see the\n\t\t* `close` docblock on the client interface.\n\t\t*\n\t\t* Safe to call when realtime was never started, safe when signed out,\n\t\t* and safe to call twice.\n\t\t*/\n\t\tclose: () => {\n\t\t\tfor (const channel of realtimeChannels.values()) channel.leave();\n\t\t\trealtimeChannels.clear();\n\t\t\tws?.disconnect(true);\n\t\t\tofflineManager?.dispose();\n\t\t\tauth.stopAutoRefresh();\n\t\t},\n\t\tsetToken: transport.setToken,\n\t\tsetAuthTokenGetter: transport.setAuthTokenGetter,\n\t\tsetOnUnauthorized: transport.setOnUnauthorized,\n\t\tresolveToken: transport.resolveToken,\n\t\tbaseUrl: transport.baseUrl,\n\t\tapiPath: transport.apiPath,\n\t\tcollection,\n\t\tcall: async (endpoint, payload) => {\n\t\t\tconst prefix = endpoint.startsWith(\"/\") ? \"\" : \"/\";\n\t\t\tconst res = await transport.request(`${prefix}${endpoint}`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: payload ? JSON.stringify(payload) : void 0\n\t\t\t});\n\t\t\treturn res.data ?? res;\n\t\t},\n\t\tdata: dataProxy,\n\t\t...offlineManager ? { offline: offlineManager.api } : {}\n\t};\n}\n//#endregion\nexport { MemoryOfflineStore, QueryBuilder, RebaseApiError, RebaseClientError, RebasePaginationError, RebaseRealtimeChannel, RebaseWebSocketClient, and, cond, createBackups, createCookieStorage, createMemoryStorage, createRebaseClient, isOfflineError, or };\n\n//# sourceMappingURL=index.es.js.map","import { Hono } from \"hono\";\nimport { HonoEnv } from \"../api/types\";\nimport { BackendCollectionRegistry } from \"../collections/BackendCollectionRegistry\";\nimport { ApiError, errorHandler } from \"../api/errors\";\nimport { DataDriver } from \"@rebasepro/types\";\n/**\n * Create Hono routes for entity history.\n * Mounted at `{basePath}/data/:slug/:id/history`.\n */\nexport interface HistoryService {\n fetchHistory(tableName: string, id: string, options: { limit: number, offset: number }): Promise<{ data: Record<string, unknown>[], total: number }>;\n fetchHistoryEntry(historyId: string): Promise<Record<string, unknown> | null>;\n}\n\nexport function createHistoryRoutes(params: {\n historyService: HistoryService;\n registry: BackendCollectionRegistry;\n driver: DataDriver;\n}): Hono<HonoEnv> {\n const { historyService, registry, driver } = params;\n const router = new Hono<HonoEnv>();\n router.onError(errorHandler);\n\n /**\n * GET /:slug/:id/history - List history entries for a entity\n *\n * Query params:\n * limit (default 20)\n * offset (default 0)\n */\n router.get(\"/:slug/:id/history\", async (c) => {\n const slug = c.req.param(\"slug\");\n const id = c.req.param(\"id\");\n const parsedLimit = parseInt(c.req.query(\"limit\") ?? \"20\", 10);\n const parsedOffset = parseInt(c.req.query(\"offset\") ?? \"0\", 10);\n const limit = Number.isNaN(parsedLimit) ? 20 : parsedLimit;\n const offset = Number.isNaN(parsedOffset) ? 0 : parsedOffset;\n\n // Resolve the collection to get the actual table name\n const collection = registry.getCollections().find(\n col => col.slug === slug || false\n );\n\n if (!collection) {\n throw ApiError.notFound(`Collection '${slug}' not found`);\n }\n\n if (!collection.history) {\n throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);\n }\n\n const tableName = collection.slug;\n\n const result = await historyService.fetchHistory(tableName, id, {\n limit: Math.min(limit, 100),\n offset: Math.max(offset, 0)\n });\n\n return c.json({\n data: result.data,\n meta: {\n total: result.total,\n limit,\n offset,\n hasMore: offset + result.data.length < result.total\n }\n });\n });\n\n /**\n * POST /:slug/:id/history/:historyId/revert - Revert entity to a historical version\n *\n * This goes through the normal save path, so it creates its own history entry.\n */\n router.post(\"/:slug/:id/history/:historyId/revert\", async (c) => {\n const slug = c.req.param(\"slug\");\n const id = c.req.param(\"id\");\n const historyId = c.req.param(\"historyId\");\n\n const collection = registry.getCollections().find(\n col => col.slug === slug || false\n );\n\n if (!collection) {\n throw ApiError.notFound(`Collection '${slug}' not found`);\n }\n\n if (!collection.history) {\n throw ApiError.badRequest(`History is not enabled for collection '${slug}'`);\n }\n\n // Fetch the history entry\n const historyEntry = await historyService.fetchHistoryEntry(historyId);\n\n if (!historyEntry) {\n throw ApiError.notFound(`History entry '${historyId}' not found`);\n }\n\n // Verify the history entry belongs to this entity (prevent cross-entity revert)\n const tableName = collection.slug;\n if (historyEntry.entity_id !== String(id) || historyEntry.table_name !== tableName) {\n throw ApiError.badRequest(\"History entry does not belong to this entity\");\n }\n\n if (!historyEntry.values) {\n throw ApiError.badRequest(\"Cannot revert: history entry has no stored values\");\n }\n\n // Revert by saving through the normal driver path — this will\n // itself create another history entry, giving a full audit trail.\n const authDriver = c.get(\"driver\") || driver;\n const path = collection.slug;\n\n const savedEntity = await authDriver.save({\n path,\n id: String(id),\n values: historyEntry.values,\n collection,\n status: \"existing\"\n });\n\n return c.json({\n data: savedEntity,\n meta: { reverted_from: historyId }\n });\n });\n\n return router;\n}\n","import type { Transporter } from \"nodemailer\";\nimport { EmailConfig, EmailSendOptions, EmailService } from \"./types\";\nimport { logger } from \"../utils/logger\";\n\nlet _nodemailer: typeof import(\"nodemailer\") | undefined;\n\nasync function loadNodemailer() {\n if (!_nodemailer) {\n try {\n _nodemailer = await import(\"nodemailer\");\n } catch {\n throw new Error(\n \"nodemailer is required for SMTP email. \" +\n \"Install it: pnpm add nodemailer\"\n );\n }\n }\n return _nodemailer;\n}\n\n/**\n * Safely parse a hostname from a URL string\n */\nfunction getHostname(urlStr: string): string | undefined {\n try {\n const url = new URL(urlStr.includes(\"://\") ? urlStr : `https://${urlStr}`);\n return url.hostname;\n } catch {\n return undefined;\n }\n}\n\n/**\n * SMTP Email Service implementation using Nodemailer\n */\nexport class SMTPEmailService implements EmailService {\n private transporter: Transporter | null = null;\n private config: EmailConfig;\n private _initialized = false;\n\n constructor(config: EmailConfig) {\n this.config = config;\n }\n\n /**\n * Lazily initialize the SMTP transporter on first use\n */\n private async ensureTransporter(): Promise<void> {\n if (this._initialized) return;\n this._initialized = true;\n\n if (this.config.smtp) {\n const nodemailer = await loadNodemailer();\n\n let smtpName = this.config.smtp.name;\n if (!smtpName) {\n const urlsToTry = [\n process.env.FRONTEND_URL,\n this.config.resetPasswordUrl,\n this.config.verifyEmailUrl\n ];\n for (const urlStr of urlsToTry) {\n if (urlStr) {\n const hostname = getHostname(urlStr);\n if (hostname) {\n smtpName = hostname;\n break;\n }\n }\n }\n }\n\n this.transporter = nodemailer.createTransport({\n name: smtpName,\n host: this.config.smtp.host,\n port: this.config.smtp.port,\n secure: this.config.smtp.secure ?? (this.config.smtp.port === 465),\n auth: this.config.smtp.auth ? {\n user: this.config.smtp.auth.user,\n pass: this.config.smtp.auth.pass\n } : undefined\n });\n }\n }\n\n /**\n * Check if the email service is properly configured\n */\n isConfigured(): boolean {\n return !!(this.config.smtp || this.config.sendEmail);\n }\n\n /**\n * Send an email using SMTP or custom send function\n */\n async send(options: EmailSendOptions): Promise<void> {\n // Use custom send function if provided\n if (this.config.sendEmail) {\n await this.config.sendEmail(options);\n return;\n }\n\n // Use SMTP transporter\n await this.ensureTransporter();\n\n if (!this.transporter) {\n throw new Error(\"Email service not configured. Provide SMTP config or sendEmail function.\");\n }\n\n const to = Array.isArray(options.to) ? options.to.join(\", \") : options.to;\n\n try {\n await this.transporter.sendMail({\n from: this.config.from,\n to,\n subject: options.subject,\n html: options.html,\n text: options.text,\n replyTo: options.replyTo\n });\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(\"Failed to send email\", { detail: message });\n throw new Error(`Failed to send email: ${message}`);\n }\n }\n\n /**\n * Verify SMTP connection (useful for startup checks)\n */\n async verifyConnection(): Promise<boolean> {\n await this.ensureTransporter();\n\n if (!this.transporter) {\n return !!this.config.sendEmail;\n }\n\n try {\n await this.transporter.verify();\n return true;\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(\"SMTP connection verification failed\", { detail: message });\n return false;\n }\n }\n}\n\n/**\n * Create an email service from configuration\n */\nexport function createEmailService(config: EmailConfig): EmailService {\n return new SMTPEmailService(config);\n}\n","import type { RebaseServerClient } from \"@rebasepro/types\";\n\n/**\n * The backing instance lives on a process-global slot, NOT in a module-local\n * variable — because more than one copy of this module can be loaded into one\n * process, and a module-local would leave every copy but the booting one dead.\n *\n * That is the normal layout under the managed runtime, not an edge case: the\n * image ships the framework at `/app/node_modules`, while a project's bundle\n * installs its own dependencies into `/bundle/node_modules` — and every custom\n * function imports `defineFunction` from `@rebasepro/server`, which resolves to\n * the bundle's transitively-installed copy. `initializeRebaseBackend()` then ran\n * against `/app`'s copy while every function held `/bundle`'s, so `rebase.data`,\n * `rebase.storage` and `rebase.dataAsAdmin` threw \"server not initialized yet\"\n * on EVERY request, forever, in an otherwise healthy process.\n *\n * `Symbol.for` is the fix because its registry is per-process rather than\n * per-module: whichever copy boots publishes here, and every other copy — same\n * version or not — reads the same live client.\n */\nconst INSTANCE_SLOT = Symbol.for(\"@rebasepro/server:singleton-instance\");\n\ntype GlobalWithInstance = typeof globalThis & {\n [INSTANCE_SLOT]?: RebaseServerClient | null;\n};\n\nfunction getInstance(): RebaseServerClient | null {\n return (globalThis as GlobalWithInstance)[INSTANCE_SLOT] ?? null;\n}\n\nfunction setInstance(client: RebaseServerClient | null): void {\n (globalThis as GlobalWithInstance)[INSTANCE_SLOT] = client;\n}\n\n/**\n * @internal Called once during server initialization to set the backing instance.\n * This is invoked by `initializeRebaseBackend()` — never call it manually.\n */\nexport function _initRebase(client: RebaseServerClient): void {\n setInstance(client);\n}\n\n/**\n * @internal Allows overriding the underlying instance for unit testing.\n * Throws an error if used in a non-test environment to prevent production abuse.\n */\nexport function _setRebaseMock(mockInstance: Partial<RebaseServerClient>): void {\n if (process.env.NODE_ENV !== \"test\") {\n throw new Error(\"_setRebaseMock can only be called in a test environment (NODE_ENV=test).\");\n }\n setInstance({ ...(getInstance() || {} as RebaseServerClient),\n...mockInstance } as RebaseServerClient);\n}\n\n/**\n * @internal Resets the singleton instance, useful for afterEach() in test suites.\n */\nexport function _resetRebaseMock(): void {\n if (process.env.NODE_ENV !== \"test\") {\n throw new Error(\"_resetRebaseMock can only be called in a test environment.\");\n }\n setInstance(null);\n}\n\n/**\n * The server-side Rebase singleton.\n *\n * Initialized automatically during server startup. Provides access to all\n * app-scoped services: **data**, **auth**, **storage**, and **email**.\n *\n * **Admin data plane** (`rebase.dataAsAdmin`):\n * Backed by the native DataDriver — calls go directly to the database without\n * JSON serialization, HTTP dispatch, or middleware overhead. The driver is\n * scoped as `{ uid: \"service\", roles: [\"admin\"] }`, so **every read and write\n * bypasses row-level-security policies**. No `REBASE_SERVICE_KEY` is required.\n *\n * ⚠️ Because it bypasses RLS, `rebase.dataAsAdmin` is for trusted background\n * work (cron jobs, migrations, service tasks) — **not** for serving user-facing\n * data. Inside a request handler, run user-scoped queries through the\n * request-scoped driver (`c.var.driver`), which carries the caller's identity\n * so RLS applies.\n *\n * `rebase.data` is **gone from the type**: `RebaseServerClient` omits it, so the\n * admin-scoped accessor has exactly one name and the privilege is visible at the\n * call site. The property still exists at runtime, aliasing `dataAsAdmin`, so an\n * untyped JavaScript caller keeps working rather than failing on `undefined`.\n *\n * **Control plane** (`rebase.auth`, `rebase.admin`, `rebase.storage`, etc.):\n * Routes through the Hono app's internal request handler. An internal per-boot\n * credential is generated automatically when `REBASE_SERVICE_KEY` is not set,\n * so control-plane calls always authenticate.\n *\n * @example\n * ```typescript\n * import { rebase } from \"@rebasepro/server\";\n *\n * // In a cron job, hook, or trusted service file (admin scope, bypasses RLS):\n * await rebase.email.send({ to: \"admin@co.com\", subject: \"Alert\", html: \"<p>Hi</p>\" });\n * const jobs = await rebase.dataAsAdmin.jobs.find({ limit: 10 });\n * ```\n */\nexport const rebase: RebaseServerClient = new Proxy({} as RebaseServerClient, {\n get(_, prop) {\n const instance = getInstance();\n if (!instance) {\n throw new Error(\n `rebase.${String(prop)}: server not initialized yet. ` +\n \"The singleton is available after Rebase starts — don't call it at import time.\"\n );\n }\n return instance[prop as keyof RebaseServerClient];\n },\n set(_, prop) {\n throw new Error(\n `Cannot set rebase.${String(prop)} directly. ` +\n \"The singleton is read-only. Use _initRebase() during server startup.\"\n );\n }\n});\n","import type { AuthAdapter } from \"@rebasepro/types\";\n// Type-only, so it is erased at compile time and creates no runtime cycle with\n// `init.ts` — which imports the two functions below.\nimport type { RebaseAuthConfig } from \"../init\";\n\n/**\n * Whether the `auth` config is an `AuthAdapter` (it can verify a request) or a\n * plain `RebaseAuthConfig`. Lives here rather than in `init.ts` so this module\n * stays free of it; `init.ts` re-exports it under its original name.\n */\nexport function isAuthAdapter(auth: RebaseAuthConfig | AuthAdapter): auth is AuthAdapter {\n return typeof auth === \"object\" && auth !== null && \"verifyRequest\" in auth\n && typeof (auth as AuthAdapter).verifyRequest === \"function\";\n}\n\n/**\n * Does this server require an authenticated caller?\n *\n * One predicate, because there are two enforcement points — the HTTP data\n * routes and the realtime socket — and they used to compute it separately. The\n * socket's copy read\n *\n * ```ts\n * authConfig?.requireAuth !== false && !!authConfig?.jwtSecret\n * ```\n *\n * which differs from this in two ways, both of them open. With no auth config\n * at all it returned `false` while the HTTP side returned `true`, so a server\n * that answered 401 to every `/api/data` read served the same rows over the\n * socket. And an explicit `requireAuth: true` was ANDed away whenever the\n * credential came from an adapter rather than a local `jwtSecret` — asking for\n * authentication was what switched it off.\n *\n * It is worth stating why that is worse than an ordinary missing check: the\n * socket seeds each session with `authenticated: !requireAuth`, so a `false`\n * here does not skip a gate, it marks every client that connects as already\n * past it.\n *\n * Its own module rather than a helper in `init.ts` so the drivers can import it\n * without pulling the backend entry point in behind it.\n *\n * - an `AuthAdapter` always implies auth is required (secure by default)\n * - a `RebaseAuthConfig` is honoured, and only an explicit `false` opens it\n * - no auth configuration at all defaults to required\n */\nexport function resolveRequireAuth(auth?: RebaseAuthConfig | AuthAdapter): boolean {\n if (!auth) return true;\n if (isAuthAdapter(auth)) return true;\n return (auth as RebaseAuthConfig).requireAuth !== false;\n}\n","import {\n AuthAdapter,\n BackendBootstrapper,\n BootstrappedAuth,\n DatabaseAdapter,\n DataDriver,\n DataSourceDefinition,\n CollectionCallbacks,\n AnyCollectionConfig,\n CollectionConfig,\n HealthCheckResult,\n HistoryConfig,\n InitializedDriver,\n isPostgresCollectionConfig,\n isSQLAdmin,\n RealtimeProvider,\n SecurityRule\n} from \"@rebasepro/types\";\nimport { createDataSourceRegistry, resolveDataSource, buildSdkData, buildRoutedRebaseData, getEffectiveSecurityRules } from \"@rebasepro/common\";\nimport { randomBytes } from \"node:crypto\";\nimport { BackendCollectionRegistry } from \"./collections/BackendCollectionRegistry\";\nimport { loadCollectionsFromDirectory } from \"./collections/loader\";\nimport { assertCollectionConfigs } from \"./collections/validate-config\";\nimport { DEFAULT_DRIVER_ID, DefaultDriverRegistry, DriverRegistry } from \"./services/driver-registry\";\nimport { createRoutedRealtimeService } from \"./services/routed-realtime-service\";\nimport { Server } from \"http\";\n\nimport { RestApiGenerator } from \"./api/rest/api-generator\";\nimport { createAuthMiddleware } from \"./auth/middleware\";\nimport { createAdapterAuthMiddleware } from \"./auth/adapter-middleware\";\nimport { scopeDataDriver } from \"./auth/rls-scope\";\nimport { createBuiltinAuthAdapter } from \"./auth/builtin-auth-adapter\";\nimport { errorHandler } from \"./api/errors\";\nimport { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { HonoEnv } from \"./api/types\";\nimport { configureLogLevel } from \"./utils/logging\";\nimport { logger } from \"./utils/logger\";\nimport { configureMiddlewares } from \"./init/middlewares\";\nimport { initializeStorage, assertStorageAccessControlConfigured } from \"./init/storage\";\nimport { mountOpenApiDocs } from \"./init/docs\";\nimport { createHealthCheck } from \"./init/health\";\nimport { createShutdown } from \"./init/shutdown\";\nimport { configureJwt, requireAdmin } from \"./auth\";\nimport {\n BackendStorageConfig,\n createStorageRoutes,\n StorageController,\n StorageRegistry\n} from \"./storage\";\nimport type { ApiKeyStore } from \"./auth/api-keys/api-key-store\";\nimport { createApiKeyStore } from \"./auth/api-keys/api-key-store\";\nimport { createApiKeyRoutes } from \"./auth/api-keys/api-key-routes\";\nimport { createApiKeyPreAuth, createFunctionApiKeyGuard, createStorageApiKeyGuard } from \"./auth/api-keys/api-key-middleware\";\nimport { createRequireAuth } from \"./auth/middleware\";\nimport { createDataRateLimiter, type DataRateLimitConfig } from \"./auth/rate-limiter\";\nimport { MemoryRateLimitStore } from \"./auth/rate-limit-store\";\nimport { warnOnAuthCollectionDataCallbacks } from \"./auth/collection-callback-warning\";\nimport { createRebaseClient } from \"@rebasepro/client\";\n\nimport { createHistoryRoutes } from \"./history\";\nimport type { EmailService } from \"./email\";\nimport { createEmailService, EmailConfig } from \"./email\";\nimport type { OAuthProvider } from \"./auth/interfaces\";\nimport type { AuthHooks } from \"./auth/auth-hooks\";\nimport { _initRebase } from \"./singleton\";\n\nexport interface RebaseAuthConfig {\n /**\n * The collection that represents auth users.\n *\n * When provided, this collection's underlying database table is used\n * for all auth operations (login, registration, password reset, etc.).\n *\n * Import the built-in default:\n * ```ts\n * import { defaultUsersCollection } from \"@rebasepro/common\";\n * auth: { collection: defaultUsersCollection, jwtSecret: \"...\" }\n * ```\n *\n * Or pass your own collection with the required auth fields\n * (email, passwordHash, displayName, etc.).\n */\n /**\n * Accepts a collection of any row type: `defineCollection` infers `M` from\n * the properties, and `CollectionConfig` is invariant in `M`, so a bare\n * `CollectionConfig` here rejects everything the builder returns.\n */\n collection?: AnyCollectionConfig;\n jwtSecret?: string;\n accessExpiresIn?: string;\n refreshExpiresIn?: string;\n requireAuth?: boolean;\n allowRegistration?: boolean;\n /**\n * Block self-registration outright — the hard kill switch.\n *\n * `allowRegistration: false` still admits the very first user on an empty\n * database, because otherwise a fresh deployment has no way to create its\n * own admin: `POST /admin/bootstrap` needs an authenticated caller. This\n * closes that window too, for operators who provision every account out of\n * band and never want a public first-come-first-admin race.\n *\n * With this set, an empty backend has no self-service path in at all —\n * create the first user with the CLI or a seed script.\n */\n disableSelfRegistration?: boolean;\n /**\n * Opt-in: expose `POST /auth/find-user` so an authenticated user can resolve\n * an email address to a minimal public profile (`uid`, `displayName`,\n * `photoURL` only). This powers invite-by-email flows without a custom\n * admin server function. Off by default because it enables user enumeration\n * by any signed-in user. Available on the client as `auth.findUserByEmail`.\n */\n allowUserLookup?: boolean;\n /**\n * A static secret key for server-to-server / script authentication.\n *\n * When a request includes `Authorization: Bearer <serviceKey>`, it is\n * granted admin-level access without JWT verification. This is the\n * Rebase equivalent of a Service Account key.\n *\n * Generate with: `node -e \"logger.info(require('crypto').randomBytes(48).toString('base64'))\"`\n *\n * Set via `REBASE_SERVICE_KEY` in your `.env`.\n * Must be at least 32 characters.\n */\n serviceKey?: string;\n email?: EmailConfig;\n // ── Convenience shortcuts ─────────────────────────────────────────\n // Each named field below is syntactic sugar that internally resolves\n // to an `OAuthProvider` via the corresponding `create*Provider`\n // factory at startup. They are equivalent to constructing the\n // provider manually and passing it in the `providers` array.\n //\n // For providers not listed here, or for full control over the\n // provider configuration, use the `providers` array directly.\n google?: { clientId: string; clientSecret?: string };\n linkedin?: { clientId: string; clientSecret: string };\n github?: { clientId: string; clientSecret: string };\n microsoft?: { clientId: string; clientSecret: string; tenantId?: string };\n apple?: { clientId: string; teamId: string; keyId: string; privateKey: string };\n facebook?: { clientId: string; clientSecret: string };\n twitter?: { clientId: string; clientSecret: string };\n discord?: { clientId: string; clientSecret: string };\n gitlab?: { clientId: string; clientSecret: string; baseUrl?: string };\n bitbucket?: { clientId: string; clientSecret: string };\n slack?: { clientId: string; clientSecret: string };\n spotify?: { clientId: string; clientSecret: string };\n defaultRole?: string;\n /**\n * Canonical array of OAuth providers.\n *\n * This is the primary extension point for **all** OAuth integrations.\n * Each entry is an `OAuthProvider<unknown>` constructed via one of\n * the `create*Provider` factories exported from `@rebasepro/server`\n * (e.g. `createGoogleProvider`, `createGitHubProvider`).\n *\n * The named convenience fields above (`google`, `github`, etc.) are\n * automatically resolved into this array at startup. You can mix both\n * approaches; named fields and explicit entries are merged (named\n * fields are appended after explicit entries).\n *\n * @example\n * ```ts\n * import { createGoogleProvider } from \"@rebasepro/server\";\n *\n * auth: {\n * providers: [\n * createGoogleProvider({ clientId: \"…\", clientSecret: \"…\" }),\n * ],\n * }\n * ```\n */\n providers?: OAuthProvider<unknown>[];\n /**\n * Override specific parts of the built-in auth implementation.\n *\n * Each override replaces one piece of the default behavior while\n * keeping everything else intact. Unset overrides fall through\n * to the built-in defaults (scrypt passwords, standard validation, etc.).\n *\n * @example bcrypt passwords with a custom hash\n * ```ts\n * import bcrypt from \"bcrypt\";\n *\n * hooks: {\n * hashPassword: (pw) => bcrypt.hash(pw, 12),\n * verifyPassword: (pw, hash) => bcrypt.compare(pw, hash),\n * }\n * ```\n */\n hooks?: AuthHooks;\n\n /**\n * Enable magic link (passwordless email) authentication.\n * Requires email to be configured.\n */\n magicLink?: boolean;\n /**\n * Opt-in httpOnly cookie mode for refresh tokens.\n *\n * When set, the refresh token is delivered as an `httpOnly`, `Secure`,\n * `SameSite` cookie instead of in the JSON response body. This\n * prevents XSS from stealing the long-lived refresh token.\n *\n * The access token remains in the JSON body so the client can use it\n * in `Authorization: Bearer` headers for API calls.\n *\n * **Requires** `credentials: \"include\"` on client-side fetch calls to\n * auth endpoints, and CORS must allow credentials (no `origin: \"*\"`).\n */\n cookieAuth?: import(\"./auth\").CookieAuthConfig;\n}\n\n/** @see RebaseBackendConfig.baas */\nexport interface BaasOptions {\n /**\n * What to do with introspected tables that have row-level security\n * disabled.\n *\n * Such a table carries no authorization model. Every authenticated request\n * runs as `rebase_user`, which is granted DML on the schema, so serving one\n * hands every row to every logged-in user — the API would be an open door\n * onto whatever the database happens to contain.\n *\n * - `\"exclude\"` (default) — do not serve it. Each excluded table is logged\n * with the SQL to protect it. Secure by default, consistent with the rest\n * of the driver, which fails a boot rather than serve unenforced requests.\n * - `\"serve\"` — serve it anyway. Only sensible when every caller is already\n * trusted, e.g. an internal service behind its own authorization.\n */\n unprotectedTables?: \"exclude\" | \"serve\";\n}\n\nexport interface RebaseBackendConfig {\n /** Invariance again — see the note on `RebaseAuthConfig.collection`. */\n collections?: AnyCollectionConfig[];\n collectionsDir?: string;\n server: Server;\n app: Hono<HonoEnv>;\n basePath?: string;\n\n /**\n * Rate limiting for the data API, per caller: an API key by its id, a\n * signed-in user by their uid, anyone else by IP.\n *\n * On by default with loose limits — a floor against a runaway client, not a\n * quota. Counts live in this process's memory unless you pass a `store`, so\n * N replicas enforce N times the limit between them; set real quotas at a\n * proxy or supply a shared store if that matters. `{ enabled: false }` for\n * a deployment whose edge already does this.\n */\n rateLimit?: DataRateLimitConfig;\n\n\n /**\n * Force the schema-editor routes on or off.\n *\n * Defaults to enabled when `collectionsDir` is set, outside production, in\n * `cms` mode. The editor rewrites collection files, so it needs a\n * `collectionsDir` to write to.\n */\n schemaEditor?: boolean;\n\n /** Options that only apply when collections are derived from the database. */\n baas?: BaasOptions;\n\n /**\n * Declared data sources, shared with the frontend `<Rebase dataSources>`.\n *\n * Used to resolve each collection's engine (capabilities) and transport.\n * Collections on a `direct`/`custom` transport are client-only: the backend\n * still owns their schema/registry but does **not** generate server data\n * routes for them. Server-mediated sources (the default) need no entry.\n */\n dataSources?: DataSourceDefinition[];\n\n /**\n * Database bootstrappers.\n */\n bootstrappers?: BackendBootstrapper[];\n /**\n * Database adapter.\n *\n * When set, this takes precedence over `bootstrappers`.\n *\n * @example\n * ```ts\n * import { createPostgresAdapter } from \"@rebasepro/server-postgres\";\n * database: createPostgresAdapter({ connection: db, schema }),\n * ```\n */\n database?: DatabaseAdapter;\n\n logging?: {\n level?: \"error\" | \"warn\" | \"info\" | \"debug\";\n };\n\n /**\n * Authentication configuration.\n *\n * Accepts **either**:\n * - `RebaseAuthConfig` — built-in configuration\n * - `AuthAdapter` — pluggable adapter for external auth (Clerk, Auth0, etc.)\n *\n * When a plain config object is provided, the built-in adapter is created\n * automatically from the bootstrapper's `initializeAuth()` result.\n */\n auth?: RebaseAuthConfig | AuthAdapter;\n\n /**\n * Storage configuration. Accepts:\n *\n * - A `BackendStorageConfig` object (`{ type: 'local' | 's3' | 'gcs', ... }`)\n * - A `StorageController` instance (for custom providers like Azure, etc.)\n * - A `Record<string, ...>` of either, for multi-backend setups\n */\n storage?: BackendStorageConfig | StorageController | Record<string, BackendStorageConfig | StorageController>;\n\n /**\n * Declared storage sources. Drives the client-side StorageSourceRegistry\n * and the transport distinction (server vs direct).\n *\n * Server-backed sources are auto-derived from the `storage` map — you\n * only need explicit entries for \"direct\" transport sources (e.g.\n * external storage) that the backend does not proxy.\n */\n storageSources?: import(\"@rebasepro/types\").StorageSourceDefinition[];\n\n /**\n * Per-object access control for storage — the analogue of a collection's\n * security rules, and the thing `requireAuth` / `publicRead` cannot\n * express because they are global switches.\n *\n * Called after authentication on every storage route with the key, bucket,\n * operation (`read` / `write` / `delete` / `list`) and resolved user.\n * Return false to deny with a 403; throwing denies too.\n *\n * ```ts\n * storageAuthorize: async ({ key, user, operation }) => {\n * if (!user) return false;\n * const [ownerId] = key.split(\"/\");\n * return ownerId === user.uid || operation === \"read\";\n * }\n * ```\n *\n * Without it, any authenticated caller may read any key they can name, so\n * multi-tenant apps should treat this as required rather than optional.\n *\n * In production, storage refuses to boot unless one of `storageAuthorize`,\n * {@link storagePublicRead}, or {@link storageInsecureAllowAnyAuthenticated}\n * is set — see `assertStorageAccessControlConfigured`.\n */\n storageAuthorize?: import(\"./storage/types\").StorageAuthorize;\n\n /**\n * Allow unauthenticated read access to stored files (default: false).\n *\n * Set this only when the bucket is genuinely a public, read-only CDN.\n * Writes, deletes and listing still require authentication. Because it is a\n * deliberate statement that reads are public, it also satisfies the\n * production storage boot guard (see {@link storageAuthorize}).\n */\n storagePublicRead?: boolean;\n\n /**\n * Opt out of the storage access-control boot guard, keeping the legacy\n * behaviour where **any** authenticated user can read, overwrite, delete or\n * list **any** key (storage keys share one flat namespace and are not under\n * RLS).\n *\n * Only safe for single-tenant apps where every signed-in user is trusted\n * with every file. Multi-tenant apps must use `storageAuthorize` instead.\n * Without one of these, storage refuses to boot in production.\n */\n storageInsecureAllowAnyAuthenticated?: boolean;\n\n /**\n * Entity history / audit-log configuration.\n *\n * - `true` — enable history with default settings\n * - `{ retention?: number }` — enable with optional retention period (days)\n */\n history?: HistoryConfig;\n enableSwagger?: boolean;\n functionsDir?: string;\n cronsDir?: string;\n /**\n * Enable/disable database persistence for cron job execution logs.\n * When set to false, cron jobs will run but logs will not be persisted to the database.\n * Default: true.\n */\n cronPersistence?: boolean;\n /**\n * Maximum request body size in bytes for API routes (default: 10MB).\n * Set to 0 to disable the global limit entirely.\n *\n * Note: Storage upload routes use their own limit from the storage config's\n * `maxFileSize` property (default: 50MB), which takes precedence over this.\n */\n maxBodySize?: number;\n /**\n * Response compression for API routes. **Enabled by default.**\n *\n * Compresses responses with gzip/deflate, negotiated from the request's\n * `Accept-Encoding`. Bodies that are already compressed (images, video),\n * streamed (`text/event-stream`), or explicitly marked\n * `Cache-Control: no-transform` are left untouched, so this is safe to\n * leave on — a large JSON list response typically drops by ~20x.\n *\n * Set to `false` when something in front of the app already compresses\n * (nginx, Cloudflare, or another reverse proxy / load balancer), to avoid\n * paying for it twice.\n */\n compression?: boolean;\n /**\n * CSRF protection configuration. **Opt-in** — disabled by default.\n *\n * BaaS APIs are consumed by mobile apps, SPAs on different domains,\n * and CLI tools, so CSRF is intentionally not enabled unless you\n * explicitly configure it with allowed origins.\n *\n * @example\n * ```ts\n * csrf: { origin: [\"https://myapp.com\", \"https://admin.myapp.com\"] }\n * ```\n */\n csrf?: {\n /** Allowed origins for CSRF validation. */\n origin: string | string[] | ((origin: string) => boolean);\n };\n /**\n * Global lifecycle callbacks applied to every collection.\n *\n * Same type as per-collection `callbacks` — fires on **every** data path\n * (REST API, WebSocket / realtime, server-side `rebase.data`).\n *\n * Execution order: global callbacks → collection callbacks → property callbacks.\n *\n * @example\n * ```ts\n * callbacks: {\n * afterRead({ row, collection }) {\n * console.log(`Read ${collection.slug}/${row.id}`);\n * return row;\n * }\n * }\n * ```\n */\n callbacks?: CollectionCallbacks;\n\n /**\n * Declare that this application installs its own CORS middleware.\n *\n * Suppresses the \"no CORS configuration detected\" warning, which exists for\n * hand-wired backends that genuinely have no origin policy.\n */\n corsHandled?: boolean;\n\n /**\n * The schema version this deployment serves, as recorded when it was built.\n *\n * Published by the contract endpoint so a client generated elsewhere can\n * tell whether it is current. Leave unset and the runtime computes one from\n * the live collections — correct, but it means the value moves whenever the\n * collections do, which is exactly right for `baas` mode and slightly less\n * useful for a built bundle that already knows its own answer.\n */\n schemaVersion?: string;\n\n /** Runtime version reported by the contract endpoint. Informational. */\n runtimeVersion?: string;\n}\n\n/**\n * Type guard to detect whether the `auth` config is an `AuthAdapter`\n * (has a `verifyRequest` method) vs a plain `RebaseAuthConfig` (plain object).\n *\n * Re-exported from `auth/require-auth`, which is where it now lives so the\n * drivers can reach `resolveRequireAuth` without importing this entry point.\n */\nimport { isAuthAdapter, resolveRequireAuth } from \"./auth/require-auth\";\nexport { isAuthAdapter } from \"./auth/require-auth\";\n\n/**\n * Type guard to detect whether `database` is a `DatabaseAdapter`.\n */\nexport function isDatabaseAdapter(db: unknown): db is DatabaseAdapter {\n return typeof db === \"object\" && db !== null && \"initializeDriver\" in db && \"type\" in db && !(\"initializeAuth\" in db);\n}\n\n\nexport interface RebaseBackendInstance {\n driverRegistry: DriverRegistry;\n driver: DataDriver;\n realtimeServices: Record<string, RealtimeProvider>;\n realtimeService: RealtimeProvider;\n auth?: BootstrappedAuth;\n history?: { historyService: import(\"./history/history-routes\").HistoryService };\n storageRegistry?: StorageRegistry;\n storageController?: StorageController;\n collectionRegistry: BackendCollectionRegistry;\n cronScheduler?: import(\"./cron\").CronScheduler;\n\n /**\n * Attach collection callbacks AFTER initialization.\n *\n * Use this instead of mutating `collectionRegistry.get(slug).callbacks`.\n * Every registry normalizes its collections through `{ ...c }`, so the\n * backend registry and each driver's registry hold **separate copies** of\n * the same collection — assigning callbacks to one is invisible to the\n * driver that actually invokes them, and the hooks silently never fire.\n * This writes to all of them.\n *\n * (Assignment, not `Object.defineProperty`: the driver resolves callbacks\n * with a spread, which copies only enumerable properties, and\n * defineProperty defaults `enumerable` to false.)\n */\n setCollectionCallbacks(slug: string, callbacks: import(\"@rebasepro/types\").CollectionCallbacks): void;\n\n /**\n * Deep health check that verifies database connectivity.\n * Returns latency and component status.\n */\n healthCheck(): Promise<HealthCheckResult>;\n\n /**\n * Graceful shutdown helper for the BaaS instance.\n * Stops the cron scheduler and closes the HTTP server, allowing\n * in-flight requests to drain within the given timeout.\n *\n * @param timeoutMs - Maximum time (ms) to wait for drain before force-exit (default: 15000).\n * Pass 0 to skip the force-exit timer (useful in tests).\n */\n shutdown(timeoutMs?: number): Promise<void>;\n}\n\n/**\n * Present a `DatabaseAdapter` as a `BackendBootstrapper`.\n *\n * The `config.database` convenience path — one adapter, no explicit source keys\n * — funnels through here. `adapterToBootstrapper` in `boot/driver.ts` does the\n * same job for the multi-source path, and the two stay separate because only\n * that one carries a registry id and a default flag; this path has exactly one\n * driver and needs neither.\n *\n * Extracted from the middle of `initializeRebaseBackend` so it can be tested.\n * Both wrappers rebuild the bootstrapper field by field, which means any\n * capability nobody remembers to list is dropped in silence — no type error,\n * because every one of them is optional, and no runtime error either, because\n * the caller's own fallback for \"driver does not implement this\" is to skip.\n * That is not hypothetical: `ensureCollectionSchema` was missing from both\n * wrappers for months, so every managed tenant booted with no collection tables\n * and 500'd on every data route. `bootstrapper-forwarding.test.ts` now asserts\n * both wrappers pass through the whole optional surface.\n */\nexport function wrapDatabaseAdapter(dbAdapter: DatabaseAdapter): BackendBootstrapper {\n return {\n type: dbAdapter.type,\n initializeDriver: (initConfig: unknown) =>\n dbAdapter.initializeDriver(initConfig as import(\"@rebasepro/types\").DatabaseAdapterInitConfig),\n initializeRealtime: dbAdapter.initializeRealtime\n ? (_config: unknown, driverResult: InitializedDriver) =>\n dbAdapter.initializeRealtime!(driverResult)\n : undefined,\n initializeAuth: dbAdapter.initializeAuth,\n initializeHistory: dbAdapter.initializeHistory,\n initializeWebsockets: dbAdapter.initializeWebsockets,\n ensureCollectionSchema: dbAdapter.ensureCollectionSchema\n ? (collections, driverResult, log) =>\n dbAdapter.ensureCollectionSchema!(collections, driverResult, log)\n : undefined,\n ensureCollectionPolicies: dbAdapter.ensureCollectionPolicies\n ? (collections, driverResult, log) =>\n dbAdapter.ensureCollectionPolicies!(collections, driverResult, log)\n : undefined,\n getAdmin: dbAdapter.getAdmin,\n mountRoutes: dbAdapter.mountRoutes\n };\n}\n\nexport async function initializeRebaseBackend(config: RebaseBackendConfig): Promise<RebaseBackendInstance> {\n // No try/catch: let init errors propagate to the caller.\n // The app entry point (e.g. startServer()) should catch and process.exit(1).\n // Returning a fake instance hides critical failures and leads to silent data loss.\n return await _initializeRebaseBackend(config);\n}\n\nasync function _initializeRebaseBackend(config: RebaseBackendConfig): Promise<RebaseBackendInstance> {\n if (config.logging?.level) {\n configureLogLevel(config.logging.level);\n } else {\n configureLogLevel();\n }\n\n logger.info(\"Initializing Rebase Backend\");\n\n const basePath = config.basePath || \"/api\";\n const isProduction = process.env.NODE_ENV === \"production\";\n\n // Configure Hono middlewares (Request ID, body limit, CSRF, CORS warning, logging)\n configureMiddlewares(config.app, basePath, isProduction, config);\n\n const collectionRegistry = new BackendCollectionRegistry();\n // Declared data sources — drives engine resolution (capabilities) and the\n // server-vs-direct transport distinction. Set before collections register\n // so normalization can resolve each collection's engine.\n const dataSourceRegistry = createDataSourceRegistry(config.dataSources);\n collectionRegistry.setDataSources(dataSourceRegistry);\n\n // Global lifecycle callbacks — applied to every collection, on all data paths.\n if (config.callbacks) {\n collectionRegistry.setGlobalCallbacks(config.callbacks);\n }\n let activeCollections = config.collections || [];\n // Collections handed in directly never touch the loader, so its strict parse\n // has to be repeated here. Configs derived from the database schema below are\n // machine-generated and are deliberately not checked.\n if (activeCollections.length > 0) assertCollectionConfigs(activeCollections);\n if (config.collectionsDir && activeCollections.length === 0) {\n activeCollections = await loadCollectionsFromDirectory(config.collectionsDir);\n logger.info(\"Auto-discovered collections\", {\n count: activeCollections.length,\n dir: config.collectionsDir\n });\n }\n\n // Declared collections, or the database's own schema.\n //\n // This was a `mode` flag the caller set, which could disagree with the\n // collections it was set alongside — the server then warned and threw the\n // collections away. There is no such state now: declaring collections is\n // what makes them served.\n //\n // Derived from what actually RESOLVED, not from what was configured: a\n // `collectionsDir` pointing at nothing declares nothing, and treating that\n // as \"declared\" would serve an empty API and never look at the database.\n const introspectCollections = activeCollections.length === 0;\n logger.info(\n introspectCollections\n ? \"No collections declared — deriving them from the database schema\"\n : \"Serving declared collections\"\n );\n\n // Directory-level `defaultSecurityRules` are applied by the collection\n // loader, so the server and `db push` agree on what a collection's rules\n // are. They cannot be set here: the generators that write the actual\n // Postgres policies never see this config.\n\n const realtimeServices: Record<string, RealtimeProvider> = {};\n const delegates: Record<string, DataDriver> = {};\n\n // ─── Resolve bootstrappers ───────────────────────────────────────────\n let bootstrappers: BackendBootstrapper[] = config.bootstrappers || [];\n if (config.database) {\n const dbAdapter = config.database;\n logger.info(\"Using DatabaseAdapter\", { type: dbAdapter.type });\n bootstrappers = [wrapDatabaseAdapter(dbAdapter)];\n }\n\n if (bootstrappers.length === 0) {\n throw new Error(\"No bootstrappers or database adapter provided. Cannot initialize database drivers.\");\n }\n\n let defaultDriverId = DEFAULT_DRIVER_ID;\n\n let defaultDriverResult: InitializedDriver | undefined = undefined;\n\n // 1. Initialize all drivers\n for (const bootstrapper of bootstrappers) {\n const b = bootstrapper;\n logger.info(\"Running bootstrapper for driver\", { driverId: b.id || bootstrapper.type });\n if (b.isDefault) {\n defaultDriverId = b.id || bootstrapper.type;\n }\n\n const driverResult = await bootstrapper.initializeDriver({\n collections: activeCollections,\n collectionRegistry,\n introspectCollections,\n baas: config.baas\n });\n delegates[b.id || bootstrapper.type] = driverResult.driver;\n\n // In baas mode the driver reports what it found in the database.\n // `undefined` means it never looked — it has no introspection support,\n // so baas mode can only ever serve nothing. Say so at boot rather than\n // letting every request 404 against a server that claims to be healthy.\n if (introspectCollections) {\n const driverName = b.id || bootstrapper.type;\n if (!driverResult.collections) {\n throw new Error(\n `Driver \"${driverName}\" cannot derive collections from the database schema, ` +\n \"and this project declared none. Declare collections, or use a driver that \" +\n \"implements introspection (e.g. @rebasepro/server-postgres).\"\n );\n }\n if (driverResult.collections.length === 0) {\n logger.warn(\n `Driver \"${driverName}\" found no tables to serve. The data API will not be mounted. ` +\n \"Create tables (migrations, SQL, any tool) and restart.\"\n );\n }\n }\n\n // These never passed through the config-time steps above, so apply them\n // here — but only when the driver was asked to describe the schema. A\n // project that declared its own collections must not have more injected\n // into it by whatever the database happens to contain.\n if (introspectCollections && driverResult.collections?.length) {\n activeCollections = [...activeCollections, ...driverResult.collections];\n }\n\n if ((b.id || bootstrapper.type) === defaultDriverId || !defaultDriverResult) {\n defaultDriverResult = driverResult;\n }\n\n if (bootstrapper.initializeRealtime) {\n const realtime = await bootstrapper.initializeRealtime({}, driverResult);\n if (realtime) {\n realtimeServices[b.id || bootstrapper.type] = realtime;\n }\n }\n }\n\n const driverRegistry = DefaultDriverRegistry.create(delegates);\n activeCollections.forEach(collection => collectionRegistry.register(collection));\n\n const defaultDriver = driverRegistry.getOrDefault(defaultDriverId);\n if (!defaultDriver || !defaultDriverResult) {\n throw new Error(\"Default driver not initialized by bootstrappers\");\n }\n const defaultBootstrapper = bootstrappers.find(b => b.id === defaultDriverId || b.type === defaultDriverId) || bootstrappers[0];\n const defaultRealtimeService = defaultDriverResult.realtimeProvider;\n\n // Resolve a collection path (e.g. \"products\", \"authors/1/posts\") to its\n // data-source key — shared by the data-driver router and the realtime\n // router. Falls back to the default key for unknown paths.\n const keyForCollectionPath = (collectionPath: string): string => {\n const slug = collectionPath.replace(/^\\/+/, \"\").split(\"/\")[0]?.split(\"?\")[0];\n if (!slug) return DEFAULT_DRIVER_ID;\n const collection = collectionRegistry.get(slug) ?? collectionRegistry.getCollectionByPath(slug);\n if (!collection) return DEFAULT_DRIVER_ID;\n return resolveDataSource(collection, dataSourceRegistry).key;\n };\n\n // ── Data-source misconfiguration check ────────────────────────────────\n // A server-transport collection whose resolved data-source key has no\n // registered driver delegate would silently fall back to the default\n // driver — i.e. land in the wrong database. Warn loudly so this surfaces\n // at boot rather than as mysterious data going to the wrong engine.\n {\n const unresolved = new Map<string, string[]>();\n const nonRlsEngines = new Set<string>();\n for (const collection of activeCollections) {\n const ds = resolveDataSource(collection, dataSourceRegistry);\n if (ds.transport !== \"server\") continue; // direct/custom are client-only\n // Server engines without row-level security enforce authorization\n // only at the application layer — surface this so it isn't a\n // silent assumption. (The default Postgres engine supports RLS.)\n if (!ds.capabilities.supportsRLS) nonRlsEngines.add(ds.engine);\n if (ds.key === DEFAULT_DRIVER_ID) continue; // always maps to the default\n if (!driverRegistry.has(ds.key)) {\n const slugs = unresolved.get(ds.key) ?? [];\n slugs.push(collection.slug ?? collection.name ?? \"?\");\n unresolved.set(ds.key, slugs);\n }\n }\n for (const [key, slugs] of unresolved) {\n logger.warn(\n `[DataSource] No driver registered for data source \"${key}\" ` +\n `(used by: ${slugs.join(\", \")}). These collections will fall back to the ` +\n `default driver \"${defaultDriverId}\" — register a bootstrapper with this id, ` +\n `or mark the data source as a direct/custom transport in \\`dataSources\\`.`\n );\n }\n for (const engine of nonRlsEngines) {\n logger.warn(\n `[DataSource] Engine \"${engine}\" does not support row-level security; ` +\n `authorization for its collections is enforced only at the application layer ` +\n `(authentication still applies). Ensure app-level checks or engine-native rules are in place.`\n );\n }\n }\n\n // 2. Initialize Auth & History via the default driver's bootstrapper\n let authConfigResult: BootstrappedAuth | undefined = undefined;\n let serviceKey: string | undefined;\n let authAdapter: AuthAdapter | undefined;\n\n if (config.auth) {\n if (isAuthAdapter(config.auth)) {\n // ── New path: User provided an AuthAdapter directly ──────────\n authAdapter = config.auth;\n serviceKey = authAdapter.serviceKey;\n\n if (authAdapter.initialize) {\n await authAdapter.initialize();\n }\n\n logger.info(\"Using AuthAdapter\", { id: authAdapter.id });\n\n // Populate authConfigResult for backward compatibility\n // (the return type still exposes `auth?: BootstrappedAuth`)\n authConfigResult = {\n userService: authAdapter.userManagement ?? {}\n };\n } else {\n // ── RebaseAuthConfig — wrap in built-in adapter ──\n const safeAuthConfig = config.auth as RebaseAuthConfig;\n\n // Auto-discover the auth collection from activeCollections if not explicitly set\n if (!safeAuthConfig.collection) {\n const foundAuthCollection = activeCollections.find(c => {\n const isAuth = c.auth;\n return isAuth === true || (isAuth && typeof isAuth === \"object\" && isAuth.enabled === true);\n });\n if (foundAuthCollection) {\n safeAuthConfig.collection = foundAuthCollection;\n logger.info(\"Auto-discovered auth collection from collection definitions\", { slug: foundAuthCollection.slug });\n }\n }\n\n // The built-in auth subsystem (users, sessions, repository) is\n // bootstrapped on the DEFAULT driver. If the auth collection is\n // routed to a non-default data source, login would read/write the\n // default engine while the collection's data views hit another —\n // a split-brain user store. Warn loudly.\n if (safeAuthConfig.collection) {\n const authDs = resolveDataSource(safeAuthConfig.collection, dataSourceRegistry);\n if (authDs.key !== DEFAULT_DRIVER_ID) {\n logger.warn(\n `[Auth] The auth collection \"${safeAuthConfig.collection.slug}\" is on data source ` +\n `\"${authDs.key}\", but the built-in auth system always uses the default data source. ` +\n `Move the auth collection to the default data source, or replace auth with an AuthAdapter ` +\n `that manages users in \"${authDs.key}\".`\n );\n }\n }\n\n // The auth write path does not run the collection save pipeline, on\n // purpose — say so when the collection expects otherwise.\n warnOnAuthCollectionDataCallbacks(safeAuthConfig.collection as never);\n\n // Extract the collection-level auth config (if `auth` is an object, not just `true`)\n const collectionAuth = safeAuthConfig.collection ? safeAuthConfig.collection.auth : undefined;\n const collectionAuthConfig = (typeof collectionAuth === \"object\" && collectionAuth !== null) ? collectionAuth : undefined;\n if (safeAuthConfig.jwtSecret) {\n configureJwt({\n secret: safeAuthConfig.jwtSecret,\n accessExpiresIn: safeAuthConfig.accessExpiresIn || \"1h\",\n refreshExpiresIn: safeAuthConfig.refreshExpiresIn || \"30d\"\n });\n }\n\n // ── Service Key Validation ───────────────────────────────────\n if (safeAuthConfig.serviceKey) {\n if (safeAuthConfig.serviceKey.length < 32) {\n throw new Error(\n \"REBASE_SERVICE_KEY is too short. Must be at least 32 characters. \" +\n \"Generate one with: node -e \\\"logger.info(require('crypto').randomBytes(48).toString('base64'))\\\"\"\n );\n }\n serviceKey = safeAuthConfig.serviceKey;\n logger.info(\"Service key configured for script/server-to-server authentication\");\n }\n\n if (defaultBootstrapper.initializeAuth) {\n logger.info(\"Bootstrapping authentication via driver protocol\");\n authConfigResult = await defaultBootstrapper.initializeAuth(config.auth, defaultDriverResult);\n\n // The built-in auth adapter is created after OAuth providers\n // are resolved (below) so it only needs to be constructed once.\n\n logger.info(\"Authentication initialized\");\n } else {\n logger.warn(\"Auth requested but default bootstrapper does not support initializeAuth\");\n }\n }\n }\n\n let historyConfigResult: { historyService: import(\"./history/history-routes\").HistoryService } | undefined = undefined;\n if (config.history) {\n if (defaultBootstrapper.initializeHistory) {\n logger.info(\"Bootstrapping entity history via driver protocol\");\n historyConfigResult = await defaultBootstrapper.initializeHistory(config.history, defaultDriverResult) as { historyService: import(\"./history/history-routes\").HistoryService } | undefined;\n\n // Inject the historyService into the driver so save/delete can record history.\n // The driver was created during initializeDriver() (before history was initialized),\n // so we must set it retroactively here.\n if (historyConfigResult?.historyService && defaultDriverResult.internals) {\n const internals = defaultDriverResult.internals as Record<string, unknown>;\n const driver = internals.driver as Record<string, unknown> | undefined;\n if (driver && \"historyService\" in driver) {\n driver.historyService = historyConfigResult.historyService;\n }\n }\n\n logger.info(\"Entity history initialized\");\n } else {\n logger.warn(\"History requested but default bootstrapper does not support initializeHistory\");\n }\n }\n\n // ─── Internal per-process credential ───────────────────────────────────\n // When the user hasn't configured a REBASE_SERVICE_KEY, generate a random\n // per-boot key so the singleton's control-plane APIs (auth, admin, storage,\n // functions) can still authenticate against the server's own middleware.\n // This key never leaves the process and is never logged.\n //\n // Resolved BEFORE route mounting so every admin surface — including the\n // adapter-created admin routes, whose middleware captures the key at\n // creation time — gates on the same key.\n const internalServiceKey = serviceKey || randomBytes(48).toString(\"base64\");\n if (!serviceKey) {\n logger.info(\"No REBASE_SERVICE_KEY configured. Generated internal per-boot key for singleton control-plane APIs.\");\n }\n\n // For user-provided AuthAdapters (the built-in one receives the key at\n // creation below): expose the internal key so the adapter and the\n // websocket auth path recognize the singleton's control-plane requests.\n if (authAdapter && !authAdapter.serviceKey) {\n authAdapter.serviceKey = internalServiceKey;\n }\n\n // ─── API Key Store Bootstrap ──────────────────────────────────────────\n // Bootstrapped before route mounting so `rk_` pre-auth can be registered\n // in front of every admin surface (Hono runs middleware in registration\n // order — a `use()` after `route()` would never fire for that router).\n let apiKeyStore: ApiKeyStore | undefined;\n const apiKeyStoreResult = createApiKeyStore(defaultDriver);\n if (apiKeyStoreResult) {\n apiKeyStore = apiKeyStoreResult;\n await apiKeyStore.ensureTable();\n logger.info(\"Service API Keys initialized\");\n }\n\n // Authenticates `rk_` bearer tokens in front of the JWT-based admin gates,\n // so keys created with `admin: true` genuinely reach the admin surfaces\n // (users, roles, api-keys, cron, backups, logs, schema editor) — their\n // documented behavior. Non-admin keys still fail `requireAdmin` with 403.\n const apiKeyPreAuth = apiKeyStore\n ? createApiKeyPreAuth({ store: apiKeyStore, driver: defaultDriver })\n : undefined;\n if (apiKeyPreAuth) {\n config.app.use(`${basePath}/admin/*`, apiKeyPreAuth);\n }\n\n if (apiKeyStore) {\n // Mount API key admin routes\n const apiKeyRoutes = createApiKeyRoutes({\n store: apiKeyStore,\n serviceKey: internalServiceKey\n });\n config.app.route(`${basePath}/admin/api-keys`, apiKeyRoutes);\n logger.info(\"API key admin routes mounted\", { path: `${basePath}/admin/api-keys` });\n }\n\n // One rate-limit store shared by the data and functions limiters: the\n // budget is per caller, not per router — two private stores would\n // silently double every caller's allowance. An operator-provided store\n // is respected as-is.\n const rateLimitConfig: DataRateLimitConfig | undefined =\n config.rateLimit?.enabled !== false\n ? {\n ...config.rateLimit,\n store: config.rateLimit?.store\n ?? new MemoryRateLimitStore(config.rateLimit?.windowMs ?? 15 * 60 * 1000)\n }\n : undefined;\n\n // 3. Initialize Storage\n const { storageRegistry, storageController } = await initializeStorage(config.storage, isProduction);\n\n // basePath already resolved above\n\n // 4. Mount API Routes\n if (config.auth) {\n // ── Auth Capabilities Endpoint ───────────────────────────────────\n // Exposes adapter capabilities so the frontend knows what's available\n // (login form vs external redirect, OAuth providers, etc.)\n config.app.get(`${basePath}/auth/config`, async (c) => {\n const capabilities = await authAdapter!.getCapabilities();\n return c.json(capabilities);\n });\n\n if (!isAuthAdapter(config.auth)) {\n const safeAuthConfig = config.auth as RebaseAuthConfig;\n const oauthProviders: OAuthProvider<unknown>[] = [...(safeAuthConfig.providers || [])];\n\n // Resolve configured OAuth providers via data-driven registration.\n // Each entry maps a config key to its factory function name and required fields.\n const OAUTH_PROVIDERS: Array<{\n key: keyof RebaseAuthConfig;\n factory: string;\n requiredFields: string[];\n }> = [\n { key: \"google\", factory: \"createGoogleProvider\", requiredFields: [\"clientId\"] },\n { key: \"linkedin\", factory: \"createLinkedinProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"github\", factory: \"createGitHubProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"microsoft\", factory: \"createMicrosoftProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"apple\", factory: \"createAppleProvider\", requiredFields: [\"clientId\", \"teamId\", \"keyId\", \"privateKey\"] },\n { key: \"facebook\", factory: \"createFacebookProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"twitter\", factory: \"createTwitterProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"discord\", factory: \"createDiscordProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"gitlab\", factory: \"createGitLabProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"bitbucket\", factory: \"createBitbucketProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"slack\", factory: \"createSlackProvider\", requiredFields: [\"clientId\", \"clientSecret\"] },\n { key: \"spotify\", factory: \"createSpotifyProvider\", requiredFields: [\"clientId\", \"clientSecret\"] }\n ];\n\n for (const { key, factory, requiredFields } of OAUTH_PROVIDERS) {\n const providerConfig = safeAuthConfig[key] as Record<string, unknown> | undefined;\n if (providerConfig && requiredFields.every(f => Boolean(providerConfig[f]))) {\n const authModule = await import(\"./auth\");\n const createFn = (authModule as unknown as Record<string, (cfg: unknown) => OAuthProvider<unknown>>)[factory];\n oauthProviders.push(createFn(providerConfig));\n }\n }\n\n // Re-create the built-in adapter with all resolved OAuth providers\n const reCollectionAuth = safeAuthConfig.collection ? safeAuthConfig.collection.auth : undefined;\n const collectionAuthConfig = (typeof reCollectionAuth === \"object\" && reCollectionAuth !== null) ? reCollectionAuth : undefined;\n authAdapter = createBuiltinAuthAdapter({\n authRepository: authConfigResult!.authRepository as import(\"./auth/interfaces\").AuthRepository ?? authConfigResult!.userService as import(\"./auth/interfaces\").AuthRepository,\n emailService: authConfigResult!.emailService as import(\"./email\").EmailService,\n emailConfig: safeAuthConfig.email,\n allowRegistration: safeAuthConfig.allowRegistration ?? false,\n disableSelfRegistration: safeAuthConfig.disableSelfRegistration ?? false,\n allowUserLookup: safeAuthConfig.allowUserLookup ?? false,\n defaultRole: safeAuthConfig.defaultRole,\n oauthProviders,\n // The internal per-boot fallback is included so the closure the\n // adapter's routes capture recognizes the singleton's own\n // control-plane requests even without a configured key.\n serviceKey: serviceKey || internalServiceKey,\n authHooks: safeAuthConfig.hooks,\n collectionAuthConfig,\n enableMagicLink: safeAuthConfig.magicLink ?? false,\n cookieAuth: safeAuthConfig.cookieAuth\n });\n\n if (safeAuthConfig.cookieAuth) {\n if (!isProduction && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) {\n logger.warn(\n \"[Auth] Cookie authentication (cookieAuth) is enabled, but no CORS restrictions are detected. \" +\n \"Browser-based clients will require credentials: 'include' and the server MUST NOT use \" +\n \"Access-Control-Allow-Origin: '*'. Ensure CORS_ORIGINS is set to your frontend URL.\"\n );\n }\n }\n }\n\n // ── Mount auth & admin routes via the adapter ────────────────────\n if (authAdapter && authAdapter.createAuthRoutes) {\n const authRoutes = authAdapter.createAuthRoutes();\n if (authRoutes) {\n config.app.route(`${basePath}/auth`, authRoutes);\n logger.info(\"Auth routes mounted via adapter\", { adapter: authAdapter.id });\n }\n }\n\n if (authAdapter && authAdapter.createAdminRoutes) {\n const adminRoutes = authAdapter.createAdminRoutes();\n if (adminRoutes) {\n config.app.route(`${basePath}/admin`, adminRoutes);\n logger.info(\"Admin routes mounted via adapter\", { adapter: authAdapter.id });\n }\n }\n }\n\n // ─── Shared gate for admin-only surfaces ──────────────────────────────\n // Cron, backups, logs, and the schema editor previously gated on the\n // plain JWT-only `requireAuth`, which silently rejected both the service\n // key and admin API keys while other admin surfaces accepted them. One\n // gate, same acceptance everywhere: `rk_` admin keys (via pre-auth), the\n // service key, and admin JWTs.\n // Whether admin surfaces get a gate at all — global for this boot, so\n // computed once rather than per router.\n //\n // Deliberately NOT conditioned on `requireAuth`. That flag answers a\n // question about the *data plane* — \"must a caller present a token to read\n // /api/data, or does RLS alone decide?\" — and `false` is the answer this\n // very file recommends to anyone serving a public website from their own\n // backend (see the `publicSelect` notice below). Reusing it here meant\n // taking that advice silently unmounted the gate on the cron trigger, the\n // log reader and the backup routes: one flag deciding two unrelated things,\n // where the harmless-looking value of one is catastrophic for the other.\n // Whether anonymous callers may read your posts has no bearing on whether\n // they may run your cron jobs. If auth exists at all, admin surfaces use it.\n const adminSurfacesGated = !!authAdapter && (\n isAuthAdapter(config.auth!) || !!(config.auth as RebaseAuthConfig).jwtSecret\n );\n const applyAdminGate = (router: Hono<HonoEnv>, surface: string): void => {\n if (!adminSurfacesGated) {\n // No adapter and no `jwtSecret`: there is no credential this server\n // could check a caller against, so it cannot tell an admin from the\n // internet. These surfaces used to mount anyway, open, with this\n // warning as their only defence — which is to say they served the\n // cron trigger and the log reader to anyone, and told nobody but\n // whoever was reading stdout at boot.\n //\n // They answer 501 instead, and stay mounted to say why: an\n // unexplained 404 on `/api/cron` reads as a broken path or a failed\n // deploy, and gets debugged as one.\n logger.warn(\n `${surface} routes are mounted but DISABLED: no authentication is configured ` +\n \"(no auth adapter and no auth.jwtSecret), so there is no way to tell an admin \" +\n \"from an anonymous caller. They answer 501 until auth is configured.\"\n );\n router.use(\"/*\", async (c) => c.json({\n error: {\n code: \"ADMIN_SURFACE_UNAVAILABLE\",\n message: `${surface} is admin-only, and this server has no authentication ` +\n \"configured to identify an admin with. Set auth.jwtSecret (or pass an \" +\n \"AuthAdapter) to enable it.\"\n }\n }, 501));\n return;\n }\n if (apiKeyPreAuth) router.use(\"/*\", apiKeyPreAuth);\n router.use(\"/*\", createRequireAuth({ serviceKey: internalServiceKey }), requireAdmin);\n };\n\n // The schema editor rewrites collection files, so it needs a collectionsDir\n // to write to and is off in baas mode (no files) and in production.\n const schemaEditorEnabled =\n config.schemaEditor ?? (!!config.collectionsDir && !introspectCollections && process.env.NODE_ENV !== \"production\");\n\n /**\n * Why the editor is off, in the words the person staring at a greyed-out\n * \"Add collection\" button needs.\n *\n * The admin panel used to decide whether collections were editable from\n * its *own* build mode — `process.env.NODE_ENV` inside the browser bundle.\n * That is a different process from the one that decides whether the routes\n * exist, and the two disagree constantly: a dev frontend against a\n * deployed API, a `baas`-mode project, a project with no `collectionsDir`,\n * a server without `ts-morph`. In every one of those the editor offered\n * itself and each save came back as a bare 404. So the server says whether\n * it can write, and says why not, and the client asks instead of guessing.\n */\n const schemaEditorUnavailable = (): { code: string, message: string } | undefined => {\n if (config.schemaEditor === false) return {\n code: \"SCHEMA_EDITOR_DISABLED\",\n message: \"The schema editor is turned off for this server (`schemaEditor: false`).\"\n };\n if (!config.collectionsDir) return {\n code: \"SCHEMA_EDITOR_NO_COLLECTIONS_DIR\",\n message: \"This server has no `collectionsDir`, so the schema editor has no collection files to write to.\"\n };\n if (schemaEditorEnabled) return undefined;\n if (introspectCollections) return {\n code: \"SCHEMA_EDITOR_BAAS_MODE\",\n message: \"Collections are introspected from the database on this server, so there are no \" +\n \"collection source files to edit. Change the schema with a migration instead.\"\n };\n if (process.env.NODE_ENV === \"production\") return {\n code: \"SCHEMA_EDITOR_PRODUCTION\",\n message: \"The schema editor is off under NODE_ENV=production: it edits collection source \" +\n \"files, and a deployed server's files are rebuilt from your repository on every \" +\n \"deploy, so an edit here would be discarded. Edit collections in development and deploy.\"\n };\n return {\n code: \"SCHEMA_EDITOR_DISABLED\",\n message: \"The schema editor is not enabled on this server.\"\n };\n };\n\n if (schemaEditorEnabled && !config.collectionsDir) {\n logger.warn(\"schemaEditor is enabled but no collectionsDir is set — the schema editor has nowhere to write. Skipping.\");\n }\n\n let schemaEditorOff = schemaEditorUnavailable();\n let schemaEditorRoutes: Hono<HonoEnv> | undefined;\n\n if (!schemaEditorOff && config.collectionsDir) {\n // ts-morph is an optional peer dependency, so it can legitimately be\n // absent — run without the schema editor instead of failing startup.\n try {\n const editorModule = await import(\"./api/schema-editor-routes\");\n schemaEditorRoutes = editorModule.createSchemaEditorRoutes(config.collectionsDir);\n } catch (err) {\n if ((err as { code?: string })?.code === \"ERR_MODULE_NOT_FOUND\") {\n schemaEditorOff = {\n code: \"SCHEMA_EDITOR_MISSING_DEPENDENCY\",\n message: \"The schema editor needs `ts-morph`, which is not installed on this server. \" +\n // `pnpm`, not `npm`: a Rebase project is a pnpm workspace, and\n // running npm inside one rewrites node_modules into a hoisted\n // layout that pnpm then disagrees with. Advice that damages the\n // project is worse than no advice — see docs/bug-classes.md §5.\n \"Run `pnpm add -D ts-morph@28.0.0` to enable it.\"\n };\n logger.warn(`Schema Editor disabled: ${schemaEditorOff.message}`);\n } else {\n throw err;\n }\n }\n }\n\n {\n // Gate a *fresh* router, then mount the routes into it. Hono collects\n // matching handlers in registration order, so a `use(\"/*\")` appended to\n // an already-populated router runs after the handler it was meant to\n // guard — which is to say never, because the handler has already\n // answered. Gating `createSchemaEditorRoutes()`'s return value did\n // exactly that, leaving `POST /api/schema-editor/collection/save`\n // reachable with no credentials at all: unauthenticated rewrites of the\n // project's collection source on any reachable dev server. Every other\n // admin surface here already builds the router, gates it, and *then*\n // routes into it; this one is now the same shape.\n const schemaEditorRouter = new Hono<HonoEnv>();\n\n applyAdminGate(schemaEditorRouter, \"Schema editor\");\n\n schemaEditorRouter.get(\"/status\", (c) => c.json(\n schemaEditorOff\n ? { enabled: false, reason: schemaEditorOff.message, code: schemaEditorOff.code }\n : { enabled: true }\n ));\n\n if (schemaEditorRoutes) {\n schemaEditorRouter.route(\"/\", schemaEditorRoutes);\n } else {\n // Mounted-but-refusing, like the other admin surfaces: an\n // unexplained 404 on a route the UI just called reads as a broken\n // deploy and gets debugged as one.\n schemaEditorRouter.all(\"/*\", (c) => c.json({\n error: {\n code: schemaEditorOff!.code,\n message: schemaEditorOff!.message\n }\n }, 501));\n }\n\n config.app.route(`${basePath}/schema-editor`, schemaEditorRouter);\n if (schemaEditorRoutes) {\n logger.info(\"Schema Editor mounted\", { path: `${basePath}/schema-editor` });\n } else {\n logger.debug(\"Schema Editor unavailable\", {\n path: `${basePath}/schema-editor`,\n code: schemaEditorOff!.code\n });\n }\n }\n\n // Filled in once the native data plane exists (below). The storage\n // authorize hook needs trusted reads to answer \"who owns this object?\", and\n // it cannot import the server itself — it is declared in the project's\n // config package, which depends on `@rebasepro/types` alone.\n const storageAuthorizeData: { current?: import(\"@rebasepro/types\").StorageAuthorizeData } = {};\n\n if (storageController) {\n // Storage uploads get their own body limit, derived from the storage config's\n // maxFileSize (default 50MB), which overrides the global API body limit.\n const storageMaxSize = (\n config.storage && typeof config.storage === \"object\" && \"type\" in config.storage\n ? (config.storage as BackendStorageConfig).maxFileSize\n : undefined\n ) ?? 50 * 1024 * 1024;\n\n // Storage is not under RLS and its keys share one flat namespace, so an\n // allow-all default is a cross-user read/write/delete hole. Refuse to\n // boot in production unless the deployment has stated an access-control\n // intent (a hook, public-read, or the explicit insecure opt-out); warn\n // loudly in development.\n assertStorageAccessControlConfigured(\n {\n hasAuthorize: !!config.storageAuthorize,\n publicRead: config.storagePublicRead === true,\n allowAnyAuthenticated: config.storageInsecureAllowAnyAuthenticated === true\n },\n isProduction\n );\n\n const storageRoutes = createStorageRoutes({\n controller: storageController,\n registry: storageRegistry,\n sources: config.storageSources,\n requireAuth: resolveRequireAuth(config.auth),\n publicRead: config.storagePublicRead === true,\n authAdapter,\n authorize: config.storageAuthorize,\n // Resolved lazily: the admin data plane is built further down, well\n // after these routes are mounted, but always before a request runs.\n authorizeData: () => storageAuthorizeData.current\n });\n\n // Wrapper router: middleware must be registered BEFORE the routes it\n // guards — Hono composes handlers in registration order, so a `use()`\n // issued after `createStorageRoutes()` has registered its handlers\n // sits deeper than them and never runs. The previous\n // `storageRoutes.use(\"/upload\", bodyLimit)` was exactly that: dead\n // code, leaving uploads without any size cap.\n const storageRouter = new Hono<HonoEnv>();\n\n // API keys on storage: authenticate `rk_` tokens, then require a\n // \"storage\" (or \"*\") permission entry for the derived operation.\n if (apiKeyPreAuth) {\n storageRouter.use(\"/*\", apiKeyPreAuth, createStorageApiKeyGuard());\n }\n\n // Apply a permissive body limit specifically for the upload endpoint\n storageRouter.use(\"/upload\", bodyLimit({\n maxSize: storageMaxSize,\n onError: (c) => {\n return c.json({\n error: {\n message: `File too large. Maximum upload size is ${Math.round(storageMaxSize / 1024 / 1024)}MB.`,\n code: \"PAYLOAD_TOO_LARGE\"\n }\n }, 413);\n }\n }));\n\n storageRouter.route(\"/\", storageRoutes);\n config.app.route(`${basePath}/storage`, storageRouter);\n } else {\n // No storage backend: say so, instead of 404ing as if the route were a\n // typo. A bare 404 reads as \"wrong URL\" and sends people debugging\n // their client; this names the actual state of the deployment.\n //\n // 501, not 503: this is permanent until someone configures a bucket,\n // and the client's offline queue retries 503 forever (see\n // RETRYABLE_STATUSES in @rebasepro/client), which would silently pile\n // up uploads that can never land.\n const storageStub = new Hono<HonoEnv>();\n storageStub.all(\"/*\", (c) => c.json({\n error: {\n message: \"File storage is not configured on this deployment, so uploads and \" +\n \"downloads are disabled. Configure a storage backend (STORAGE_TYPE=s3 or \" +\n \"STORAGE_TYPE=gcs plus its bucket and credentials) and redeploy.\",\n code: \"STORAGE_NOT_CONFIGURED\"\n }\n }, 501));\n config.app.route(`${basePath}/storage`, storageStub);\n logger.info(\"Storage not configured — /storage returns 501 STORAGE_NOT_CONFIGURED\");\n }\n\n if (activeCollections.length > 0) {\n const dataRouter = new Hono<HonoEnv>();\n dataRouter.onError(errorHandler);\n\n // Secure by default: require auth when auth is configured.\n // Developers who intentionally want public data access (relying\n // entirely on Postgres RLS) must explicitly set `auth.requireAuth: false`.\n const dataRequireAuth = resolveRequireAuth(config.auth);\n\n if (!dataRequireAuth) {\n logger.warn(\n \"Data routes running WITHOUT authentication enforcement. \" +\n \"Access control is fully delegated to Postgres RLS policies. \" +\n \"If no RLS policies exist, data is publicly accessible. \" +\n \"Set auth.requireAuth to true (or remove it) to require authentication.\"\n );\n } else {\n // The other half of the same decision, and the one nobody sees.\n //\n // `{ operation: \"select\", access: \"public\" }` means \"no row filter\",\n // not \"no login\" — the API gate still answers 401 to a caller with no\n // token, whatever RLS would have allowed. Read on its own, a 401 from\n // a collection the author called public looks like broken RLS or a\n // missing table, and gets debugged as one (it has been). Say it once\n // at boot, where the operator is already reading, naming the switch.\n const publicSelect = activeCollections\n .filter(c => getEffectiveSecurityRules(c).some(rule =>\n \"access\" in rule && rule.access === \"public\" &&\n (rule.operation === \"select\" || rule.operation === \"all\" ||\n (Array.isArray(rule.operations) && rule.operations.includes(\"select\")))\n ))\n .map(c => c.slug);\n\n if (publicSelect.length > 0) {\n logger.info(\n `${publicSelect.length} collection(s) grant unfiltered reads (${publicSelect.join(\", \")}), ` +\n \"but every /api/data route still requires a token: `access: \\\"public\\\"` widens which ROWS a \" +\n \"caller sees, not who may call. An unauthenticated read answers 401 regardless. \" +\n \"To let RLS alone decide — the usual choice for a public website reading its own backend — \" +\n \"set AUTH_REQUIRE=false (or `auth.requireAuth: false`).\"\n );\n }\n }\n\n // Multi-data-source routing: when more than one database engine is\n // registered (e.g. Postgres + MongoDB in one instance), resolve the\n // delegate per request from the request's collection data source. The\n // auth middleware then scopes that delegate (RLS for Postgres, no-op\n // for engines without `withAuth()`) into the request context. For a\n // single-engine backend this is omitted — behaviour is unchanged.\n const dataPathMarker = `${basePath}/data/`;\n const resolveRequestDriver = (reqPath: string): DataDriver => {\n const i = reqPath.indexOf(dataPathMarker);\n const collectionPath = i >= 0 ? reqPath.slice(i + dataPathMarker.length) : reqPath;\n const key = keyForCollectionPath(collectionPath);\n // Use the authoritative default for the default key; otherwise the\n // named delegate, falling back to default if it isn't registered.\n if (!key || key === DEFAULT_DRIVER_ID) return defaultDriver;\n return driverRegistry.get(key) ?? defaultDriver;\n };\n const multiEngine = bootstrappers.length > 1;\n const resolveDriver = multiEngine ? ((c: { req: { path: string } }) => resolveRequestDriver(c.req.path)) : undefined;\n\n // Use adapter middleware when an AuthAdapter is available,\n // falling back to the built-in JWT middleware otherwise.\n if (authAdapter) {\n dataRouter.use(\"/*\", createAdapterAuthMiddleware({\n adapter: authAdapter,\n driver: defaultDriver,\n resolveDriver,\n requireAuth: dataRequireAuth,\n apiKeyStore\n }));\n } else {\n dataRouter.use(\"/*\", createAuthMiddleware({\n driver: defaultDriver,\n resolveDriver,\n requireAuth: dataRequireAuth,\n serviceKey: internalServiceKey,\n apiKeyStore\n }));\n }\n\n // Rate limiting, per caller: API key, else signed-in user, else IP.\n // Not gated on `apiKeyStore` any more — that made the limiter's\n // presence depend on a feature it does not need, so a deployment\n // without API keys had no limit at all on its data API.\n if (rateLimitConfig) {\n dataRouter.use(\"/*\", createDataRateLimiter(rateLimitConfig));\n }\n\n // Mount history routes BEFORE the REST API subcollection catch-all so\n // that /:slug/:id/history is matched by the dedicated handler first.\n if (historyConfigResult && historyConfigResult.historyService) {\n const historyRoutes = createHistoryRoutes({\n historyService: historyConfigResult.historyService,\n registry: collectionRegistry,\n driver: defaultDriver\n });\n dataRouter.route(\"/\", historyRoutes);\n }\n\n // Only generate server data routes for server-mediated collections.\n // Collections on a direct/custom transport are client-only — the\n // backend must not expose a (mis-engined) endpoint for them.\n const serverCollections = activeCollections.filter(\n (collection) => resolveDataSource(collection, dataSourceRegistry).transport === \"server\"\n );\n\n const restGenerator = new RestApiGenerator(\n serverCollections,\n defaultDriver,\n authAdapter\n );\n dataRouter.route(\"/\", restGenerator.generateRoutes());\n\n config.app.route(`${basePath}/data`, dataRouter);\n }\n\n // ── OpenAPI / Swagger ─────────────────────────────────────────────────\n await mountOpenApiDocs(config.app, basePath, config.enableSwagger, activeCollections, resolveRequireAuth(config.auth));\n\n // ─── Server-side singleton ────────────────────────────────────────────\n // Build the RebaseClient for control-plane APIs (auth, admin, storage,\n // functions, cron). These still route through the Hono app because they\n // genuinely need route dispatch + middleware.\n // `rebase.data` is replaced below with a native driver-backed data plane.\n const serverClient = createRebaseClient({\n baseUrl: \"http://localhost\",\n apiPath: basePath,\n websocketUrl: \"\",\n token: internalServiceKey,\n fetch: async (input: RequestInfo | URL, init?: RequestInit) => {\n return await config.app.request(input as string | Request | URL, init);\n }\n });\n\n // ─── Native data plane ────────────────────────────────────────────────\n // Replace the HTTP-transport data layer with a driver-backed RebaseData.\n // This eliminates JSON serialize → Hono dispatch → auth → deserialize for\n // every rebase.data call. RLS semantics are preserved: the driver is scoped\n // once as { uid: \"service\", roles: [\"admin\"] }, matching the identity the\n // service-key HTTP path produced.\n const serviceIdentity = { uid: \"service\", roles: [\"admin\"] as string[] };\n\n const scopedDefaultDriver = await scopeDataDriver(defaultDriver, serviceIdentity);\n const defaultData = buildSdkData(scopedDefaultDriver);\n\n // Hand the storage authorize hook its trusted reader. Scoped as the service\n // identity, so an ownership lookup is not itself filtered by the caller's\n // permissions — the hook IS the permission decision.\n storageAuthorizeData.current = defaultData as unknown as import(\"@rebasepro/types\").StorageAuthorizeData;\n\n // Multi-engine: scope and wrap each non-default delegate so\n // rebase.data on a non-default-engine collection reaches the correct driver.\n const dataSourcesByKey: Record<string, import(\"@rebasepro/types\").RebaseSdkData> = {};\n for (const driverKey of driverRegistry.list()) {\n if (driverKey === DEFAULT_DRIVER_ID) continue;\n const delegate = driverRegistry.get(driverKey);\n if (!delegate) continue;\n const scopedDelegate = await scopeDataDriver(delegate, serviceIdentity);\n dataSourcesByKey[driverKey] = buildSdkData(scopedDelegate);\n }\n\n const serverData = buildRoutedRebaseData({\n defaultData,\n sources: dataSourcesByKey,\n resolveKey: (slugOrPath: string) => keyForCollectionPath(slugOrPath)\n });\n\n // Overwrite the HTTP-transport data proxy with the native driver-backed one.\n // The rest of the client (auth, admin, cron, functions, storage) keeps using\n // the HTTP transport, which is fine — they are low-frequency control-plane ops.\n //\n // `dataAsAdmin` is the admin accessor, and the only one `RebaseServerClient`\n // declares — `data` is `Omit`ted from the type so the privilege has to be\n // named at the call site.\n //\n // It is still assigned here on purpose. `createRebaseClient` above already\n // put an HTTP-transport `data` on this object, so *not* overwriting it would\n // leave `rebase.data` working in plain JS while quietly routing through the\n // loop this native plane exists to skip — a silent performance and identity\n // change instead of the compile error TypeScript now gives. Both names point\n // at the same admin-scoped, RLS-bypassing object.\n Object.assign(serverClient, { data: serverData, dataAsAdmin: serverData });\n logger.info(\"Native data plane attached to singleton (bypasses HTTP loop)\");\n\n // Same treatment for storage: server-side `rebase.storage` must talk to the\n // controller directly, not loop back through `POST /api/storage/upload`. The\n // loopback carried the service key but still 403'd (the storage route's auth\n // is written for real user/session requests, not the internal self-call), so\n // every backend-initiated write — e.g. the deploy build-context upload —\n // failed at ~2ms with \"Request failed with status 403\". The controller\n // exposes the same StorageSource surface (putObject/getObject/…).\n if (storageController) {\n Object.assign(serverClient, { storage: storageController });\n logger.info(\"Native storage attached to singleton (bypasses HTTP loop)\");\n }\n\n // Attach email service to the server client when configured.\n // The email service may come from the auth bootstrapper or from the auth config directly.\n let emailService: EmailService | undefined;\n if (authConfigResult?.emailService) {\n emailService = authConfigResult.emailService as EmailService;\n } else if (config.auth && !isAuthAdapter(config.auth) && (config.auth as RebaseAuthConfig).email) {\n emailService = createEmailService((config.auth as RebaseAuthConfig).email!);\n }\n\n if (emailService) {\n Object.assign(serverClient, { email: emailService });\n logger.info(\"Email service attached to singleton\", { configured: emailService.isConfigured() });\n\n if (emailService.isConfigured() && typeof emailService.verifyConnection === \"function\") {\n emailService.verifyConnection().then((success) => {\n if (!success) {\n logger.warn(\"Warning: SMTP connection verification failed. Email delivery may fail.\");\n } else {\n logger.info(\"SMTP connection verified successfully.\");\n }\n }).catch((err) => {\n logger.warn(\"Warning: SMTP connection verification failed. Email delivery may fail.\", { error: err });\n });\n }\n }\n\n // Attach raw SQL capability when the driver supports it (Postgres, MySQL).\n // Document databases (MongoDB, Firestore) won't have this.\n const driverAdmin = defaultBootstrapper.getAdmin?.(defaultDriverResult);\n if (isSQLAdmin(driverAdmin)) {\n Object.assign(serverClient, {\n sql: (query: string, options?: { database?: string; role?: string; params?: unknown[] }) =>\n driverAdmin.executeSql(query, options)\n });\n logger.info(\"SQL capability attached to singleton\");\n }\n\n // The server client is assembled dynamically above (native data plane,\n // dataAsAdmin, email, sql attached via Object.assign), so TS can't see the\n // full RebaseServerClient shape statically — cast at the boundary.\n _initRebase(serverClient as unknown as import(\"@rebasepro/types\").RebaseServerClient);\n logger.info(\"Rebase singleton initialized\");\n\n // Retroactively inject the server client into the driver so that\n // entity callbacks receive `context.client` at runtime.\n // The driver is created before the client (which depends on the mounted\n // Hono app), so we set it here, mirroring the historyService injection above.\n if (defaultDriverResult.internals) {\n const internals = defaultDriverResult.internals as Record<string, unknown>;\n const driver = internals.driver as Record<string, unknown> | undefined;\n if (driver && \"client\" in driver) {\n driver.client = serverClient;\n }\n }\n\n // 5. Mount Custom Functions\n if (config.functionsDir) {\n const { loadFunctionsFromDirectory } = await import(\"./functions/function-loader\");\n const { createFunctionRoutes } = await import(\"./functions/function-routes\");\n\n const loadedFunctions = await loadFunctionsFromDirectory(config.functionsDir);\n\n if (loadedFunctions.length > 0) {\n const functionsRouter = new Hono<HonoEnv>();\n functionsRouter.onError(errorHandler);\n\n // Custom functions do NOT require authentication at the global level by default.\n // This allows custom functions to define public endpoints (like webhooks).\n // Per-route auth can be further refined inside individual functions using `requireAuth`.\n const functionsRequireAuth = false;\n\n // Use adapter middleware when available, fallback to built-in\n if (authAdapter) {\n functionsRouter.use(\"/*\", createAdapterAuthMiddleware({\n adapter: authAdapter,\n driver: defaultDriver,\n requireAuth: functionsRequireAuth,\n apiKeyStore\n }));\n } else {\n functionsRouter.use(\"/*\", createAuthMiddleware({\n driver: defaultDriver,\n requireAuth: functionsRequireAuth,\n serviceKey: internalServiceKey,\n apiKeyStore\n }));\n }\n\n // API-key requests must hold a \"functions\"/\"functions/<name>\"\n // permission (or the \"*\" wildcard). Without this, any valid key —\n // however narrowly scoped — could invoke every custom function.\n functionsRouter.use(\"/*\", createFunctionApiKeyGuard(`${basePath}/functions`));\n\n // Same per-caller rate limiting as the data API, sharing its\n // store so one caller has one budget. Previously only /api/data\n // was limited, so a key's rate_limit did not bound its function\n // traffic at all.\n //\n // The anonymous bucket is disabled here: functions default to\n // public access precisely for webhook receivers (Stripe, GitHub),\n // whose bursts come from a handful of provider IPs — an IP-keyed\n // 300/window cap would 429 them. Anonymous function traffic was\n // never limited before; keys and signed-in users now are.\n if (rateLimitConfig) {\n functionsRouter.use(\"/*\", createDataRateLimiter({ ...rateLimitConfig, anonymous: null }));\n }\n\n const fnRoutes = createFunctionRoutes(loadedFunctions);\n functionsRouter.route(\"/\", fnRoutes);\n config.app.route(`${basePath}/functions`, functionsRouter);\n logger.info(\"Mounted custom functions\", {\n count: loadedFunctions.length,\n path: `${basePath}/functions`\n });\n }\n }\n\n // 6. Mount Cron Jobs\n let cronScheduler: import(\"./cron\").CronScheduler | undefined;\n if (config.cronsDir) {\n const { loadCronJobsFromDirectory } = await import(\"./cron/cron-loader\");\n const { CronScheduler } = await import(\"./cron/cron-scheduler\");\n const { createCronRoutes } = await import(\"./cron/cron-routes\");\n const { createCronStore } = await import(\"./cron/cron-store\");\n\n const loadedCronJobs = await loadCronJobsFromDirectory(config.cronsDir);\n\n cronScheduler = new CronScheduler();\n\n // The cron scheduler uses the same serverClient as the singleton.\n // ctx.client inside cron handlers IS the same `rebase` instance.\n cronScheduler.setClient(serverClient);\n\n if (loadedCronJobs.length > 0) {\n cronScheduler.registerJobs(loadedCronJobs);\n\n // Attach database persistence if the driver supports SQL and persistence is enabled\n const admin = defaultBootstrapper.getAdmin?.(defaultDriverResult);\n const store = (admin && config.cronPersistence !== false) ? createCronStore(defaultDriver) : undefined;\n if (store) {\n await store.ensureTable();\n cronScheduler.setStore(store);\n }\n }\n\n // Mounted for the directory, not for the jobs in it. Mounting only when\n // something loaded meant a single unparseable file — a syntax error, an\n // import that throws, a module the loader could not read — took the\n // whole cron surface with it: `/api/cron` 404ed, the Studio panel broke,\n // and the only trace was one line in the boot log. An empty list is the\n // honest answer, and it is a debuggable one.\n const cronRouter = new Hono<HonoEnv>();\n\n // Cron admin routes require authentication + admin role\n applyAdminGate(cronRouter, \"Cron\");\n\n cronRouter.route(\"/\", createCronRoutes(cronScheduler));\n config.app.route(`${basePath}/cron`, cronRouter);\n\n if (loadedCronJobs.length > 0) {\n cronScheduler.start();\n logger.info(\"Mounted cron jobs\", {\n count: loadedCronJobs.length,\n path: `${basePath}/cron`\n });\n } else {\n logger.warn(\n `Cron routes mounted at ${basePath}/cron, but no jobs loaded from ${config.cronsDir}. ` +\n \"Nothing is scheduled — check the messages above for files that failed to load.\"\n );\n }\n }\n\n // 6b. Mount Backup admin routes (for the Studio Backups panel).\n // Read the destination lazily from env so config changes don't need a\n // rebuild. Only enabled when BACKUP_DESTINATION is set.\n {\n const { createBackupRoutes, parseBackupDestination } = await import(\"./backup\");\n const backupRouter = new Hono<HonoEnv>();\n\n applyAdminGate(backupRouter, \"Backup\");\n\n backupRouter.route(\"/\", createBackupRoutes({\n getDestination: () => {\n const out = process.env.BACKUP_DESTINATION?.trim();\n return out ? parseBackupDestination(out) : null;\n },\n storage: storageController\n }));\n config.app.route(`${basePath}/admin/backups`, backupRouter);\n logger.info(\"Backup admin routes mounted\", { path: `${basePath}/admin/backups` });\n }\n\n // 6c. Mount Logs routes (for the Studio Logs Explorer). Request logs expose\n // paths, status codes and correlation IDs, so they are admin-only — the same\n // posture as the cron and backup admin routes above.\n {\n const { default: logsRoutes } = await import(\"./api/logs-routes\");\n const logsRouter = new Hono<HonoEnv>();\n\n applyAdminGate(logsRouter, \"Logs\");\n\n logsRouter.route(\"/\", logsRoutes);\n config.app.route(`${basePath}/logs`, logsRouter);\n logger.info(\"Logs routes mounted\", { path: `${basePath}/logs` });\n }\n\n // 6d. Mount the project contract — what lets a repository that does *not*\n // contain the collections still generate a typed client against them. This\n // is the backbone of frontends, second web apps and mobile apps living in\n // their own repositories.\n //\n // Mounted here rather than by the bundle runtime so a project with a\n // hand-written entrypoint gets it too: ejecting should cost you the stock\n // runtime, not the API surface.\n {\n const { createContractRoutes } = await import(\"./api/contract-routes\");\n const contractRouter = new Hono<HonoEnv>();\n\n // Only `/contract` is gated: it is a full map of the schema, including\n // tables no security rule would ever expose. Its sibling\n // `/schema-version` returns a bare version string that stands for the\n // schema without describing it, and is deliberately reachable by a CI\n // job holding no credentials.\n //\n // With no way to gate it, `/contract` is not served at all — the same\n // answer `applyAdminGate` gives the other admin surfaces, which refuse\n // rather than open when there is no credential to check. It differs only\n // in status: this one is 404 because it is not an operation someone\n // tried to perform, it is a document that is not there. Configure auth\n // and it returns.\n if (adminSurfacesGated) {\n if (apiKeyPreAuth) contractRouter.use(\"/contract\", apiKeyPreAuth);\n contractRouter.use(\n \"/contract\",\n createRequireAuth({ serviceKey: internalServiceKey }),\n requireAdmin\n );\n } else {\n contractRouter.all(\"/contract\", (c) => c.json({\n error: {\n code: \"CONTRACT_UNAVAILABLE\",\n message: \"The project contract is only served when authentication is configured, \" +\n \"because it describes every table and relation in the project.\"\n }\n }, 404));\n logger.warn(\n \"Contract endpoint disabled: no auth is configured (no adapter or no jwtSecret), \" +\n \"and it would otherwise expose the full collection schema to anyone. \" +\n \"`/api/meta/schema-version` is still served.\"\n );\n }\n\n contractRouter.route(\"/\", createContractRoutes({\n collectionRegistry,\n schemaVersion: config.schemaVersion,\n runtimeVersion: config.runtimeVersion\n }));\n\n config.app.route(`${basePath}/meta`, contractRouter);\n logger.info(\"Contract routes mounted\", { path: `${basePath}/meta` });\n }\n\n // With multiple realtime-capable engines, route subscriptions to the\n // provider owning each collection (the realtime counterpart of the data\n // router). The single WebSocket server is driven by this composite.\n // Single-engine setups use the default provider unchanged.\n const effectiveRealtimeService: RealtimeProvider = Object.keys(realtimeServices).length > 1\n ? createRoutedRealtimeService({\n providers: realtimeServices,\n defaultKey: defaultDriverId,\n resolveKey: keyForCollectionPath\n })\n : defaultRealtimeService as RealtimeProvider;\n\n if (defaultBootstrapper.initializeWebsockets && effectiveRealtimeService) {\n await defaultBootstrapper.initializeWebsockets(config.server, effectiveRealtimeService, defaultDriver, config.auth, authAdapter);\n }\n\n logger.info(\"Rebase Backend Initialized\");\n\n // ── Deep Health Check ─────────────────────────────────────────────────\n // The auth probe is only available when a driver bootstrapped auth — an\n // AuthAdapter or a deployment without auth leaves it undefined, and the\n // health check falls back to the database probe alone.\n const authSchemaCheck = authConfigResult?.schemaHealthCheck;\n const healthCheck = createHealthCheck(\n defaultDriver,\n authSchemaCheck ? () => authSchemaCheck.call(authConfigResult) : undefined\n );\n\n // ── Graceful Shutdown ─────────────────────────────────────────────────\n const shutdown = createShutdown({\n server: config.server,\n cronScheduler,\n realtimeServices\n });\n\n /**\n * Every registry a driver might resolve callbacks from, plus the backend's\n * own. Each holds its own normalized copy of a collection, so callbacks have\n * to be written to all of them.\n */\n const callbackTargets = (): Array<{ get(slug: string): unknown }> => {\n const targets: Array<{ get(slug: string): unknown }> = [collectionRegistry];\n for (const key of [DEFAULT_DRIVER_ID, ...driverRegistry.list()]) {\n const d = driverRegistry.get(key) as unknown as { registry?: { get(slug: string): unknown } };\n if (d?.registry && typeof d.registry.get === \"function\" && !targets.includes(d.registry)) {\n targets.push(d.registry);\n }\n }\n return targets;\n };\n\n const setCollectionCallbacks = (\n slug: string,\n callbacks: import(\"@rebasepro/types\").CollectionCallbacks\n ): void => {\n let attached = 0;\n for (const registry of callbackTargets()) {\n const collection = registry.get(slug) as { callbacks?: unknown } | undefined;\n if (collection) {\n collection.callbacks = callbacks;\n attached++;\n }\n }\n if (attached === 0) {\n logger.warn(`[callbacks] Collection \"${slug}\" not found in any registry — callbacks not attached.`);\n }\n };\n\n return {\n driverRegistry,\n driver: defaultDriver,\n setCollectionCallbacks,\n realtimeServices,\n realtimeService: effectiveRealtimeService,\n auth: authConfigResult,\n history: historyConfigResult,\n storageRegistry,\n storageController,\n collectionRegistry,\n cronScheduler,\n healthCheck,\n shutdown\n };\n}\n","import { Hono } from \"hono\";\nimport type { RebaseServerClient } from \"@rebasepro/types\";\nimport type { HonoEnv } from \"../api/types\";\nimport { rebase } from \"../singleton\";\n\n/**\n * Typed context injected into a function authored with {@link defineFunction}.\n *\n * Surfaces the app-scoped Rebase singleton so handlers don't need to reach\n * for the global `rebase` import. Request-scoped values (the authenticated\n * `user`, the RLS-scoped `driver`, the `apiKey`, the `requestId`) are typed\n * on the Hono context via {@link HonoEnv} — read them with `c.get(\"user\")`\n * / `c.var.driver` inside a handler.\n */\nexport interface RebaseFunctionContext {\n /**\n * The server-side Rebase singleton (`dataAsAdmin`, `auth`, `storage`,\n * `email`, `sql`).\n *\n * `rebase.dataAsAdmin` runs with **admin privileges and bypasses RLS** — use\n * it only for trusted admin work. For user-scoped queries inside a handler,\n * use the request `driver` (`c.var.driver`), which carries the caller's\n * identity so RLS applies. (`rebase.data` no longer exists on this type —\n * `dataAsAdmin` is the only name for the admin-scoped accessor.)\n */\n rebase: RebaseServerClient;\n}\n\n/**\n * Typed authoring contract for a custom backend function.\n *\n * A custom function is a file in the `functionsDir` that default-exports a\n * Hono app; the loader mounts it at `/<filename>`. `defineFunction` is the\n * typed opt-in for that contract: it hands you a pre-typed `Hono<HonoEnv>`\n * app (so `c.var.user` / `c.var.driver` are typed) plus a\n * {@link RebaseFunctionContext}, and returns exactly the Hono app the loader\n * already accepts — so it is fully interchangeable with a plain\n * `export default new Hono()`.\n *\n * @example\n * ```ts\n * import { defineFunction, requireAuth } from \"@rebasepro/server\";\n *\n * export default defineFunction((app, { rebase }) => {\n * app.use(\"/*\", requireAuth);\n * app.get(\"/home\", async (c) => {\n * const [stats] = await rebase.sql!(`SELECT count(*) AS n FROM orders`);\n * return c.json({ orders: Number(stats.n) });\n * });\n * });\n * ```\n *\n * @param definition Receives the function's Hono app and the typed context.\n * Register routes on the provided `app` and return nothing, or return your\n * own `Hono<HonoEnv>` app to use instead.\n * @returns The Hono app to default-export from the function file.\n */\nexport function defineFunction(\n definition: (app: Hono<HonoEnv>, ctx: RebaseFunctionContext) => void | Hono<HonoEnv>\n): Hono<HonoEnv> {\n const app = new Hono<HonoEnv>();\n const returned = definition(app, { rebase });\n return returned instanceof Hono ? returned : app;\n}\n","import type { CronJobDefinition } from \"@rebasepro/types\";\n\n/**\n * Typed authoring helper for a cron job file. Identity at runtime —\n * a plain default-exported {@link CronJobDefinition} works identically;\n * this adds type inference and autocomplete.\n *\n * @see {@link defineFunction} for the equivalent custom-functions helper.\n *\n * @example\n * ```ts\n * import { defineCron } from \"@rebasepro/server\";\n *\n * export default defineCron({\n * name: \"Nightly cleanup\",\n * schedule: \"0 3 * * *\",\n * async handler({ client, log }) {\n * const { data: expired } = await client.data.sessions.find({\n * where: { expired: [\"==\", true] },\n * });\n * for (const session of expired) {\n * await client.data.sessions.delete(session.id);\n * }\n * log(`Deleted ${expired.length} expired sessions`);\n * },\n * });\n * ```\n */\nexport function defineCron(definition: CronJobDefinition): CronJobDefinition {\n return definition;\n}\n","import { sql, SQL } from \"drizzle-orm\";\n\n/**\n * Returns a SQL chunk calling `auth.uid()` — the current user's ID.\n * This is a PostgreSQL RLS helper function created in the `auth` schema\n * that reads `app.uid` set per-transaction by `withAuth()`.\n *\n * @example\n * sql`${table.uid} = ${authUid()}`\n */\nexport const authUid = (): SQL => {\n return sql`auth.uid()`;\n};\n\n/**\n * Returns a SQL chunk calling `auth.roles()` — the current user's roles\n * as a comma-separated string.\n * Reads `app.user_roles` set per-transaction by `withAuth()`.\n *\n * @example\n * sql`auth.roles() ~ 'admin'`\n */\nexport const authRoles = (): SQL => {\n return sql`auth.roles()`;\n};\n\n/**\n * Returns a SQL chunk calling `auth.jwt()` — the full JWT claims as JSONB.\n * Reads `app.jwt` set per-transaction by `withAuth()`.\n *\n * @example\n * sql`auth.jwt()->>'sub'`\n */\nexport const authJwt = (): SQL => {\n return sql`auth.jwt()`;\n};\n\n\n","import { z } from \"zod\";\nimport * as crypto from \"crypto\";\nimport { logger } from \"./utils/logger\";\n\n/**\n * Generate a cryptographically secure random secret (hex-encoded).\n * Used as a fallback when secrets are not explicitly configured —\n * avoids the need for hardcoded dev secrets.\n */\nfunction generateSecret(bytes = 48): string {\n return crypto.randomBytes(bytes).toString(\"hex\");\n}\n\n/**\n * Zod coercion helper: transforms `\"true\"` → `true`, everything else → `false`.\n */\nconst boolString = z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\");\n\n/**\n * Zod coercion helper for optional boolean strings.\n */\nconst optionalBoolString = z.enum([\"true\", \"false\", \"\"]).optional().transform(v => v === \"true\");\n\n/**\n * Helper to determine if a string is a localhost or loopback address/URL.\n */\nfunction isLocalhostOrLoopback(value: string): boolean {\n const trimmed = value.trim();\n if (!trimmed) return false;\n\n // 1. Try parsing as URL\n try {\n const parsed = new URL(trimmed);\n const host = parsed.hostname.toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host.startsWith(\"127.\")\n ) {\n return true;\n }\n } catch {\n // Not a standard URL, or custom protocol that URL class fails to parse\n }\n\n // 2. Custom protocol parser fallback (e.g. postgres://, mongodb://, etc.)\n const protocolMatch = trimmed.match(/^[a-zA-Z0-9+-.]+:\\/\\/(?:[^@/]+@)?(?:\\[([^\\]]+)\\]|([^:/]+))/);\n if (protocolMatch) {\n const host = (protocolMatch[1] || protocolMatch[2] || \"\").toLowerCase();\n if (\n host === \"localhost\" ||\n host === \"127.0.0.1\" ||\n host === \"::1\" ||\n host.startsWith(\"127.\")\n ) {\n return true;\n }\n }\n\n // 3. Plain hostname / host:port checker (e.g. \"localhost\", \"127.0.0.1:5432\", \"[::1]:6379\")\n let plainHost = trimmed.toLowerCase();\n if (plainHost.startsWith(\"[\") && plainHost.includes(\"]\")) {\n const endBracket = plainHost.indexOf(\"]\");\n plainHost = plainHost.slice(1, endBracket);\n } else {\n const colonIndex = plainHost.lastIndexOf(\":\");\n if (colonIndex !== -1 && plainHost.indexOf(\":\") === colonIndex) {\n plainHost = plainHost.substring(0, colonIndex);\n }\n }\n\n if (\n plainHost === \"localhost\" ||\n plainHost === \"127.0.0.1\" ||\n plainHost === \"::1\" ||\n plainHost.startsWith(\"127.\")\n ) {\n return true;\n }\n\n return false;\n}\n\n/**\n * The full set of environment variables recognized by a Rebase backend.\n */\nconst rebaseEnvSchema = z.object({\n NODE_ENV: z.enum([\"development\", \"production\", \"test\"]).default(\"development\"),\n PORT: z.string().default(\"3001\").transform(Number),\n DATABASE_URL: z.string().url(\"DATABASE_URL must be a valid URL\"),\n ADMIN_CONNECTION_STRING: z.string().url().optional(),\n JWT_SECRET: z.string().min(32, \"JWT_SECRET must be at least 32 characters long\"),\n JWT_ACCESS_EXPIRES_IN: z.string().default(\"1h\"),\n // Sliding: every rotation re-ups it, so this governs how long a session\n // survives INACTIVITY, not how long it survives. 400d is the ceiling any\n // browser will honour on the cookie that carries it.\n JWT_REFRESH_EXPIRES_IN: z.string().default(\"400d\"),\n GOOGLE_CLIENT_ID: z.string().optional(),\n GOOGLE_CLIENT_SECRET: z.string().optional(),\n REBASE_SERVICE_KEY: z.string().optional(),\n ALLOW_REGISTRATION: boolString,\n // The kill switch, which also closes the empty-database bootstrap window\n // that ALLOW_REGISTRATION=false deliberately leaves open. Optional so an\n // unset variable means \"not configured\" rather than an explicit false.\n DISABLE_SELF_REGISTRATION: optionalBoolString,\n ALLOW_LOCALHOST_IN_PRODUCTION: optionalBoolString,\n CORS_ORIGINS: z.string().optional(),\n FRONTEND_URL: z.string().optional(),\n DB_POOL_MAX: z.string().default(\"20\").transform(Number),\n DB_POOL_IDLE_TIMEOUT: z.string().default(\"30000\").transform(Number),\n DB_POOL_CONNECT_TIMEOUT: z.string().default(\"10000\").transform(Number),\n DATABASE_DIRECT_URL: z.string().url().optional(),\n DATABASE_READ_URL: z.string().url().optional(),\n FORCE_LOCAL_STORAGE: optionalBoolString,\n // `gcs` is a first-class storage backend (GCSStorageController) and a valid\n // `type` in BackendStorageConfig, so it must validate here too — otherwise\n // an app that selects GCS from this variable dies in loadEnv before its own\n // config code ever runs.\n STORAGE_TYPE: z.enum([\"local\", \"s3\", \"gcs\"]).default(\"local\"),\n STORAGE_PATH: z.string().optional(),\n S3_BUCKET: z.string().optional(),\n S3_REGION: z.string().optional(),\n S3_ACCESS_KEY_ID: z.string().optional(),\n S3_SECRET_ACCESS_KEY: z.string().optional(),\n S3_ENDPOINT: z.string().url().optional(),\n S3_FORCE_PATH_STYLE: optionalBoolString,\n // The GCS counterparts of the S3 set above. Without them `STORAGE_TYPE=gcs`\n // validated but there was no way to say *which* bucket, so an app whose\n // config only branched on \"s3\" fell through to local disk — i.e. straight\n // into the ephemeral-storage trap. Credentials stay optional: on GKE\n // Workload Identity supplies them through ADC and a key file is the\n // exception, not the rule.\n GCS_BUCKET: z.string().optional(),\n GCS_PROJECT_ID: z.string().optional(),\n GCS_KEY_FILENAME: z.string().optional()\n});\n\n/** Inferred type of the validated environment. */\nexport type RebaseEnv = z.infer<typeof rebaseEnvSchema>;\n\n/**\n * Load and validate the Rebase environment configuration from `process.env`.\n *\n * Call this **after** your `.env` file has been loaded (via `dotenv`, `--env-file`,\n * container injection, etc.). This function does not load `.env` files itself —\n * that is a deployment concern, not a framework concern.\n *\n * Behavior:\n * - Auto-generates ephemeral `JWT_SECRET` and `REBASE_SERVICE_KEY` in\n * non-production mode so developers can start without manual setup.\n * - Blocks auto-generated secrets in production.\n * - Returns a fully typed, validated env object.\n *\n * Use `extend` to add your own typed env variables on top of the base Rebase schema:\n *\n * @example\n * ```ts\n * import dotenv from \"dotenv\";\n * import { z } from \"zod\";\n * import { loadEnv } from \"@rebasepro/server\";\n *\n * dotenv.config({ path: \"../../.env\" });\n *\n * // Basic — just Rebase env vars:\n * export const env = loadEnv();\n *\n * // Extended — add your own typed vars:\n * export const env = loadEnv({\n * extend: z.object({\n * SMTP_HOST: z.string().optional(),\n * SMTP_PORT: z.string().default(\"587\").transform(Number),\n * STRIPE_SECRET_KEY: z.string(),\n * })\n * });\n * // env.SMTP_HOST → string | undefined (fully typed)\n * // env.STRIPE_SECRET_KEY → string (validated, required)\n * ```\n */\nexport function loadEnv(): RebaseEnv;\nexport function loadEnv<E extends z.ZodObject<z.ZodRawShape>>(options: { extend: E }): RebaseEnv & z.infer<E>;\nexport function loadEnv(options?: { extend?: z.ZodObject<z.ZodRawShape> }): Record<string, unknown> {\n // Auto-generate dev secrets before validation so the Zod schema sees valid values.\n const isProduction = process.env.NODE_ENV === \"production\";\n const autoGeneratedSecrets: string[] = [];\n\n if (!isProduction) {\n if (!process.env.JWT_SECRET) {\n process.env.JWT_SECRET = generateSecret();\n autoGeneratedSecrets.push(\"JWT_SECRET\");\n }\n if (!process.env.REBASE_SERVICE_KEY) {\n process.env.REBASE_SERVICE_KEY = generateSecret();\n autoGeneratedSecrets.push(\"REBASE_SERVICE_KEY\");\n }\n }\n\n // Merge base schema with user extensions (if provided).\n const combinedSchema = options?.extend\n ? rebaseEnvSchema.merge(options.extend)\n : rebaseEnvSchema;\n\n // Validate with production-specific refinements.\n const schema = combinedSchema.superRefine((data, ctx) => {\n const d = data as RebaseEnv & Record<string, unknown>;\n if (d.NODE_ENV === \"production\" && !d.CORS_ORIGINS && !d.FRONTEND_URL) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"CORS_ORIGINS or FRONTEND_URL must be set in production to secure the API.\",\n path: [\"CORS_ORIGINS\"]\n });\n }\n if (d.NODE_ENV === \"production\" && autoGeneratedSecrets.length > 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${autoGeneratedSecrets.join(\", \")} must be explicitly set in production. ` +\n \"Do not rely on auto-generated secrets outside development.\",\n path: [autoGeneratedSecrets[0]]\n });\n }\n if (d.NODE_ENV === \"production\" && !d.ALLOW_LOCALHOST_IN_PRODUCTION) {\n for (const [key, value] of Object.entries(data)) {\n if (key === \"CORS_ORIGINS\") continue;\n if (typeof value === \"string\" && isLocalhostOrLoopback(value)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n // The value is deliberately not echoed: these variables\n // routinely carry credentials (DATABASE_URL, SMTP_PASS,\n // OAuth secrets), and a failed production boot is logged\n // wherever the container's stdout goes.\n message: `Environment variable ${key} points at a local/loopback host. Deployed instances must not connect to localhost.`,\n path: [key]\n });\n }\n }\n }\n });\n\n const env = schema.parse(process.env);\n\n // Warn after successful parse so the server still starts in dev.\n if (autoGeneratedSecrets.length > 0) {\n logger.warn(\n `⚠️ Auto-generated secrets for: ${autoGeneratedSecrets.join(\", \")}. ` +\n \"These are ephemeral — existing tokens will be invalidated on restart. \" +\n \"Set them explicitly in .env for persistent sessions.\"\n );\n }\n\n return env as Record<string, unknown>;\n}\n","import { createHmac, randomUUID } from \"crypto\";\n\nexport interface WebhookConfig {\n id: string;\n url: string;\n secret?: string;\n headers?: Record<string, string>;\n events: string[];\n table: string;\n enabled: boolean;\n}\n\nexport interface WebhookDeliveryResult {\n webhookId: string;\n event: string;\n payload: Record<string, unknown>;\n statusCode: number;\n responseBody: string;\n success: boolean;\n attemptNumber: number;\n}\n\nexport class WebhookDispatcher {\n private webhooks: WebhookConfig[] = [];\n private maxRetries = 3;\n private retryDelays = [1000, 5000, 15000]; // Exponential backoff\n\n /** Register webhooks to watch */\n setWebhooks(webhooks: WebhookConfig[]): void {\n this.webhooks = webhooks.filter(w => w.enabled);\n }\n\n /** Called when a entity changes — checks if any webhook matches */\n async onEntityChange(\n table: string,\n event: \"INSERT\" | \"UPDATE\" | \"DELETE\",\n id: string,\n entity: Record<string, unknown> | null,\n previousEntity?: Record<string, unknown> | null\n ): Promise<WebhookDeliveryResult[]> {\n const matchingWebhooks = this.webhooks.filter(\n w => w.table === table && w.events.includes(event)\n );\n\n if (matchingWebhooks.length === 0) return [];\n\n const results: WebhookDeliveryResult[] = [];\n\n for (const webhook of matchingWebhooks) {\n const payload: Record<string, unknown> = {\n type: event,\n table,\n record: entity,\n old_record: event === \"UPDATE\" ? previousEntity : undefined,\n schema: \"public\",\n timestamp: new Date().toISOString()\n };\n\n const result = await this.deliverWithRetry(webhook, event, payload);\n results.push(result);\n }\n\n return results;\n }\n\n private async deliverWithRetry(\n webhook: WebhookConfig,\n event: string,\n payload: Record<string, unknown>\n ): Promise<WebhookDeliveryResult> {\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n const result = await this.deliver(webhook, event, payload, attempt);\n if (result.success) return result;\n\n if (attempt < this.maxRetries) {\n await new Promise(r => setTimeout(r, this.retryDelays[attempt - 1]));\n } else {\n return result; // Final failure\n }\n }\n\n // Should never reach here, but satisfies TypeScript\n return {\n webhookId: webhook.id,\n event,\n payload,\n statusCode: 0,\n responseBody: \"Max retries exceeded\",\n success: false,\n attemptNumber: this.maxRetries\n };\n }\n\n private async deliver(\n webhook: WebhookConfig,\n event: string,\n payload: Record<string, unknown>,\n attemptNumber: number\n ): Promise<WebhookDeliveryResult> {\n const body = JSON.stringify(payload);\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-Webhook-Id\": webhook.id,\n \"X-Webhook-Event\": event,\n \"X-Webhook-Delivery\": randomUUID(),\n \"X-Webhook-Attempt\": String(attemptNumber),\n ...(webhook.headers || {})\n };\n\n // HMAC signature\n if (webhook.secret) {\n const signature = createHmac(\"sha256\", webhook.secret).update(body).digest(\"hex\");\n headers[\"X-Webhook-Signature\"] = `sha256=${signature}`;\n }\n\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 10000); // 10s timeout\n\n const response = await fetch(webhook.url, {\n method: \"POST\",\n headers,\n body,\n signal: controller.signal\n });\n\n clearTimeout(timeout);\n\n const responseBody = await response.text().catch(() => \"\");\n const success = response.status >= 200 && response.status < 300;\n\n return {\n webhookId: webhook.id,\n event,\n payload,\n statusCode: response.status,\n responseBody: responseBody.slice(0, 1000), // Truncate\n success,\n attemptNumber\n };\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n webhookId: webhook.id,\n event,\n payload,\n statusCode: 0,\n responseBody: message.slice(0, 1000),\n success: false,\n attemptNumber\n };\n }\n }\n}\n","/**\n * Dev-mode port resolution utilities.\n *\n * Provides a `listen` wrapper that automatically retries the next port when\n * the requested one is already in use, and writes the resolved port to a\n * well-known temp file so the CLI / frontend can discover it.\n *\n * Port affinity: when a port file already exists (e.g. after a tsx watch\n * restart), the saved port is tried FIRST so the backend stays on the same\n * port the frontend was configured with.\n *\n * This module is dev-only and should never run in production.\n */\nimport type { Server } from \"http\";\nimport path from \"path\";\nimport fs from \"fs\";\n\nconst MAX_PORT_ATTEMPTS = 20;\n\n/** Filename written next to the project `.env` so the CLI can read it. */\nexport const DEV_PORT_FILENAME = \".rebase-dev-port\";\n\n/**\n * Try to `listen` on `startPort`. If the port is busy (`EADDRINUSE`), increment\n * and retry up to `maxAttempts` times.\n *\n * When a port file written by a previous run exists *and that run asked for the\n * same `startPort`*, the port it landed on is tried first, so tsx watch restarts\n * keep the address the frontend was configured with. A different `startPort` means\n * the configuration changed and the file is ignored — an explicitly requested port\n * is never overridden by a stale one.\n *\n * Resolves with the port that was actually bound.\n *\n * @internal Not part of the stable public API. Exported only because the\n * official app template (`packages/cli/templates/template/backend/src/index.ts`\n * and `app/backend/src/index.ts`) calls it directly in dev mode. Its dev-only\n * port-affinity behavior is an implementation detail and may change without\n * a major version bump.\n */\nexport function listenWithPortRetry(\n server: Server,\n startPort: number,\n options?: {\n host?: string;\n maxAttempts?: number;\n /** Absolute path to write the resolved port file into. Defaults to `process.cwd()`. */\n portFileDir?: string;\n /** Service key to include in the state file for MCP server auto-discovery. */\n serviceKey?: string;\n }\n): Promise<number> {\n const host = options?.host ?? \"0.0.0.0\";\n const maxAttempts = options?.maxAttempts ?? MAX_PORT_ATTEMPTS;\n const portFileDir = options?.portFileDir;\n\n const isProd = process.env.NODE_ENV === \"production\";\n if (isProd) {\n return new Promise<number>((resolve, reject) => {\n const onError = (err: Error) => {\n reject(err);\n };\n server.once(\"error\", onError);\n server.listen(startPort, host, () => {\n server.removeListener(\"error\", onError);\n resolve(startPort);\n });\n });\n }\n\n // Read affinity port from a previous run's port file.\n // This ensures tsx watch restarts land on the same port the frontend was\n // configured with, even if the CLI-computed port was different.\n //\n // It applies only when the port being *asked for* has not changed since that\n // file was written, which is why the file records both. Affinity used to win\n // outright, so a stale file silently overrode an explicit port: set `PORT=4000`\n // in `.env` and the server would keep binding whatever the last run happened to\n // land on, reporting the old number. `resolvePort` in the CLI has always ranked\n // these correctly — explicit `--port`, then `PORT`, then affinity — and this is\n // the server agreeing with it.\n //\n // The e2e suite is what surfaced it: it assigns each backend a fresh free port,\n // and the second boot in a project ignored it and re-bound the first one.\n let affinityPort: number | null = null;\n if (portFileDir) {\n try {\n const portFile = path.join(portFileDir, DEV_PORT_FILENAME);\n if (fs.existsSync(portFile)) {\n // \"<bound> <requested>\" — `parseInt` stops at the space, so older\n // readers that expect a bare number still read the bound port.\n const [savedRaw, requestedRaw] = fs.readFileSync(portFile, \"utf-8\").trim().split(/\\s+/);\n const saved = parseInt(savedRaw, 10);\n const requestedThen = requestedRaw === undefined ? NaN : parseInt(requestedRaw, 10);\n const sameRequest = Number.isNaN(requestedThen) || requestedThen === startPort;\n if (saved > 0 && saved < 65536 && saved !== startPort && sameRequest) {\n affinityPort = saved;\n }\n }\n } catch { /* ignore */ }\n }\n\n return new Promise<number>((resolve, reject) => {\n let attempt = 0;\n // Build the ordered list of ports to try:\n // 1. The affinity port (if different from startPort)\n // 2. startPort, startPort+1, startPort+2, ...\n const portsToTry: number[] = [];\n if (affinityPort) portsToTry.push(affinityPort);\n for (let i = 0; i < maxAttempts; i++) {\n const p = startPort + i;\n if (p !== affinityPort) portsToTry.push(p);\n }\n\n function tryNext(index: number) {\n if (index >= portsToTry.length) {\n reject(new Error(\n \"All attempted ports are in use. \" +\n \"Stop other Rebase instances or specify a different port with --port.\"\n ));\n return;\n }\n\n const port = portsToTry[index];\n attempt++;\n\n // Both listeners are removed on either outcome.\n //\n // This used to pass the success handler as `server.listen(port, host, cb)`,\n // and that form registers `cb` as a one-shot `listening` listener which a\n // *failed* attempt never removes. So after an EADDRINUSE, the next attempt's\n // success ran both handlers, and the earliest one won the promise: the\n // function resolved with — and wrote into the port file — the port it had\n // just failed to bind.\n //\n // What that looked like: with something already on 3001, the server bound\n // 3002 and announced \"API running at http://localhost:3001\". Every caller\n // that trusted the banner reached the *other* process, which answered\n // normally from its own database. No error was logged anywhere. It cost the\n // templates e2e six failures that blamed registration, and it would hand a\n // developer running two projects a URL that silently serves the wrong app.\n const onListening = () => {\n cleanup();\n\n // Write the port file so the CLI can pick it up\n if (portFileDir) {\n try {\n const portFile = path.join(portFileDir, DEV_PORT_FILENAME);\n // Bound port first so `parseInt` still yields it, then the\n // port that was requested — that is what makes the affinity\n // above conditional rather than absolute.\n fs.writeFileSync(portFile, `${port} ${startPort}`, \"utf-8\");\n } catch {\n // Non-fatal — the CLI will fall back to parsing stdout\n }\n\n // Write .rebase/state.json so external scripts can discover\n // the running server port, URL, etc.\n writeStateFile(portFileDir, port, options?.serviceKey);\n }\n\n resolve(port);\n };\n\n const onError = (err: NodeJS.ErrnoException) => {\n cleanup();\n if (err.code === \"EADDRINUSE\") {\n tryNext(index + 1);\n } else {\n reject(err);\n }\n };\n\n function cleanup() {\n server.removeListener(\"listening\", onListening);\n server.removeListener(\"error\", onError);\n }\n\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen(port, host);\n }\n\n tryNext(0);\n });\n}\n\n/**\n * Clean up the dev port file and state file (call on graceful shutdown).\n *\n * @internal Not part of the stable public API. See {@link listenWithPortRetry}.\n */\nexport function cleanupDevPortFile(dir: string): void {\n try {\n const portFile = path.join(dir, DEV_PORT_FILENAME);\n if (fs.existsSync(portFile)) {\n fs.unlinkSync(portFile);\n }\n } catch {\n // ignore\n }\n try {\n const stateFile = path.join(dir, \".rebase\", \"state.json\");\n if (fs.existsSync(stateFile)) {\n fs.unlinkSync(stateFile);\n }\n } catch {\n // ignore\n }\n}\n\n/**\n * Write `.rebase/state.json` with runtime info for external scripts.\n *\n * Scripts can read this file to discover:\n * - `port` — the actual port the backend is listening on\n * - `baseUrl` — full URL including protocol and port\n * - `pid` — the backend process ID\n * - `startedAt` — ISO timestamp of when the server started\n * - `serviceKey` — (dev only) the REBASE_SERVICE_KEY for MCP auto-discovery\n *\n * @example Reading from a script:\n * ```ts\n * const state = JSON.parse(fs.readFileSync('.rebase/state.json', 'utf-8'));\n * const apiUrl = state.baseUrl; // \"http://localhost:3519\"\n * ```\n */\nfunction writeStateFile(projectRoot: string, port: number, serviceKey?: string): void {\n try {\n const rebaseDir = path.join(projectRoot, \".rebase\");\n if (!fs.existsSync(rebaseDir)) {\n fs.mkdirSync(rebaseDir, { recursive: true });\n }\n const stateFile = path.join(rebaseDir, \"state.json\");\n const state: Record<string, unknown> = {\n port,\n baseUrl: `http://localhost:${port}`,\n pid: process.pid,\n startedAt: new Date().toISOString()\n };\n if (serviceKey) {\n state.serviceKey = serviceKey;\n }\n // Owner-only: the file can carry the dev service key. `mode` only\n // applies on create, so chmod covers a pre-existing file.\n fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), { encoding: \"utf-8\", mode: 0o600 });\n fs.chmodSync(stateFile, 0o600);\n } catch {\n // Non-fatal\n }\n}\n","import { Hono } from \"hono\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport * as path from \"path\";\nimport * as fs from \"fs\";\nimport fsp from \"node:fs/promises\";\nimport { responseCompression } from \"./utils/compression.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * Configuration for serving a Single Page Application\n */\nexport interface ServeSPAConfig {\n /**\n * Absolute path to the frontend build directory\n * @example path.join(__dirname, \"../../frontend/dist\")\n */\n frontendPath: string;\n\n /**\n * Public base path this app is served under (default: \"/\").\n *\n * No trailing slash unless it *is* \"/\". Several apps run in one process,\n * each under its own prefix — a site at \"/\" and an admin at \"/admin\" — so\n * both the asset middleware and the SPA fallback are scoped here rather\n * than claiming \"/*\" globally.\n *\n * The assets must have been *built* for this path too; see\n * `assertBuiltForPath` in the CLI.\n */\n basePath?: string;\n\n /**\n * Base path for API routes (default: \"/api\")\n * Requests to this path will be passed through to API handlers\n */\n apiBasePath?: string;\n\n /**\n * Additional paths to exclude from SPA handling\n * These paths will be passed through to other handlers\n *\n * When several apps share a process, the \"/\"-rooted one must list its\n * siblings here. Mount order alone is not enough: a request to \"/admin/x\"\n * that misses the admin's files would otherwise fall through to the root\n * app's catch-all and be answered with the *site's* index.html under the\n * admin's URL — which reads as an admin bug for a long time.\n *\n * Each entry excludes a path *segment*, not a string prefix: \"/admin\"\n * excludes \"/admin\" and \"/admin/x\" but not \"/administrators\", which is an\n * ordinary route of the app rooted at \"/\".\n *\n * @example [\"/health\", \"/ws\", \"/metrics\", \"/admin\"]\n */\n excludePaths?: string[];\n\n /**\n * Index file to serve for SPA routes (default: \"index.html\")\n */\n indexFile?: string;\n\n /**\n * Serve index.html for unmatched paths under `basePath` (default: true).\n *\n * `false` registers the asset middleware only, for a static *site* whose\n * generator emitted a real file per route.\n */\n spa?: boolean;\n}\n\n/**\n * Is `requestPath` the excluded path `prefix`, or something beneath it?\n *\n * Segment-aware on purpose. A plain `startsWith` reads \"/api\" as excluding\n * \"/apidocs\", and \"/admin\" as excluding \"/administrators\" — both ordinary\n * client-side routes of the app rooted at \"/\", both then answered with a 404\n * because the SPA fallback declined them and nothing else claims the path.\n * `apiBasePath` is always in the exclusion list, so this reached single-app\n * setups too, not just the multi-app ones the list was added for.\n */\nfunction isUnderPath(requestPath: string, prefix: string): boolean {\n // \"/\" would exclude everything below it, which is every request.\n const trimmed = prefix.replace(/\\/+$/, \"\");\n if (trimmed === \"\") return true;\n return requestPath === trimmed || requestPath.startsWith(`${trimmed}/`);\n}\n\n/**\n * Serve a Single Page Application from an Hono app.\n *\n * @internal Not part of the stable public API. Exported only because the\n * official app template (`packages/cli/templates/template/backend/src/index.ts`\n * and `app/backend/src/index.ts`) calls it to serve the built frontend in\n * production. Its request-handling behavior is an implementation detail and\n * may change without a major version bump.\n */\nexport function serveSPA<E extends import(\"hono\").Env>(app: Hono<E>, config: ServeSPAConfig): void {\n const {\n frontendPath,\n apiBasePath = \"/api\",\n excludePaths = [],\n indexFile = \"index.html\",\n spa = true\n } = config;\n\n // \"/admin/\" and \"/admin\" must not be two different mounts.\n const rawBase = config.basePath ?? \"/\";\n const basePath = rawBase !== \"/\" ? rawBase.replace(/\\/+$/, \"\") : \"/\";\n const isRoot = basePath === \"/\";\n\n // Validate frontend path exists.\n //\n // NOTE: this warns and disables itself rather than throwing, so a wrong path\n // leaves the API answering perfectly while the site 404s. Verify a mount by\n // fetching it, never by reading the logs.\n if (!fs.existsSync(frontendPath)) {\n logger.warn(`⚠️ Frontend build path does not exist: ${frontendPath}`);\n logger.warn(\" SPA serving is disabled. Build your frontend first.\");\n return;\n }\n\n // Scoped to this app's prefix. Registering at \"/*\" would mean one process\n // could serve exactly one SPA — and, worse, the first one registered would\n // silently answer for every app mounted after it.\n const scope = isRoot ? \"/*\" : `${basePath}/*`;\n\n // Compress the bundle. The API is compressed by `configureMiddlewares`, but\n // that is scoped to the API base path — static assets are served here, and\n // the JS bundle is the single largest thing most apps ship.\n //\n // Registered before serveStatic so it wraps it. `precompressed` takes\n // priority where the build emitted .br/.gz siblings: those cost no CPU and\n // give brotli, and set Content-Encoding themselves, which makes the\n // compression middleware skip them.\n app.use(scope, responseCompression());\n app.use(scope, serveStatic({\n root: path.relative(process.cwd(), frontendPath),\n precompressed: true,\n // The prefix is a serving concern, not a directory: `/admin/assets/x.js`\n // lives at `<adminBuild>/assets/x.js`.\n ...(isRoot ? {} : { rewriteRequestPath: (p: string) => p.slice(basePath.length) || \"/\" })\n }));\n\n if (!spa) {\n logger.info(`✅ Static serving enabled at ${basePath} from: ${frontendPath}`);\n return;\n }\n\n // Build list of paths to exclude from SPA handling\n const allExcludePaths = [apiBasePath, ...excludePaths];\n\n // Cache the index.html content to avoid re-reading from disk on every navigation request.\n let cachedHtml: string | null = null;\n\n // SPA fallback - serve index.html for all non-excluded routes under basePath\n app.get(scope, async (c, next) => {\n // Skip excluded paths (API, health checks, sibling apps).\n if (allExcludePaths.some(p => isUnderPath(c.req.path, p))) {\n return next();\n }\n\n const indexPath = path.join(frontendPath, indexFile);\n\n if (!cachedHtml) {\n try {\n cachedHtml = await fsp.readFile(indexPath, \"utf-8\");\n } catch {\n logger.warn(`⚠️ Index file not found: ${indexPath}`);\n return next();\n }\n }\n\n return c.html(cachedHtml);\n });\n\n logger.info(`✅ SPA serving enabled at ${basePath} from: ${frontendPath}`);\n}\n\n","import fs from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport {\n BUNDLE_FORMAT_VERSION,\n RUNTIME_CONTRACT_VERSION,\n type CollectionConfig,\n type CollectionCallbacks,\n type DataSourceDefinition,\n type RebaseBundleManifest,\n type StorageSourceDefinition\n} from \"@rebasepro/types\";\nimport type { StorageAuthorize } from \"../storage/types\";\nimport { logger } from \"../utils/logger\";\n\n/** Thrown when a bundle cannot be read, or claims a contract this runtime cannot honour. */\nexport class BundleError extends Error {\n constructor(message: string, readonly hint?: string) {\n super(message);\n this.name = \"BundleError\";\n }\n}\n\n/** A bundle that has been located and whose manifest has been validated. */\nexport interface LoadedBundle {\n dir: string;\n manifest: RebaseBundleManifest;\n /** Absolute path to the compiled collections directory, when present. */\n collectionsDir?: string;\n functionsDir?: string;\n cronsDir?: string;\n /**\n * Built static apps to serve from this process, in mount order.\n *\n * A list, not a single directory: one process serves a site at `/` and an\n * admin at `/admin`. Entries whose directory is missing are dropped with a\n * warning, so a partially-built bundle still boots its API.\n */\n staticApps: LoadedStaticApp[];\n}\n\n/** One built static app inside a loaded bundle, with an absolute directory. */\nexport interface LoadedStaticApp {\n /** Public base path, e.g. `/` or `/admin`. */\n path: string;\n /** Absolute path to the built assets. */\n dir: string;\n /** Serve `index.html` for unmatched paths under `path`. */\n spa: boolean;\n}\n\nconst MANIFEST_FILENAME = \"manifest.json\";\n\n/**\n * Bring a format-1 manifest up to the shape the rest of this runtime expects.\n *\n * Old bundles booting on a new runtime is the case the format version exists to\n * protect, so this is not a courtesy — it is the contract. A project built\n * before the rename ships `mode` and a single `entry.static` directory string,\n * and without this it would boot with no `kind` (so every gate keyed on\n * `kind === \"backend\"` would skip) and an `entry.static` the loader would try to\n * iterate as a list.\n *\n * In place, and only ever filling in what is absent, so a format-2 manifest\n * passes through untouched.\n */\nfunction upgradeLegacyManifest(manifest: RebaseBundleManifest): void {\n const legacy = manifest as RebaseBundleManifest & {\n mode?: string;\n entry?: { static?: unknown; admin?: unknown };\n };\n\n if (!legacy.kind) {\n // `cms` and `baas` were both backends — the distinction between them is\n // derived from `entry.config` now.\n legacy.kind = legacy.mode === \"static\" ? \"static\" : \"backend\";\n }\n\n const entry = legacy.entry;\n if (!entry) return;\n\n if (typeof entry.static === \"string\") {\n entry.static = [{ path: \"/\",\ndir: entry.static,\nspa: true }];\n } else if (!entry.static && typeof entry.admin === \"string\") {\n // A format-1 bundled admin panel was served at the root, exactly as a\n // static app was — `staticDir ?? adminDir`, one or the other.\n entry.static = [{ path: \"/\",\ndir: entry.admin,\nspa: true }];\n }\n delete entry.admin;\n}\n\n/**\n * Read and validate a bundle's manifest.\n *\n * The checks here are the runtime half of the compatibility contract, and they\n * all fail loudly at boot rather than at the first request. A container that\n * refuses to start is a deploy that rolls back; a container that starts and then\n * misbehaves is an incident.\n */\nexport function readBundleManifest(bundleDir: string): RebaseBundleManifest {\n const manifestPath = path.join(bundleDir, MANIFEST_FILENAME);\n\n if (!fs.existsSync(manifestPath)) {\n throw new BundleError(\n `No ${MANIFEST_FILENAME} found in ${bundleDir}`,\n \"Build the project with `rebase build` and point the runtime at the output directory.\"\n );\n }\n\n let manifest: RebaseBundleManifest;\n try {\n manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as RebaseBundleManifest;\n } catch (err) {\n throw new BundleError(\n `${manifestPath} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n if (typeof manifest.bundleFormat !== \"number\") {\n throw new BundleError(`${manifestPath} is missing \"bundleFormat\".`);\n }\n\n // Newer format on an older runtime: the layout may have fields this code\n // does not know how to read, so refuse rather than half-load it. The reverse\n // — an older bundle on a newer runtime — is the case that must keep working,\n // and does.\n if (manifest.bundleFormat > BUNDLE_FORMAT_VERSION) {\n throw new BundleError(\n `This bundle uses format ${manifest.bundleFormat}, but this runtime understands up to ${BUNDLE_FORMAT_VERSION}.`,\n \"Upgrade the runtime image, or rebuild the bundle with a matching CLI.\"\n );\n }\n\n upgradeLegacyManifest(manifest);\n\n const contract = manifest.runtime?.contract;\n if (typeof contract === \"number\" && contract !== RUNTIME_CONTRACT_VERSION) {\n throw new BundleError(\n `This bundle targets runtime contract v${contract}, but this runtime implements v${RUNTIME_CONTRACT_VERSION}.`,\n contract > RUNTIME_CONTRACT_VERSION\n ? \"Upgrade the runtime image to a version that implements the newer contract.\"\n : \"Rebuild the bundle against the current runtime (`rebase build`), or run a runtime image from the previous major.\"\n );\n }\n\n return manifest;\n}\n\n/**\n * Locate a bundle and resolve every directory the runtime needs from it.\n *\n * Entry paths in the manifest are bundle-relative and are resolved here, once,\n * so nothing downstream has to know the layout. A declared directory that does\n * not exist is dropped with a warning rather than failing the boot: an empty\n * `functions/` is a perfectly ordinary project, and refusing to start over one\n * would be the runtime inventing a requirement the developer never stated.\n */\n/**\n * Resolve a bundle-relative entry, refusing anything that escapes the bundle.\n *\n * Applied to the entries that are `import()`ed — the schema, the config index,\n * the users collection — and not only to the ones that are merely scanned. Those\n * three *execute code*, so they are precisely the ones a malformed or hostile\n * manifest would target, and leaving them unchecked while guarding the read-only\n * paths would be defending the wrong door.\n */\nexport function resolveBundlePath(\n bundleDir: string,\n entry: string,\n label: string\n): string {\n const resolved = path.resolve(bundleDir, entry);\n const relative = path.relative(bundleDir, resolved);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new BundleError(\n `Bundle entry \"${label}\" points outside the bundle: ${entry}`\n );\n }\n return resolved;\n}\n\nexport function loadBundle(bundleDir: string): LoadedBundle {\n const dir = path.resolve(bundleDir);\n\n if (!fs.existsSync(dir)) {\n throw new BundleError(\n `Bundle directory not found: ${dir}`,\n \"Run `rebase build` first, or pass the correct path (e.g. `rebase-server ./dist-bundle`).\"\n );\n }\n\n const manifest = readBundleManifest(dir);\n\n const resolveEntry = (entry: string | undefined, label: string): string | undefined => {\n if (!entry) return undefined;\n // A manifest is a build artifact, but it is also a file a deploy\n // pipeline moves around — keep every entry inside the bundle so a\n // malformed one cannot point the runtime at arbitrary paths.\n const resolved = resolveBundlePath(dir, entry, label);\n if (!fs.existsSync(resolved)) {\n logger.warn(`Bundle declares ${label} at \"${entry}\", but that path does not exist — skipping.`);\n return undefined;\n }\n return resolved;\n };\n\n const entry = manifest.entry ?? {};\n\n // Collections live under the config package unless stated otherwise.\n const collectionsDir = entry.collections\n ? resolveEntry(entry.collections, \"collections\")\n : entry.config\n ? resolveEntry(path.join(entry.config, \"collections\"), \"collections\")\n : undefined;\n\n return {\n dir,\n manifest,\n collectionsDir,\n functionsDir: resolveEntry(entry.functions, \"functions\"),\n cronsDir: resolveEntry(entry.crons, \"crons\"),\n staticApps: (entry.static ?? [])\n .map(item => {\n const resolved = resolveEntry(item.dir, `static app \"${item.path}\"`);\n return resolved ? { path: item.path,\ndir: resolved,\nspa: item.spa !== false } : undefined;\n })\n .filter((item): item is LoadedStaticApp => item !== undefined)\n // Longest path first, \"/\" last: the root app's catch-all would\n // otherwise claim every sibling's URLs.\n .sort((a, b) => b.path.length - a.path.length)\n };\n}\n\n/**\n * The Drizzle schema a bundle ships: tables, enums and relations, as generated\n * from the project's collections.\n */\nexport interface BundleSchemaExports {\n tables?: Record<string, unknown>;\n enums?: Record<string, unknown>;\n relations?: Record<string, unknown>;\n}\n\n/**\n * Import the bundle's Drizzle schema module.\n *\n * Returns `undefined` when the bundle declares none — `baas` mode introspects the\n * live database instead of shipping a schema.\n */\nexport async function loadBundleSchema(bundle: LoadedBundle): Promise<BundleSchemaExports | undefined> {\n const entry = bundle.manifest.entry?.schema;\n if (!entry) return undefined;\n\n const schemaPath = resolveBundlePath(bundle.dir, entry, \"schema\");\n if (!fs.existsSync(schemaPath)) {\n logger.warn(`Bundle declares a schema at \"${entry}\", but that file does not exist — continuing without it.`);\n return undefined;\n }\n\n const mod = await import(pathToFileURL(schemaPath).href) as BundleSchemaExports;\n return {\n tables: mod.tables,\n enums: mod.enums,\n relations: mod.relations\n };\n}\n\n/**\n * Build a bundle view over a project's **source** directories.\n *\n * `rebase dev` runs TypeScript directly through tsx, so there is no compiled\n * bundle to load — but everything downstream of loading (drivers, storage, auth,\n * routes) should be identical, or development stops predicting production. This\n * produces the same {@link LoadedBundle} shape from source paths, so the one boot\n * path serves both.\n *\n * The schema version is left empty deliberately: nothing has been built, so\n * there is no build-time answer, and the runtime computes one from the live\n * collections instead.\n */\nexport function createSourceBundle(options: {\n projectRoot: string;\n config?: string;\n collections?: string;\n functions?: string;\n crons?: string;\n schema?: string;\n app?: string;\n}): LoadedBundle {\n const dir = path.resolve(options.projectRoot);\n const resolve = (entry: string | undefined): string | undefined => {\n if (!entry) return undefined;\n const full = path.resolve(dir, entry);\n return fs.existsSync(full) ? full : undefined;\n };\n\n const configDir = options.config ?? \"config\";\n const collectionsDir = options.collections\n ?? (options.config !== undefined || fs.existsSync(path.join(dir, configDir))\n ? path.join(configDir, \"collections\")\n : undefined);\n\n const manifest: RebaseBundleManifest = {\n bundleFormat: BUNDLE_FORMAT_VERSION,\n runtime: {\n range: `^${RUNTIME_CONTRACT_VERSION}`,\n builtAgainst: \"source\",\n contract: RUNTIME_CONTRACT_VERSION\n },\n schemaVersion: \"\",\n app: options.app ?? \"backend\",\n kind: \"backend\",\n entry: {\n config: options.config ?? configDir,\n collections: collectionsDir,\n functions: options.functions,\n crons: options.crons,\n schema: options.schema\n },\n hooks: { native: false },\n deps: { declared: {} },\n build: { cli: \"source\",\nnode: process.versions.node.split(\".\")[0],\ncreatedAt: new Date().toISOString() }\n };\n\n return {\n dir,\n manifest,\n collectionsDir: resolve(collectionsDir),\n functionsDir: resolve(options.functions),\n cronsDir: resolve(options.crons),\n staticApps: []\n };\n}\n\n/**\n * Declarations a bundle's config package exports alongside its collections.\n *\n * These describe *topology* — which databases and which buckets exist — so they\n * belong to the project rather than to the environment. The environment then\n * supplies credentials for each declared key. Splitting it this way is what lets\n * a deploy be validated before it runs: the set of things needing configuration\n * is known from the bundle, without reading anyone's secrets.\n */\nexport interface BundleConfigExports {\n dataSources?: DataSourceDefinition[];\n storageSources?: StorageSourceDefinition[];\n /**\n * Per-object storage access control.\n *\n * A function, so it can only come from the project's own code — there is no\n * environment variable that could express \"this user may read this key\".\n * Without a way to supply it, a production deployment with a bucket would be\n * forced to choose between `STORAGE_PUBLIC_READ` (world-readable) and\n * `STORAGE_ALLOW_ANY_AUTHENTICATED` (every signed-in user can read, overwrite\n * and delete every other user's files) — the runtime would be making an\n * insecure choice on the developer's behalf.\n */\n storageAuthorize?: StorageAuthorize;\n /** Lifecycle callbacks applied to every collection. */\n callbacks?: CollectionCallbacks;\n}\n\n/**\n * Read the config package's `index` for declarations.\n *\n * Absent, empty or unreadable all mean the same thing: a single default database\n * and a single default bucket. That is the overwhelmingly common project, and it\n * must not be required to say so. A malformed export is reported and ignored\n * rather than fatal — a typo in an optional declaration should not take down a\n * server whose collections are fine.\n */\nexport async function loadBundleConfigExports(bundle: LoadedBundle): Promise<BundleConfigExports> {\n const configEntry = bundle.manifest.entry?.config;\n if (!configEntry) return {};\n\n const configDir = resolveBundlePath(bundle.dir, configEntry, \"config\");\n // `.ts` for a source boot (`rebase dev` runs under tsx, which imports\n // TypeScript directly); `.js` for a built bundle.\n const indexPath = [\".js\", \".ts\"]\n .map(ext => path.join(configDir, `index${ext}`))\n .find(candidate => fs.existsSync(candidate));\n if (!indexPath) return {};\n\n let mod: Record<string, unknown>;\n try {\n mod = await import(pathToFileURL(indexPath).href) as Record<string, unknown>;\n } catch (err) {\n logger.warn(\n `Could not import the config index at ${indexPath}: ` +\n `${err instanceof Error ? err.message : String(err)}. ` +\n \"Continuing with a single default data source and storage source.\"\n );\n return {};\n }\n\n const readArray = <T>(name: string): T[] | undefined => {\n const value = mod[name];\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) {\n logger.warn(`Config exports \"${name}\" but it is not an array — ignoring.`);\n return undefined;\n }\n return value as T[];\n };\n\n const readFunction = <T>(name: string): T | undefined => {\n const value = mod[name];\n if (value === undefined) return undefined;\n if (typeof value !== \"function\") {\n logger.warn(`Config exports \"${name}\" but it is not a function — ignoring.`);\n return undefined;\n }\n return value as T;\n };\n\n const callbacks = mod.callbacks;\n\n return {\n dataSources: readArray<DataSourceDefinition>(\"dataSources\"),\n storageSources: readArray<StorageSourceDefinition>(\"storageSources\"),\n storageAuthorize: readFunction<StorageAuthorize>(\"storageAuthorize\"),\n callbacks: callbacks && typeof callbacks === \"object\"\n ? callbacks as CollectionCallbacks\n : undefined\n };\n}\n\n/**\n * Import the collection that backs authentication.\n *\n * Auth needs to know which table holds users. The bundle names the module; the\n * convention (`collections/users`) covers every project that did not rename it.\n * Returning `undefined` is valid — a `baas`-mode project has no config package,\n * and the auth bootstrapper falls back to its own default users table.\n */\nexport async function loadUsersCollection(bundle: LoadedBundle): Promise<CollectionConfig | undefined> {\n const entry = bundle.manifest.entry;\n const configDir = entry?.config\n ? resolveBundlePath(bundle.dir, entry.config, \"config\")\n : undefined;\n\n const candidates: string[] = [];\n if (entry?.usersCollection) {\n const declared = resolveBundlePath(bundle.dir, entry.usersCollection, \"usersCollection\");\n candidates.push(declared, `${declared}.js`, `${declared}.ts`);\n }\n for (const dir of [configDir && path.join(configDir, \"collections\"), bundle.collectionsDir]) {\n if (!dir) continue;\n candidates.push(path.join(dir, \"users.js\"), path.join(dir, \"users.ts\"));\n }\n\n for (const candidate of candidates) {\n if (!/\\.(js|ts)$/.test(candidate) || !fs.existsSync(candidate)) continue;\n try {\n const mod = await import(pathToFileURL(candidate).href) as { default?: CollectionConfig };\n if (mod.default) return mod.default;\n logger.warn(`Users collection module ${candidate} has no default export — ignoring.`);\n } catch (err) {\n logger.warn(\n `Failed to import users collection from ${candidate}: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n\n return undefined;\n}\n","import { z } from \"zod\";\nimport { loadEnv, type RebaseEnv } from \"../env\";\nimport { BundleError } from \"./bundle\";\n\n/**\n * The environment a bundle-booted runtime understands.\n *\n * This extends the base {@link loadEnv} schema with the variables an application\n * used to declare for itself in its own `env.ts`. They live here now because the\n * runtime, not the application, is what reads them: a project ships a bundle and\n * a set of environment variables, and everything either side needs to agree on\n * has to be part of the contract rather than a convention each project reinvents.\n */\nconst bootEnvExtension = z.object({\n // ── Email ────────────────────────────────────────────────────────────────\n SMTP_HOST: z.string().optional(),\n SMTP_PORT: z.string().default(\"587\").transform(Number),\n SMTP_SECURE: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n SMTP_USER: z.string().optional(),\n SMTP_PASS: z.string().optional(),\n SMTP_FROM: z.string().optional(),\n SMTP_NAME: z.string().optional(),\n APP_NAME: z.string().default(\"Rebase\"),\n\n // ── Runtime behaviour ────────────────────────────────────────────────────\n /**\n * Serve the bundle's static/admin assets from this process.\n *\n * Default on, because a self-hosted single-container deployment is the case\n * that needs it and the assets are simply absent when there is nothing to\n * serve. A platform putting a CDN in front turns it off.\n */\n REBASE_SERVE_STATIC: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n /**\n * What the runtime may do to the database schema at boot.\n *\n * - `none` (default in production) — touch nothing. Schema changes are a\n * deliberate, reviewable step, not a side effect of a restart.\n * - `ensure` — create the auth/system tables if missing, never touch\n * collection tables. The default outside production.\n * - `push` — reconcile collection tables with the bundle's schema. Convenient\n * for a local compose stack; in production it means a container restart can\n * rewrite the schema, so it must be asked for explicitly.\n */\n REBASE_MIGRATE_ON_BOOT: z.enum([\"none\", \"ensure\", \"push\", \"\"]).optional(),\n /** Expose Prometheus metrics at `/metrics`. Off unless asked for. */\n REBASE_METRICS: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n /**\n * Bearer token guarding `/metrics`. When unset the endpoint is open to\n * anyone who can reach the port, which is fine on a private network and not\n * fine on a public one — hence the boot-time warning rather than a silent\n * default.\n */\n REBASE_METRICS_TOKEN: z.string().optional(),\n LOG_LEVEL: z.enum([\"error\", \"warn\", \"info\", \"debug\", \"\"]).optional(),\n\n // ── Storage access control ───────────────────────────────────────────────\n /** Serve stored objects to unauthenticated readers. */\n STORAGE_PUBLIC_READ: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n /**\n * Opt out of the storage access-control boot guard, restoring the behaviour\n * where any authenticated user may read, overwrite, delete or list any key.\n * Only defensible when every signed-in user is trusted with every file.\n */\n STORAGE_ALLOW_ANY_AUTHENTICATED: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n\n // ── Auth ─────────────────────────────────────────────────────────────────\n AUTH_REQUIRE: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n AUTH_ALLOW_USER_LOOKUP: z.enum([\"true\", \"false\", \"\"]).default(\"false\").transform(v => v === \"true\"),\n AUTH_COOKIE_SAME_SITE: z.enum([\"Strict\", \"Lax\", \"None\", \"\"]).optional(),\n AUTH_DEFAULT_ROLE: z.string().optional(),\n GITHUB_CLIENT_ID: z.string().optional(),\n GITHUB_CLIENT_SECRET: z.string().optional(),\n MICROSOFT_CLIENT_ID: z.string().optional(),\n MICROSOFT_CLIENT_SECRET: z.string().optional(),\n\n // ── API surface ──────────────────────────────────────────────────────────\n REBASE_BASE_PATH: z.string().default(\"/api\"),\n /**\n * The OpenAPI surface: `/api/docs` (the spec) and `/api/swagger` (the UI).\n *\n * Deliberately tri-state, and resolved against NODE_ENV by\n * {@link resolveEnableSwagger} rather than defaulted here. Unset means \"on\n * in development, off in production\" — an explicit `true` or `false` always\n * wins in both.\n *\n * It used to default to `\"false\"` outright, which reads as a safe default\n * and was not one: the runtime is how every scaffolded project boots, so\n * the docs disappeared from projects that never asked for that. `rebase\n * init` prints \"docs are at /api/swagger\" on completion, the headless\n * README repeats it, and the console's API Explorer fetches `/api/docs` —\n * all three 404'd against a project running the runtime, and the baas e2e\n * failed on exactly that.\n */\n REBASE_ENABLE_SWAGGER: z.enum([\"true\", \"false\", \"\"]).optional()\n .transform(v => (v === undefined || v === \"\" ? undefined : v === \"true\")),\n /**\n * Maximum request body size, in **bytes**.\n *\n * Validated as a number rather than coerced loosely: `Number(\"10MB\")` is\n * `NaN`, which is not nullish, so it would slip past the downstream default\n * and then fail a `> 0` check — silently removing every body limit from the\n * API. A boot failure naming the variable is the only safe reading of a\n * value nobody can interpret.\n */\n REBASE_MAX_BODY_SIZE: z.coerce\n .number({ message: \"REBASE_MAX_BODY_SIZE must be a number of bytes (e.g. 10485760)\" })\n .int()\n .nonnegative()\n .optional(),\n REBASE_COMPRESSION: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n REBASE_HISTORY: z.enum([\"true\", \"false\", \"\"]).default(\"true\").transform(v => v !== \"false\"),\n /** Comma-separated origins allowed to make credentialed cross-origin calls. */\n CORS_ORIGINS: z.string().optional()\n});\n\nexport type RebaseBootEnv = RebaseEnv & z.infer<typeof bootEnvExtension>;\n\n/**\n * Load and validate the environment for a bundle boot.\n *\n * Does not read `.env` files — that is the deployment's job (a container gets\n * real environment variables; `rebase dev` and `rebase start` load dotenv before\n * calling in).\n */\nexport function loadBootEnv(): RebaseBootEnv {\n try {\n return loadEnv({ extend: bootEnvExtension }) as RebaseBootEnv;\n } catch (err) {\n // A raw ZodError prints a JSON dump and a stack trace through the\n // validator — several screens of noise whose actual content is \"you did\n // not set DATABASE_URL\". Restate it as the list of variables to fix.\n const issues = (err as { issues?: { path?: (string | number)[]; message?: string }[] }).issues;\n if (!Array.isArray(issues)) throw err;\n\n const lines = issues.map(issue => {\n const name = Array.isArray(issue.path) ? issue.path.join(\".\") : \"\";\n const detail = issue.message === \"Invalid input\" ? \"is required\" : issue.message;\n return name ? ` ${name}: ${detail}` : ` ${detail}`;\n });\n\n throw new BundleError(\n `The environment is not valid:\\n${lines.join(\"\\n\")}`,\n \"See https://rebase.pro/docs/deployment/self-hosting/ for the variables a deployment needs.\"\n );\n }\n}\n\n/**\n * Whether an origin is a loopback address.\n *\n * In development the runtime reflects only localhost origins. It cannot reflect\n * an arbitrary `Origin`, because credentials are enabled: any site the developer\n * happened to visit could otherwise make credentialed requests against the dev\n * server with the developer's session and read the responses.\n */\nexport function isLocalhostOrigin(origin: string): boolean {\n try {\n const { hostname } = new URL(origin);\n return hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\";\n } catch {\n return false;\n }\n}\n\n/** A CORS origin resolver of the shape Hono's `cors()` middleware expects. */\n/**\n * Whether this process serves the OpenAPI docs.\n *\n * An explicit `REBASE_ENABLE_SWAGGER` wins in either direction. Left unset, the\n * docs follow the environment: on in development, where they are part of how a\n * scaffolded project is meant to be explored, and off in production, where the\n * spec enumerates every collection and field to anyone who asks for it.\n *\n * Returning `undefined` for development is the point rather than an oversight —\n * it hands the decision to the server's own policy in `init/docs.ts`, which also\n * knows to withhold the Swagger UI while still serving the spec. Two defaults\n * that can disagree about the same route is the bug this replaces.\n */\nexport function resolveEnableSwagger(env: RebaseBootEnv): boolean | undefined {\n if (env.REBASE_ENABLE_SWAGGER !== undefined) return env.REBASE_ENABLE_SWAGGER;\n return env.NODE_ENV === \"production\" ? false : undefined;\n}\n\nexport type CorsOriginResolver = (origin: string) => string | null;\n\n/**\n * Build the CORS origin policy.\n *\n * Production serves an explicit allow-list and nothing else. `loadEnv` already\n * refuses to start a production process with neither `CORS_ORIGINS` nor\n * `FRONTEND_URL`, so an empty list here can only mean the values were blank\n * strings — still worth failing on, because the alternative is an API that\n * quietly rejects its own frontend.\n */\nexport function resolveCorsOrigin(env: RebaseBootEnv): CorsOriginResolver {\n const isProduction = env.NODE_ENV === \"production\";\n\n if (!isProduction) {\n return (origin: string) => {\n if (!origin) return \"*\";\n return isLocalhostOrigin(origin) ? origin : null;\n };\n }\n\n const raw = env.CORS_ORIGINS || env.FRONTEND_URL || \"\";\n const allowed = raw.split(\",\").map(s => s.trim()).filter(Boolean);\n\n if (allowed.length === 0) {\n throw new Error(\n \"CORS_ORIGINS or FRONTEND_URL must be set in production. \" +\n \"Example: CORS_ORIGINS=https://yourdomain.com\"\n );\n }\n\n const wildcard = allowed.includes(\"*\");\n if (wildcard) {\n // `*` with credentials is rejected by every browser, so a config that\n // asks for it is a misconfiguration that would present as an opaque CORS\n // failure at runtime. Say so at boot instead.\n throw new Error(\n \"CORS_ORIGINS cannot be \\\"*\\\" — the API sends credentials, and browsers \" +\n \"refuse a wildcard origin on credentialed requests. List the exact origins.\"\n );\n }\n\n return (origin: string) => (allowed.includes(origin) ? origin : null);\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport {\n DEFAULT_DATA_SOURCE_KEY,\n DEFAULT_STORAGE_SOURCE_KEY,\n findStorageSuffixCollision,\n normalizeStorageSources,\n storageEnvSuffix,\n type DataSourceDefinition,\n type DeclaredStorageSources,\n type StorageSourceDefinition\n} from \"@rebasepro/types\";\nimport type { BackendStorageConfig } from \"../storage/types\";\nimport { logger } from \"../utils/logger\";\nimport { BundleError } from \"./bundle\";\n\n/**\n * Resolving *named* data and storage sources from the environment.\n *\n * A project is not required to have one database and one bucket. Collections\n * already route by `collection.dataSource`, storage properties already route by\n * `storageSource`, and the backend already registers one driver per source key —\n * so the only piece missing was a way to *configure* the second, third and fourth\n * of each without hand-writing an entrypoint.\n *\n * The naming rule is mechanical, and deliberately derives the variable name from\n * the declared key rather than trying to discover keys by scanning the\n * environment. Scanning would have to guess how `DATABASE_URL_READ_REPLICA` splits\n * into a key; deriving cannot be ambiguous, and a typo shows up as a missing\n * source at boot instead of a silently ignored variable.\n *\n * ```\n * <BASE> the default source DATABASE_URL, S3_BUCKET\n * <BASE>__<KEY> a named source DATABASE_URL__ANALYTICS, S3_BUCKET__MEDIA\n * ```\n *\n * The double underscore matters: single-underscore suffixes collide with real\n * variable names (`S3_BUCKET_NAME` would parse as bucket \"name\").\n */\n\n/** Environment lookup, injectable so tests need not mutate `process.env`. */\nexport type EnvBag = Record<string, string | undefined>;\n\n/**\n * Convert a source key into the suffix used in environment variable names.\n *\n * The default key maps to no suffix at all, which is what keeps every existing\n * single-database deployment working untouched.\n *\n * The rule itself lives in `@rebasepro/types` so the CLI and any control plane\n * derive identical names from identical keys; this wrapper exists only to raise\n * it as a `BundleError`, which is what the rest of boot reports failures as.\n */\nexport function envSuffixForKey(key: string, defaultKey: string): string {\n try {\n return storageEnvSuffix(key, defaultKey);\n } catch (err) {\n throw new BundleError(\n `Source key \"${key}\" cannot be turned into an environment variable name.`,\n \"Use a key containing at least one letter or digit.\"\n );\n }\n}\n\n/** Read `<base>` for the default source, `<base>__<KEY>` for a named one. */\nfunction readVar(env: EnvBag, base: string, suffix: string): string | undefined {\n const value = env[`${base}${suffix}`];\n return value === \"\" ? undefined : value;\n}\n\nfunction readBool(env: EnvBag, base: string, suffix: string): boolean | undefined {\n const raw = readVar(env, base, suffix);\n if (raw === undefined) return undefined;\n return raw === \"true\";\n}\n\n/**\n * Guard against two distinct keys collapsing onto the same variable name.\n *\n * `media-cdn` and `media_cdn` are different source keys but the same suffix, and\n * without this check one of them would silently read the other's configuration.\n */\nexport function assertDistinctSuffixes(\n definitions: { key: string }[],\n defaultKey: string,\n what: string\n): void {\n const collision = findStorageSuffixCollision(definitions.map(d => d.key), defaultKey);\n if (collision) {\n throw new BundleError(\n `${what} keys \"${collision.a}\" and \"${collision.b}\" both map to the same environment ` +\n `variable suffix \"${collision.suffix || \"(none)\"}\".`,\n \"Rename one of them so each source has its own configuration.\"\n );\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Data sources\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Which driver package backs a given engine, before env overrides. */\nconst ENGINE_DRIVERS: Record<string, string> = {\n postgres: \"@rebasepro/server-postgres\",\n postgresql: \"@rebasepro/server-postgres\",\n mongodb: \"@rebasepro/server-mongo\",\n mongo: \"@rebasepro/server-mongo\"\n};\n\n/** A data source resolved to everything needed to build a driver for it. */\nexport interface ResolvedDataSourceConfig {\n /** Data-source key — becomes the driver-registry id collections route by. */\n key: string;\n engine: string;\n /** npm package implementing the driver. */\n driverPackage: string;\n connectionString: string;\n adminConnectionString?: string;\n readConnectionString?: string;\n isDefault: boolean;\n poolConfig?: Record<string, number>;\n}\n\n/**\n * Resolve every server-transport data source to a connection.\n *\n * `direct` and `custom` transports are skipped: the client talks to those\n * itself, so the backend holds no connection for them and must not demand one.\n *\n * A declared source with no connection string is an error rather than a warning.\n * The alternative — starting without it — means every collection routed to that\n * source silently falls back to the default database, which is data landing in\n * the wrong place with a healthy-looking server in front of it.\n */\nexport function resolveDataSources(\n env: EnvBag,\n definitions: DataSourceDefinition[] | undefined\n): ResolvedDataSourceConfig[] {\n const declared = definitions ?? [];\n assertDistinctSuffixes(declared, DEFAULT_DATA_SOURCE_KEY, \"Data source\");\n\n // A project that declares nothing still has one database: the default.\n const hasDefault = declared.some(d => d.key === DEFAULT_DATA_SOURCE_KEY);\n const serverSide = declared.filter(d => (d.transport ?? \"server\") === \"server\");\n const effective: DataSourceDefinition[] = hasDefault\n ? serverSide\n : [{ key: DEFAULT_DATA_SOURCE_KEY,\nengine: \"postgres\" }, ...serverSide];\n\n const resolved: ResolvedDataSourceConfig[] = [];\n\n for (const definition of effective) {\n const suffix = envSuffixForKey(definition.key, DEFAULT_DATA_SOURCE_KEY);\n const connectionString = readVar(env, \"DATABASE_URL\", suffix);\n\n if (!connectionString) {\n throw new BundleError(\n `Data source \"${definition.key}\" has no connection string — ` +\n `set ${`DATABASE_URL${suffix}`}.`,\n \"Every declared server-transport data source needs its own connection; \" +\n \"collections routed to it would otherwise silently use the default database.\"\n );\n }\n\n const engine = definition.engine || \"postgres\";\n const driverPackage =\n readVar(env, \"REBASE_DRIVER\", suffix) ||\n ENGINE_DRIVERS[engine.toLowerCase()];\n\n if (!driverPackage) {\n throw new BundleError(\n `No driver package is known for engine \"${engine}\" (data source \"${definition.key}\") — ` +\n `set ${`REBASE_DRIVER${suffix}`} to the npm package implementing it.`\n );\n }\n\n const poolConfig = resolvePoolConfig(env, suffix);\n\n resolved.push({\n key: definition.key,\n engine,\n driverPackage,\n connectionString,\n adminConnectionString: readVar(env, \"ADMIN_CONNECTION_STRING\", suffix),\n readConnectionString: readVar(env, \"DATABASE_READ_URL\", suffix),\n isDefault: definition.key === DEFAULT_DATA_SOURCE_KEY,\n poolConfig\n });\n }\n\n if (!resolved.some(r => r.isDefault)) {\n // A default declared as `direct` still fails here, and must: the driver\n // registry promotes whatever driver it has to be the default, so a\n // project in that shape would route every collection that names no data\n // source into some *other* project database. Refusing is the only\n // outcome that cannot silently write to the wrong place.\n const directDefault = declared.some(\n d => d.key === DEFAULT_DATA_SOURCE_KEY && (d.transport ?? \"server\") !== \"server\"\n );\n throw new BundleError(\n directDefault\n ? `The default data source is declared with a non-server transport, so the backend ` +\n \"holds no connection for it — but collections that name no data source still need one.\"\n : \"No default data source is configured.\",\n directDefault\n ? `Give \"${DEFAULT_DATA_SOURCE_KEY}\" a server transport and set DATABASE_URL, or point ` +\n \"every collection at an explicit dataSource.\"\n : `Declare a data source with key \"${DEFAULT_DATA_SOURCE_KEY}\", or set DATABASE_URL.`\n );\n }\n\n return resolved;\n}\n\nfunction resolvePoolConfig(env: EnvBag, suffix: string): Record<string, number> | undefined {\n const entries: Record<string, number> = {};\n const max = readVar(env, \"DB_POOL_MAX\", suffix);\n const idle = readVar(env, \"DB_POOL_IDLE_TIMEOUT\", suffix);\n const connect = readVar(env, \"DB_POOL_CONNECT_TIMEOUT\", suffix);\n\n if (max !== undefined) entries.max = Number(max);\n if (idle !== undefined) entries.idleTimeoutMillis = Number(idle);\n if (connect !== undefined) entries.connectionTimeoutMillis = Number(connect);\n\n for (const [name, value] of Object.entries(entries)) {\n if (!Number.isFinite(value)) {\n throw new BundleError(`Pool setting \"${name}\" for suffix \"${suffix || \"(default)\"}\" is not a number.`);\n }\n }\n\n return Object.keys(entries).length > 0 ? entries : undefined;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Storage sources\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Build one storage configuration from the variables for a single source.\n *\n * Returns `undefined` when the source has no configuration at all, so an\n * optional bucket that was never set does not fail a boot. The production\n * \"local storage is off\" rule deliberately does *not* live here — it is enforced\n * once, in `initializeStorage`, which logs precisely why storage is disabled.\n * Duplicating it would mean two places to keep in agreement.\n */\nexport function resolveStorageBackend(\n env: EnvBag,\n key: string,\n engineHint: string | undefined,\n defaultBasePath: string\n): BackendStorageConfig | undefined {\n const suffix = envSuffixForKey(key, DEFAULT_STORAGE_SOURCE_KEY);\n const declaredType = readVar(env, \"STORAGE_TYPE\", suffix);\n const type = (declaredType || engineHint || \"\").toLowerCase();\n // Whether the *environment* named this backend, as opposed to inheriting it\n // from a declaration. It decides what a missing bucket means:\n //\n // STORAGE_TYPE__MEDIA=s3 with no bucket → someone configured this and got\n // it wrong. Refuse.\n // `rebase.json` declares media: s3, and\n // the environment says nothing → the bucket has not been\n // attached yet. Not an error.\n //\n // Declaring a source is how a project states its topology, often long before\n // anyone attaches a bucket to it — the console's whole \"declared, not\n // configured\" state. Treating that as a fatal misconfiguration would make\n // the act of declaring a bucket crash-loop the backend until someone\n // configured it, which is precisely the unreadable failure the manifest\n // declaration exists to prevent.\n const explicit = Boolean(declaredType);\n\n if (type === \"s3\") {\n const bucket = readVar(env, \"S3_BUCKET\", suffix);\n if (!bucket) {\n if (!explicit) return undefined;\n throw new BundleError(\n `Storage source \"${key}\" is set to s3 but has no bucket — ` +\n `set ${`S3_BUCKET${suffix}`}.`\n );\n }\n const accessKeyId = readVar(env, \"S3_ACCESS_KEY_ID\", suffix);\n const secretAccessKey = readVar(env, \"S3_SECRET_ACCESS_KEY\", suffix);\n // A bucket with no credentials cannot work, and failing here is far\n // clearer than what it does otherwise: `S3StorageController` passes an\n // explicit `credentials: { accessKeyId: \"\", secretAccessKey: \"\" }` to the\n // AWS SDK, which suppresses the SDK's own credential chain — so this\n // never silently falls back to an instance profile or IRSA. It signs\n // every request with nothing and fails each one separately, at upload\n // time, with an opaque signing error.\n //\n // Same rule the control plane applies when it classifies a tenant's\n // environment for the build log, so the log and the runtime agree on\n // what this configuration is.\n if (!accessKeyId || !secretAccessKey) {\n if (!explicit) return undefined;\n const missing = [\n !accessKeyId && `S3_ACCESS_KEY_ID${suffix}`,\n !secretAccessKey && `S3_SECRET_ACCESS_KEY${suffix}`\n ].filter(Boolean).join(\" and \");\n throw new BundleError(\n `Storage source \"${key}\" is set to s3 with a bucket but no credentials — set ${missing}.`,\n \"A bucket without credentials cannot be reached: every upload fails when the request is signed.\"\n );\n }\n\n return {\n type: \"s3\",\n bucket,\n region: readVar(env, \"S3_REGION\", suffix) || \"auto\",\n accessKeyId,\n secretAccessKey,\n endpoint: readVar(env, \"S3_ENDPOINT\", suffix),\n forcePathStyle: readBool(env, \"S3_FORCE_PATH_STYLE\", suffix)\n };\n }\n\n if (type === \"gcs\") {\n const bucket = readVar(env, \"GCS_BUCKET\", suffix);\n if (!bucket) {\n if (!explicit) return undefined;\n throw new BundleError(\n `Storage source \"${key}\" is set to gcs but has no bucket — ` +\n `set ${`GCS_BUCKET${suffix}`}.`\n );\n }\n return {\n type: \"gcs\",\n bucket,\n projectId: readVar(env, \"GCS_PROJECT_ID\", suffix),\n keyFilename: readVar(env, \"GCS_KEY_FILENAME\", suffix)\n };\n }\n\n if (type === \"local\" || type === \"\") {\n return {\n type: \"local\",\n basePath: readVar(env, \"STORAGE_PATH\", suffix) || defaultBasePath\n };\n }\n\n throw new BundleError(\n `Storage source \"${key}\" has unsupported type \"${type}\".`,\n \"Supported types are local, s3 and gcs. For anything else, pass a StorageController.\"\n );\n}\n\n/**\n * Resolve every server-transport storage source into a controller config map.\n *\n * The returned shape is the `Record<key, config>` the backend already accepts,\n * so multiple buckets need nothing new downstream — they were always supported,\n * they just had no way to be configured from the environment.\n */\nexport function resolveStorageSources(\n env: EnvBag,\n definitions: StorageSourceDefinition[] | undefined,\n defaultBasePath: string\n): Record<string, BackendStorageConfig> | undefined {\n const declared = definitions ?? [];\n assertDistinctSuffixes(declared, DEFAULT_STORAGE_SOURCE_KEY, \"Storage source\");\n\n const serverSide = declared.filter(d => (d.transport ?? \"server\") === \"server\");\n\n // Synthesize the default bucket only when the project declared *nothing*.\n //\n // Inventing one alongside explicitly declared sources is actively harmful.\n // The synthesized default falls through to local disk; production drops local\n // backends (files written there die with the container); the storage registry\n // then promotes whichever backend remains to be the default. So a project\n // declaring only a \"media\" bucket would put its default uploads on local disk\n // in development and in the media bucket in production. Two different\n // destinations either side of a deploy is worse than having no default\n // bucket, which at least fails the same way in both.\n const effective: { key: string; engine?: string }[] = declared.length === 0\n ? [{ key: DEFAULT_STORAGE_SOURCE_KEY,\nengine: undefined }]\n : serverSide;\n\n const result: Record<string, BackendStorageConfig> = {};\n for (const definition of effective) {\n const config = resolveStorageBackend(\n env,\n definition.key,\n definition.engine,\n defaultBasePath\n );\n if (config) result[definition.key] = config;\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\n/**\n * Read a project's declared storage sources from its `rebase.json`.\n *\n * A managed bundle carries its topology in `manifest.json`, resolved at build\n * time. A **custom** runtime has no manifest — it builds its own image and its\n * own entrypoint — so without this it would have to re-declare in code what\n * `rebase.json` already says, and the two would drift. Since a custom image\n * contains the repository anyway, reading the file it already ships is what\n * keeps one declaration authoritative for both runtimes.\n *\n * Walks up from `startDir` because an entrypoint lives at `backend/src` in the\n * scaffolded layout and somewhere else in a hand-rolled one. A missing,\n * unreadable or malformed file means \"declared nothing\" — one default source —\n * which is the correct reading of every project that predates this and must\n * never be an error: a storage declaration is optional, and failing to boot a\n * whole backend over an absent optional file would be the worse bug.\n */\nexport function loadDeclaredStorageSources(\n startDir: string,\n levels = 5\n): StorageSourceDefinition[] {\n let dir = startDir;\n for (let i = 0; i <= levels; i++) {\n const candidate = path.join(dir, \"rebase.json\");\n if (fs.existsSync(candidate)) {\n // Only the read and the parse degrade quietly. What the file *says*\n // is validated outside this catch on purpose: a collision between two\n // source keys is precisely the failure this loader exists to prevent,\n // and swallowing it would turn \"these two buckets would read each\n // other's credentials\" into \"this project declared nothing\" — the\n // silent wrong answer instead of the loud right one.\n let declared: DeclaredStorageSources | undefined;\n try {\n declared = (JSON.parse(fs.readFileSync(candidate, \"utf8\")) as {\n storage?: DeclaredStorageSources;\n })?.storage;\n } catch (err) {\n logger.warn(\n `Could not read storage sources from ${candidate}: ` +\n `${err instanceof Error ? err.message : String(err)}. ` +\n \"Continuing with a single default storage source.\"\n );\n return [];\n }\n const sources = normalizeStorageSources(declared, undefined);\n assertDistinctSuffixes(sources, DEFAULT_STORAGE_SOURCE_KEY, \"Storage source\");\n return sources;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return [];\n}\n","/**\n * Telling a *stale* driver apart from a driver that never had the feature.\n *\n * The managed runtime is two halves that version independently. The image\n * supplies `@rebasepro/server` — `docker/entrypoint.mjs` symlinks it over\n * whatever the bundle installed, so the boot harness is always the image's. The\n * **driver** is not redirected: `@rebasepro/server-postgres` comes from the\n * bundle's `deps.declared`, pinned to whatever the project's `package.json`\n * asked npm for. Shipping a new image therefore does not ship a new driver, and\n * a fix that spans both packages reaches a tenant only after an npm publish AND\n * a rebuild.\n *\n * That split has a nasty failure mode, and it has already burned a day. Boot\n * looks for an optional capability, does not find it, and reports the honest\n * local fact — \"this driver does not implement collection-table creation\" —\n * which is exactly what a schemaless driver looks like. But a driver that is\n * merely *older than the runtime asking* looks identical, and the two want\n * opposite responses: one is \"this database is not managed by Rebase, carry on\",\n * the other is \"your tables were never created and every data route is about to\n * 500\". Naming the versions is what separates them, so these helpers exist to\n * put both numbers in front of whoever reads the log.\n */\nimport fs from \"fs\";\nimport path from \"path\";\n\n/** The package whose version defines \"the runtime\" for skew purposes. */\nconst RUNTIME_PACKAGE = \"@rebasepro/server\";\n\n/**\n * Locate a package by walking `node_modules` up from a directory.\n *\n * Lives here rather than in `driver.ts` because both the driver loader and the\n * version check need it, and `driver.ts` already imports this module.\n */\nexport function findPackageDir(fromDir: string, packageName: string): string | undefined {\n let dir = path.resolve(fromDir);\n for (;;) {\n const candidate = path.join(dir, \"node_modules\", ...packageName.split(\"/\"));\n if (fs.existsSync(path.join(candidate, \"package.json\"))) return candidate;\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\ninterface ParsedVersion {\n parts: number[];\n /** `canary.g7f1150f` in `0.12.1-canary.g7f1150f`, absent on a release. */\n prerelease?: string;\n}\n\n/**\n * Parse the subset of semver the workspace actually publishes.\n *\n * Deliberately lenient: an unparseable version yields `undefined` and every\n * comparison then declines to judge, because a wrong \"your driver is old\"\n * warning on a fork's custom version string is worse than no warning at all.\n */\nfunction parseVersion(version: string): ParsedVersion | undefined {\n const match = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(.+))?$/.exec(version.trim());\n if (!match) return undefined;\n return {\n parts: [Number(match[1]), Number(match[2]), Number(match[3])],\n prerelease: match[4]\n };\n}\n\n/**\n * Compare two versions, or `undefined` when either cannot be parsed.\n *\n * Follows semver on the one rule that matters here: a prerelease sorts *below*\n * the release it leads to, so `0.12.1-canary.g7f1150f` < `0.12.1`. Without that\n * rule every canary would read as newer than the stable it precedes, and the\n * canaries are precisely where fixes land first.\n */\nexport function compareVersions(a: string, b: string): number | undefined {\n const left = parseVersion(a);\n const right = parseVersion(b);\n if (!left || !right) return undefined;\n\n for (let i = 0; i < 3; i++) {\n if (left.parts[i] !== right.parts[i]) return left.parts[i] < right.parts[i] ? -1 : 1;\n }\n if (left.prerelease === right.prerelease) return 0;\n if (left.prerelease === undefined) return 1;\n if (right.prerelease === undefined) return -1;\n return left.prerelease < right.prerelease ? -1 : 1;\n}\n\nexport interface DriverSkew {\n /** True only when both versions parsed AND the driver is genuinely older. */\n stale: boolean;\n /**\n * A clause naming both versions, ready to append to a sentence. Present\n * whenever both versions are known — including when they agree, because\n * \"the driver is current\" is the fact that redirects an investigation away\n * from staleness and toward the real cause.\n */\n detail?: string;\n}\n\n/**\n * Describe how a driver's version relates to the runtime asking it for work.\n *\n * Returns `stale: false` whenever it cannot tell — an unknown version, an\n * unparseable one, a driver that is newer. Silence beats a confident wrong\n * diagnosis, and the caller still prints its own local fact either way.\n */\nexport function describeDriverSkew(\n driverVersion: string | undefined,\n runtimeVersion: string | undefined\n): DriverSkew {\n if (!driverVersion || !runtimeVersion) return { stale: false };\n const order = compareVersions(driverVersion, runtimeVersion);\n if (order === undefined) return { stale: false };\n if (order < 0) {\n return {\n stale: true,\n detail:\n `The driver is at ${driverVersion} while this runtime is ${runtimeVersion} — ` +\n \"the driver is OLDER, so this is very likely a stale pin rather than a driver \" +\n \"that never had the capability.\"\n };\n }\n return {\n stale: false,\n detail: `Driver ${driverVersion}, runtime ${runtimeVersion}.`\n };\n}\n\n/**\n * How to get a project's schema applied, written once and owned by the runtime.\n *\n * This text lives in `@rebasepro/server` on purpose. The equivalent guidance in\n * the Postgres driver's schema-drift warning can only ever be as current as the\n * driver a tenant pinned — so the tenants who most need to be told \"your driver\n * is too old\" are exactly the ones whose driver still prints the old advice.\n * The image's copy of this package is never stale, so guidance printed from\n * here always reflects the platform as it is today.\n *\n * Both audiences get a line because the runtime cannot reliably tell which one\n * it is serving, and naming only the pnpm scripts — as this once did everywhere\n * — tells a managed operator to run a command that structurally cannot reach\n * their in-cluster database.\n */\nexport function schemaRecoveryGuidance(options: { staleDriver?: boolean } = {}): string {\n const lines = [\n \" To apply this project's schema:\",\n \" • Managed cloud: the runtime applies tables and RLS at boot (unless\",\n \" REBASE_MIGRATE_ON_BOOT=none). `rebase db push` cannot reach a tenant's\",\n \" in-cluster database — redeploy instead.\"\n ];\n if (options.staleDriver) {\n lines.push(\n \" Because the driver is pinned by your bundle, bump the\",\n \" `@rebasepro/server-postgres` version in your project's package.json\",\n \" and redeploy — a newer platform image alone will NOT update it.\"\n );\n }\n lines.push(\" • Self-host: run `rebase db push` (dev) or `rebase db migrate` (prod).\");\n return lines.join(\"\\n\");\n}\n\n/**\n * The installed version of a package, read from its `package.json`.\n *\n * Returns `undefined` rather than throwing for every failure — a missing or\n * malformed manifest degrades the diagnosis, and must never take down a boot\n * that would otherwise have served.\n */\nexport function readPackageVersion(packageDir: string): string | undefined {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(packageDir, \"package.json\"), \"utf8\")) as {\n version?: unknown;\n };\n return typeof pkg.version === \"string\" ? pkg.version : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The version of `@rebasepro/server` this deployment is actually running.\n *\n * Resolved from the same roots the drivers are, and that is the point rather\n * than a convenience. In a managed container `docker/entrypoint.mjs` replaces\n * `/bundle/node_modules/@rebasepro/server` with a link to the image's copy, so\n * reading the manifest *through the bundle* reports the version that will\n * really execute — which is exactly the number the driver has to be compared\n * against. Reading this package's own manifest by module path would report the\n * same thing in the happy case and quietly lie in the case that matters: a\n * bundle whose link did not happen.\n *\n * Returns `undefined` when the package cannot be found; every caller treats\n * that as \"cannot judge\" and stays quiet.\n */\nexport function readRuntimeVersion(roots: string[]): string | undefined {\n for (const root of roots) {\n const dir = findPackageDir(root, RUNTIME_PACKAGE);\n const version = dir ? readPackageVersion(dir) : undefined;\n if (version) return version;\n }\n return undefined;\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport type {\n BackendBootstrapper,\n DatabaseAdapter,\n DatabaseAdapterInitConfig,\n InitializedDriver\n} from \"@rebasepro/types\";\nimport { logger } from \"../utils/logger\";\nimport { BundleError } from \"./bundle\";\nimport type { ResolvedDataSourceConfig } from \"./sources\";\nimport { findPackageDir, readPackageVersion } from \"./version-skew\";\n\n/**\n * Database drivers are loaded by name at runtime rather than imported.\n *\n * They have to be: every driver package depends on this one (it implements the\n * adapter interfaces defined here), so a static import would be a cycle. Loading\n * by name also keeps the runtime honestly database-agnostic — the image has no\n * opinion about Postgres, it resolves whichever driver each data source declares.\n */\n\n/** What a driver package must export to be bootable. */\ninterface DriverModule {\n createDatabaseConnection?: DriverConnectionFactory;\n createPostgresDatabaseConnection?: DriverConnectionFactory;\n createAdapter?: DriverAdapterFactory;\n createPostgresAdapter?: DriverAdapterFactory;\n}\n\ntype DriverConnectionFactory = (\n connectionString: string,\n schema?: Record<string, unknown>,\n poolConfig?: Record<string, unknown>\n) => DriverConnection;\n\ntype DriverAdapterFactory = (config: Record<string, unknown>) => DatabaseAdapter;\n\n/**\n * The connection handle a driver hands back at boot: the client object, the\n * pool to close on shutdown, and how to probe it.\n *\n * Named `DatabaseConnection` until that collided with `DatabaseConnection` in\n * `@rebasepro/types` — an abstract `{ type, isConnected, close() }` that\n * `MongoDBConnection` implements. The two share no field, and both are public:\n * one is re-exported from `@rebasepro/server`'s index, the other from\n * `@rebasepro/types`, packages that are installed together.\n */\nexport interface DriverConnection {\n db: unknown;\n /**\n * Present for pool-based drivers. Closed during shutdown, and used to probe\n * the source for health — `query` lives here, not on the connection itself.\n */\n pool?: {\n end: () => Promise<void>;\n query?: (sql: string) => Promise<unknown>;\n };\n /** Some drivers expose a query directly instead of via a pool. */\n query?: (sql: string) => Promise<unknown>;\n connectionString?: string;\n}\n\n/**\n * Run a trivial query against a source, to see whether it answers.\n *\n * Returns `undefined` when the driver exposes no way to ask — a driver that\n * cannot be probed must not be reported as unhealthy, only as unknown.\n */\nexport async function probeDataSource(\n source: InitializedDataSource\n): Promise<{ healthy: boolean; error?: string } | undefined> {\n const query = source.connection.query ?? source.connection.pool?.query;\n if (typeof query !== \"function\") return undefined;\n\n try {\n await query.call(source.connection.pool ?? source.connection, \"SELECT 1\");\n return { healthy: true };\n } catch (err) {\n return {\n healthy: false,\n error: err instanceof Error ? err.message : String(err)\n };\n }\n}\n\n/** One initialized data source: its bootstrapper plus the handle to close. */\nexport interface InitializedDataSource {\n key: string;\n engine: string;\n driverPackage: string;\n /**\n * The driver's installed version, when it could be read.\n *\n * Carried so a boot that finds a capability missing can say whether the\n * driver is *old* or merely *different* — see `version-skew.ts`. Optional\n * because a driver resolved from outside a `node_modules` tree (a linked\n * workspace, a bare specifier) has no manifest to read, and that must not\n * be fatal.\n */\n driverVersion?: string;\n bootstrapper: BackendBootstrapper;\n connection: DriverConnection;\n}\n\nexport interface BundleSchema {\n tables?: Record<string, unknown>;\n enums?: Record<string, unknown>;\n relations?: Record<string, unknown>;\n}\n\n/**\n * Where to look for packages a bundle brought with it.\n *\n * A driver has to be resolved relative to the **bundle**, not to this package.\n * A bare `import(\"@rebasepro/server-postgres\")` resolves from wherever the\n * runtime itself is installed, which on a real deployment is somewhere else\n * entirely — the runtime image holds the server, the bundle holds the project's\n * dependencies. Resolving from the bundle is also the honest semantics: the\n * project declares which driver it uses, so the project's tree is where to look.\n *\n * Several roots, because a driver is installed wherever the project keeps its\n * dependencies: beside a built bundle, but inside the backend package in a\n * workspace running from source.\n */\nexport function bundleResolutionRoots(bundleDir: string): string[] {\n return [\n bundleDir,\n path.join(bundleDir, \"backend\"),\n path.join(bundleDir, \"config\")\n ];\n}\n\n/** The ESM entry a package declares, preferring `exports` over the legacy fields. */\nfunction resolvePackageEntry(packageDir: string): string | undefined {\n let pkg: {\n exports?: unknown;\n module?: string;\n main?: string;\n };\n try {\n pkg = JSON.parse(fs.readFileSync(path.join(packageDir, \"package.json\"), \"utf8\"));\n } catch {\n return undefined;\n }\n\n const fromExports = (value: unknown): string | undefined => {\n if (typeof value === \"string\") return value;\n if (!value || typeof value !== \"object\") return undefined;\n const record = value as Record<string, unknown>;\n // Import first: this is an ESM runtime, and a driver's `require` entry\n // may not exist at all.\n for (const condition of [\"import\", \"module\", \"default\", \"node\"]) {\n const resolved = fromExports(record[condition]);\n if (resolved) return resolved;\n }\n return undefined;\n };\n\n const candidate = (pkg.exports && typeof pkg.exports === \"object\"\n ? fromExports((pkg.exports as Record<string, unknown>[\".\"]) ?? pkg.exports)\n : fromExports(pkg.exports))\n ?? pkg.module\n ?? pkg.main;\n\n if (!candidate) return undefined;\n const entry = path.resolve(packageDir, candidate);\n return fs.existsSync(entry) ? entry : undefined;\n}\n\n/**\n * Import a driver package, resolving its factories under either naming scheme.\n *\n * The generic names are the contract going forward; the Postgres-specific ones\n * are still accepted so a bundle can run against a driver release that predates\n * the generic aliases.\n */\nasync function importDriver(packageName: string, resolveFrom: string[] = []): Promise<{\n createConnection: DriverConnectionFactory;\n createAdapter: DriverAdapterFactory;\n /** Where the driver was found, when it resolved from a `node_modules` tree. */\n packageDir?: string;\n}> {\n let specifier = packageName;\n let resolvedDir: string | undefined;\n\n for (const root of resolveFrom) {\n const packageDir = findPackageDir(root, packageName);\n const entry = packageDir ? resolvePackageEntry(packageDir) : undefined;\n if (entry) {\n specifier = pathToFileURL(entry).href;\n resolvedDir = packageDir;\n break;\n }\n }\n\n let mod: DriverModule;\n try {\n mod = await import(specifier) as DriverModule;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new BundleError(\n `Could not load the database driver \"${packageName}\": ${message}`,\n `Install it alongside the runtime (e.g. \\`npm install ${packageName}\\`), ` +\n \"or point the data source at a different driver with REBASE_DRIVER.\"\n );\n }\n\n const createConnection = mod.createDatabaseConnection || mod.createPostgresDatabaseConnection;\n const createAdapter = mod.createAdapter || mod.createPostgresAdapter;\n\n if (!createConnection || !createAdapter) {\n throw new BundleError(\n `\"${packageName}\" does not look like a Rebase database driver.`,\n \"A driver must export `createDatabaseConnection` and `createAdapter`.\"\n );\n }\n\n return { createConnection, createAdapter, packageDir: resolvedDir };\n}\n\n/**\n * Wrap a `DatabaseAdapter` as a `BackendBootstrapper` carrying a registry id.\n *\n * `initializeRebaseBackend` does this internally for its single-adapter\n * convenience path, but that path hardcodes one anonymous driver. Multiple\n * sources need an explicit `id` per adapter, because the id is exactly what\n * `collection.dataSource` routes against.\n */\nexport function adapterToBootstrapper(\n adapter: DatabaseAdapter,\n id: string,\n isDefault: boolean\n): BackendBootstrapper {\n return {\n type: adapter.type,\n id,\n isDefault,\n initializeDriver: (initConfig: unknown) =>\n adapter.initializeDriver(initConfig as DatabaseAdapterInitConfig),\n initializeRealtime: adapter.initializeRealtime\n ? (_config: unknown, driverResult: InitializedDriver) =>\n adapter.initializeRealtime!(driverResult)\n : undefined,\n initializeAuth: adapter.initializeAuth,\n initializeHistory: adapter.initializeHistory,\n initializeWebsockets: adapter.initializeWebsockets,\n // Load-bearing for a managed boot: the runtime creates a fresh tenant's\n // tables and RLS through these at boot. Dropping them here (the previous\n // shape did) left the schema-ensure feature dead on the real adapter\n // path — `boot.ts` saw no method and skipped, so every data route 500'd\n // on a missing relation with only a \"driver does not implement\" warning.\n ensureCollectionSchema: adapter.ensureCollectionSchema\n ? (collections, driverResult, log) =>\n adapter.ensureCollectionSchema!(collections, driverResult, log)\n : undefined,\n ensureCollectionPolicies: adapter.ensureCollectionPolicies\n ? (collections, driverResult, log) =>\n adapter.ensureCollectionPolicies!(collections, driverResult, log)\n : undefined,\n getAdmin: adapter.getAdmin,\n mountRoutes: adapter.mountRoutes\n };\n}\n\n/**\n * Build a driver for one data source.\n *\n * Only the default source receives the bundle's Drizzle schema: the schema\n * describes the tables generated from this project's collections, which live in\n * the default database. Handing it to a secondary source would tell that\n * driver's adapter about tables it does not have.\n */\nexport async function initializeDataSource(\n source: ResolvedDataSourceConfig,\n schema: BundleSchema | undefined,\n resolveFrom: string[] = []\n): Promise<InitializedDataSource> {\n const { createConnection, createAdapter, packageDir } = await importDriver(source.driverPackage, resolveFrom);\n const driverVersion = packageDir ? readPackageVersion(packageDir) : undefined;\n\n // Every in-tree caller passes `undefined` for the connection's own schema —\n // drizzle only needs it for the relational query API, which the drivers do\n // not use, and passing the grouped bundle schema here would register\n // \"tables\"/\"enums\"/\"relations\" as if they were table names.\n const connection = createConnection(source.connectionString, undefined, source.poolConfig);\n\n const adapter = createAdapter({\n connection: connection.db,\n connectionString: connection.connectionString ?? source.connectionString,\n adminConnectionString: source.adminConnectionString || source.connectionString,\n readConnectionString: source.readConnectionString,\n ...(source.isDefault && schema ? { schema } : {})\n });\n\n logger.info(\"Initialized data source\", {\n key: source.key,\n engine: source.engine,\n driver: source.driverPackage,\n driverVersion\n });\n\n return {\n key: source.key,\n engine: source.engine,\n driverPackage: source.driverPackage,\n driverVersion,\n bootstrapper: adapterToBootstrapper(adapter, source.key, source.isDefault),\n connection\n };\n}\n\n/**\n * Build drivers for every resolved data source.\n *\n * Sequential on purpose: a failure on the second source should not leave a\n * half-opened pool from a third racing behind it, and the log then reads in the\n * order a human would expect.\n */\nexport async function initializeDataSources(\n sources: ResolvedDataSourceConfig[],\n schema: BundleSchema | undefined,\n resolveFrom: string[] = []\n): Promise<InitializedDataSource[]> {\n const initialized: InitializedDataSource[] = [];\n try {\n for (const source of sources) {\n initialized.push(await initializeDataSource(source, schema, resolveFrom));\n }\n } catch (err) {\n // Close whatever did open, so a failed boot does not hold connections\n // against the database while the container restarts.\n await Promise.allSettled(\n initialized.map(s => s.connection.pool?.end())\n );\n throw err;\n }\n return initialized;\n}\n","import type { CollectionConfig } from \"@rebasepro/types\";\nimport type { RebaseAuthConfig } from \"../init\";\nimport type { EmailConfig } from \"../email\";\nimport type { RebaseBootEnv } from \"./env\";\n\n/**\n * Build the email configuration, or `undefined` when no SMTP host is set.\n *\n * Without it the auth adapter still works; password-reset and verification mail\n * simply has nowhere to go, which the auth routes report for themselves.\n */\nexport function resolveEmailOptions(env: RebaseBootEnv): EmailConfig | undefined {\n if (!env.SMTP_HOST) return undefined;\n\n return {\n from: env.SMTP_FROM || `${env.APP_NAME} <noreply@rebase.pro>`,\n smtp: {\n host: env.SMTP_HOST,\n port: env.SMTP_PORT,\n secure: env.SMTP_SECURE,\n auth: env.SMTP_USER\n ? { user: env.SMTP_USER,\npass: env.SMTP_PASS ?? \"\" }\n : undefined,\n name: env.SMTP_NAME\n },\n appName: env.APP_NAME,\n resetPasswordUrl: env.FRONTEND_URL\n };\n}\n\n/**\n * Build the auth configuration from the environment and the bundle's users\n * collection.\n *\n * OAuth providers are included only when both halves of a credential pair are\n * present. Google is the exception the template already made: a client id alone\n * is enough, because the ID-token flow needs no secret.\n */\nexport function resolveAuthOptions(\n env: RebaseBootEnv,\n usersCollection: CollectionConfig | undefined\n): RebaseAuthConfig {\n const auth: RebaseAuthConfig = {\n collection: usersCollection,\n jwtSecret: env.JWT_SECRET,\n accessExpiresIn: env.JWT_ACCESS_EXPIRES_IN,\n refreshExpiresIn: env.JWT_REFRESH_EXPIRES_IN,\n serviceKey: env.REBASE_SERVICE_KEY,\n requireAuth: env.AUTH_REQUIRE,\n allowRegistration: env.ALLOW_REGISTRATION,\n disableSelfRegistration: env.DISABLE_SELF_REGISTRATION,\n allowUserLookup: env.AUTH_ALLOW_USER_LOOKUP,\n email: resolveEmailOptions(env),\n // Cookie auth keeps the refresh token in an httpOnly cookie rather than\n // localStorage, putting it out of reach of XSS. Enabling it costs a\n // token-flow client nothing — the client opts in via `authFlowMode` —\n // so the safer flow is simply always available.\n cookieAuth: { sameSite: env.AUTH_COOKIE_SAME_SITE || \"Lax\" }\n };\n\n if (env.AUTH_DEFAULT_ROLE) {\n auth.defaultRole = env.AUTH_DEFAULT_ROLE;\n }\n\n if (env.GOOGLE_CLIENT_ID) {\n auth.google = {\n clientId: env.GOOGLE_CLIENT_ID,\n clientSecret: env.GOOGLE_CLIENT_SECRET\n };\n }\n if (env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET) {\n auth.github = {\n clientId: env.GITHUB_CLIENT_ID,\n clientSecret: env.GITHUB_CLIENT_SECRET\n };\n }\n if (env.MICROSOFT_CLIENT_ID && env.MICROSOFT_CLIENT_SECRET) {\n auth.microsoft = {\n clientId: env.MICROSOFT_CLIENT_ID,\n clientSecret: env.MICROSOFT_CLIENT_SECRET\n };\n }\n\n return auth;\n}\n","import { Hono } from \"hono\";\nimport type { MiddlewareHandler } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\nimport { safeCompare } from \"../auth/crypto-utils\";\nimport { extractBearerToken } from \"../auth/bearer-token\";\n\n/**\n * Runtime metrics, in Prometheus text format.\n *\n * The point of emitting these from the runtime rather than scraping the\n * container is that only the runtime knows what a request *was*. A pod-level CPU\n * graph cannot tell you that auth is slow while data is fine, or that one app is\n * generating all the traffic. Surface by surface is the difference between a\n * chart that looks like observability and one you can act on.\n *\n * Self-hosters get the same endpoint — this is a plain Prometheus target, not a\n * hook into a hosted platform.\n */\n\n/** Which part of the API served a request. */\nexport type MetricSurface = \"data\" | \"auth\" | \"storage\" | \"functions\" | \"admin\" | \"meta\" | \"other\";\n\nconst LATENCY_BUCKETS_MS = [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000];\n\n/**\n * Separators for the composite map keys used internally.\n *\n * ASCII unit/record separators, which cannot appear in a Prometheus metric name\n * and are vanishingly unlikely in a label value. They are written as escape\n * sequences rather than literal control characters so the source stays greppable\n * and diffable.\n */\nconst LABEL_SEP = \"\\u001f\";\nconst NAME_SEP = \"\\u001e\";\n\ninterface HistogramState {\n counts: number[];\n sum: number;\n total: number;\n}\n\n/**\n * In-process metric store.\n *\n * Counters reset when the process does, which is exactly what Prometheus\n * expects — it handles resets natively, and a restart is a real event a\n * dashboard should be able to see.\n */\n/**\n * Ceiling on distinct label combinations per metric family.\n *\n * Label values that vary without bound are the classic way to take down a\n * Prometheus — and, before that, the process emitting them, since every distinct\n * combination allocates a permanent series. The label set here is derived partly\n * from request paths, so it is reachable by anyone who can send a request.\n * Beyond the cap, series collapse into a single `(other)` bucket: the totals stay\n * correct and memory stops growing.\n */\nconst MAX_SERIES = 512;\n\nexport class MetricsRegistry {\n private requests = new Map<string, number>();\n private latency = new Map<string, HistogramState>();\n private gauges = new Map<string, number>();\n private counters = new Map<string, number>();\n readonly startedAt = Date.now();\n\n private static labelKey(labels: Record<string, string>): string {\n return Object.entries(labels)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([k, v]) => `${k}=${v}`)\n .join(LABEL_SEP);\n }\n\n private static parseLabels(key: string): Record<string, string> {\n if (!key) return {};\n return Object.fromEntries(\n key.split(LABEL_SEP).filter(Boolean).map(pair => {\n const index = pair.indexOf(\"=\");\n return [pair.slice(0, index), pair.slice(index + 1)];\n })\n );\n }\n\n /**\n * Key a named series.\n *\n * Concatenating a name and its labels without a separator would let metric\n * `rebase_x` with label `y=1` collide with a metric literally named\n * `rebase_xy=1`.\n */\n private static namedKey(name: string, labels: Record<string, string>): string {\n return `${name}${NAME_SEP}${MetricsRegistry.labelKey(labels)}`;\n }\n\n private static splitNamedKey(key: string): [string, string] {\n const index = key.indexOf(NAME_SEP);\n if (index === -1) return [key, \"\"];\n return [key.slice(0, index), key.slice(index + NAME_SEP.length)];\n }\n\n recordRequest(labels: Record<string, string>, durationMs: number): void {\n let key = MetricsRegistry.labelKey(labels);\n\n if (!this.requests.has(key) && this.requests.size >= MAX_SERIES) {\n // Only the collection label can grow without bound, so only it is\n // collapsed — rewriting a request that never had one would invent a\n // `collection=\"(other)\"` on, say, an auth request and make the\n // output misleading rather than merely coarser.\n const { collection: _dropped, ...rest } = labels;\n key = MetricsRegistry.labelKey(\n \"collection\" in labels ? { ...rest,\n collection: \"(other)\" } : rest\n );\n }\n\n this.requests.set(key, (this.requests.get(key) ?? 0) + 1);\n\n let hist = this.latency.get(key);\n if (!hist) {\n hist = { counts: new Array(LATENCY_BUCKETS_MS.length + 1).fill(0),\nsum: 0,\ntotal: 0 };\n this.latency.set(key, hist);\n }\n hist.sum += durationMs;\n hist.total += 1;\n let bucket = LATENCY_BUCKETS_MS.findIndex(upper => durationMs <= upper);\n if (bucket === -1) bucket = LATENCY_BUCKETS_MS.length;\n hist.counts[bucket] += 1;\n }\n\n incrementCounter(name: string, labels: Record<string, string> = {}, by = 1): void {\n const key = MetricsRegistry.namedKey(name, labels);\n // Capped for the same reason request series are: whatever calls this\n // next may well pass something request-derived.\n if (!this.counters.has(key) && this.counters.size >= MAX_SERIES) return;\n this.counters.set(key, (this.counters.get(key) ?? 0) + by);\n }\n\n setGauge(name: string, value: number, labels: Record<string, string> = {}): void {\n const key = MetricsRegistry.namedKey(name, labels);\n if (!this.gauges.has(key) && this.gauges.size >= MAX_SERIES) return;\n this.gauges.set(key, value);\n }\n\n /** Prometheus escaping: backslash, quote and newline, in that order. */\n private static formatLabels(labels: Record<string, string>, extra?: Record<string, string>): string {\n const all = { ...labels,\n...extra };\n const entries = Object.entries(all).filter(([, v]) => v !== undefined && v !== \"\");\n if (entries.length === 0) return \"\";\n const body = entries\n .map(([k, v]) => `${k}=\"${String(v).replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, \"\\\\\\\"\").replace(/\\n/g, \"\\\\n\")}\"`)\n .join(\",\");\n return `{${body}}`;\n }\n\n /** Group `name -> [[labelKey, value]]` for one-HELP-per-metric rendering. */\n private static group(source: Map<string, number>): Map<string, [string, number][]> {\n const grouped = new Map<string, [string, number][]>();\n for (const [key, value] of source) {\n const [name, labelKey] = MetricsRegistry.splitNamedKey(key);\n const list = grouped.get(name) ?? [];\n list.push([labelKey, value]);\n grouped.set(name, list);\n }\n return grouped;\n }\n\n render(): string {\n const lines: string[] = [];\n\n lines.push(\"# HELP rebase_uptime_seconds Seconds since this runtime started.\");\n lines.push(\"# TYPE rebase_uptime_seconds gauge\");\n lines.push(`rebase_uptime_seconds ${((Date.now() - this.startedAt) / 1000).toFixed(0)}`);\n\n lines.push(\"# HELP rebase_requests_total Requests handled, by surface, method and status.\");\n lines.push(\"# TYPE rebase_requests_total counter\");\n for (const [key, value] of this.requests) {\n lines.push(`rebase_requests_total${MetricsRegistry.formatLabels(MetricsRegistry.parseLabels(key))} ${value}`);\n }\n\n lines.push(\"# HELP rebase_request_duration_ms Request latency in milliseconds.\");\n lines.push(\"# TYPE rebase_request_duration_ms histogram\");\n for (const [key, hist] of this.latency) {\n const labels = MetricsRegistry.parseLabels(key);\n let cumulative = 0;\n for (let i = 0; i < LATENCY_BUCKETS_MS.length; i++) {\n cumulative += hist.counts[i];\n lines.push(\n `rebase_request_duration_ms_bucket${MetricsRegistry.formatLabels(labels, { le: String(LATENCY_BUCKETS_MS[i]) })} ${cumulative}`\n );\n }\n cumulative += hist.counts[LATENCY_BUCKETS_MS.length];\n lines.push(`rebase_request_duration_ms_bucket${MetricsRegistry.formatLabels(labels, { le: \"+Inf\" })} ${cumulative}`);\n lines.push(`rebase_request_duration_ms_sum${MetricsRegistry.formatLabels(labels)} ${hist.sum.toFixed(3)}`);\n lines.push(`rebase_request_duration_ms_count${MetricsRegistry.formatLabels(labels)} ${hist.total}`);\n }\n\n for (const [name, entries] of MetricsRegistry.group(this.counters)) {\n lines.push(`# TYPE ${name} counter`);\n for (const [labelKey, value] of entries) {\n lines.push(`${name}${MetricsRegistry.formatLabels(MetricsRegistry.parseLabels(labelKey))} ${value}`);\n }\n }\n\n for (const [name, entries] of MetricsRegistry.group(this.gauges)) {\n lines.push(`# TYPE ${name} gauge`);\n for (const [labelKey, value] of entries) {\n lines.push(`${name}${MetricsRegistry.formatLabels(MetricsRegistry.parseLabels(labelKey))} ${value}`);\n }\n }\n\n const memory = process.memoryUsage();\n lines.push(\"# TYPE rebase_process_heap_bytes gauge\");\n lines.push(`rebase_process_heap_bytes ${memory.heapUsed}`);\n lines.push(\"# TYPE rebase_process_rss_bytes gauge\");\n lines.push(`rebase_process_rss_bytes ${memory.rss}`);\n\n return lines.join(\"\\n\") + \"\\n\";\n }\n}\n\n/**\n * Classify a path into the surface that served it.\n *\n * Path *shape*, never the full path: a label per entity id would create an\n * unbounded set of time series, which is the classic way to take down a\n * Prometheus. Collection slugs are bounded by the schema, so those are safe and\n * genuinely useful.\n */\nexport function classifySurface(pathname: string, basePath = \"/api\"): {\n surface: MetricSurface;\n collection?: string;\n} {\n const prefix = basePath.endsWith(\"/\") ? basePath.slice(0, -1) : basePath;\n if (!pathname.startsWith(prefix)) {\n return { surface: \"other\" };\n }\n\n const rest = pathname.slice(prefix.length).replace(/^\\/+/, \"\");\n const [head, second] = rest.split(\"/\");\n\n switch (head) {\n case \"data\":\n return { surface: \"data\",\ncollection: second || undefined };\n case \"auth\":\n return { surface: \"auth\" };\n case \"storage\":\n return { surface: \"storage\" };\n case \"functions\":\n return { surface: \"functions\",\ncollection: second || undefined };\n case \"admin\":\n return { surface: \"admin\" };\n case \"meta\":\n return { surface: \"meta\" };\n default:\n return { surface: \"other\" };\n }\n}\n\nexport interface MetricsHandle {\n registry: MetricsRegistry;\n middleware: MiddlewareHandler<HonoEnv>;\n /**\n * Restrict the `collection` label to names that actually exist.\n *\n * Called once the collections are known — the middleware has to be installed\n * before them, since it must wrap every request. Until it is called, and for\n * any name not in the set, the label is dropped: a path segment is attacker-\n * controlled, and one series per value invented is unbounded memory.\n */\n setKnownCollections(slugs: Iterable<string>): void;\n}\n\n/**\n * Build the request-timing middleware and the registry it feeds.\n *\n * Timing wraps `next()` in a `finally`, so a request that throws is still\n * counted — an endpoint that only ever fails would otherwise be invisible in\n * exactly the situation the metrics exist for.\n */\nexport function createMetricsMiddleware(basePath = \"/api\"): MetricsHandle {\n const registry = new MetricsRegistry();\n let known: Set<string> | undefined;\n\n const middleware: MiddlewareHandler<HonoEnv> = async (c, next) => {\n const started = performance.now();\n const { surface, collection } = classifySurface(new URL(c.req.url).pathname, basePath);\n\n try {\n await next();\n } finally {\n const duration = performance.now() - started;\n const labels: Record<string, string> = {\n surface,\n method: c.req.method,\n status: String(c.res?.status ?? 0)\n };\n // Only a name the schema knows about becomes a label. A request for\n // `/api/data/<random>` is a 404, and recording it by name would let\n // anyone mint unlimited time series just by sending requests.\n if (collection && known?.has(collection)) labels.collection = collection;\n registry.recordRequest(labels, duration);\n }\n };\n\n return {\n registry,\n middleware,\n setKnownCollections(slugs: Iterable<string>) {\n known = new Set(slugs);\n }\n };\n}\n\n/**\n * Mount the scrape endpoint.\n *\n * When a token is configured it is required, and compared in constant time — a\n * timing oracle on a metrics token is a small thing, but it is free to avoid.\n */\nexport function createMetricsRoutes(registry: MetricsRegistry, token?: string): Hono<HonoEnv> {\n const router = new Hono<HonoEnv>();\n\n router.get(\"/\", (c) => {\n if (token) {\n const provided = extractBearerToken(c.req.header(\"authorization\")) ?? \"\";\n if (!provided || !safeCompare(provided, token)) {\n return c.text(\"Unauthorized\", 401);\n }\n }\n return c.text(registry.render(), 200, {\n \"Content-Type\": \"text/plain; version=0.0.4; charset=utf-8\"\n });\n });\n\n return router;\n}\n","/**\n * Fetching a bundle at boot, for platforms with no init container.\n *\n * A bundle normally arrives on disk before the process starts: `rebase build`\n * writes one, a container image carries one, and on Kubernetes an init container\n * fetches one into a shared volume before the runtime container runs. All three\n * mean `runFromBundle` can assume the files are already there.\n *\n * Serverless platforms have no init container. Cloud Run starts one container\n * and nothing else, so the choice is between baking a per-tenant image — a build\n * on every deploy and an image per tenant to garbage-collect — or fetching at\n * boot. This is the second.\n *\n * ## Every start, not just the first\n *\n * The fetch has to be cheap and repeatable because it runs on *every* cold\n * start: a scale-from-zero, an instance recycled after an hour idle, a new\n * revision. That is also why the platform's bundle URL is deliberately a stable\n * endpoint rather than a signed expiring one — an instance starting for the\n * first time in three days needs the same URL to work.\n *\n * ## It refuses rather than half-unpacking\n *\n * Every failure here — a URL that 403s, a truncated download, a tarball that\n * unpacks to something without a manifest — exits non-zero before the runtime\n * boots. A partially-unpacked bundle would boot into a confusing failure much\n * later: missing collections read as an empty schema, and\n * `REBASE_MIGRATE_ON_BOOT=ensure` would then happily create nothing and report\n * success. Failing at the fetch is the only place the error still says what is\n * actually wrong.\n */\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst run = promisify(execFile);\n\n/** Where the runtime is told to fetch its bundle from. */\nexport const BUNDLE_URL_ENV = \"REBASE_BUNDLE_URL\";\n/** Bearer token for that fetch. Does not expire — see the module note. */\nexport const BUNDLE_TOKEN_ENV = \"REBASE_BUNDLE_TOKEN\";\n\nexport interface FetchBundleOptions {\n url: string;\n token?: string;\n /** Where to unpack. Defaults to a fresh directory under the OS temp dir. */\n destination?: string;\n /** Injected for tests. */\n fetchImpl?: typeof fetch;\n /** Injected for tests. */\n extract?: (tarball: string, destination: string) => Promise<void>;\n /** How long the download may take before it is abandoned. */\n timeoutMs?: number;\n}\n\n/**\n * Whether this process should fetch its bundle rather than read one from disk.\n *\n * An explicit `REBASE_BUNDLE` — a path — always wins. A platform that mounted a\n * bundle AND set a URL means somebody is mid-migration between the two, and the\n * local copy is the one that is definitely there.\n */\nexport function shouldFetchBundle(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env[BUNDLE_URL_ENV]) && !env.REBASE_BUNDLE;\n}\n\n/** Untar with the system `tar`, which every base image has. */\nasync function extractWithTar(tarball: string, destination: string): Promise<void> {\n // `-m` (do not restore mtimes) because some sandboxes reject utimes on\n // extracted files and the failure looks like a corrupt archive.\n await run(\"tar\", [\"-xzmf\", tarball, \"-C\", destination]);\n}\n\n/**\n * Download and unpack a bundle, returning the directory it landed in.\n *\n * Downloads to a file rather than streaming into `tar`, deliberately. A stream\n * that dies mid-transfer leaves `tar` having successfully extracted a prefix of\n * the archive and exiting 0 — the half-unpacked bundle this module exists to\n * refuse. Writing the whole tarball first means a truncated download is caught\n * by `tar` as a corrupt archive, which is an error.\n */\nexport async function fetchBundle(options: FetchBundleOptions): Promise<string> {\n const fetchImpl = options.fetchImpl ?? fetch;\n const extract = options.extract ?? extractWithTar;\n\n const destination = options.destination\n ?? fs.mkdtempSync(path.join(os.tmpdir(), \"rebase-bundle-\"));\n fs.mkdirSync(destination, { recursive: true });\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? 60_000);\n\n let response: Response;\n try {\n response = await fetchImpl(options.url, {\n headers: options.token ? { authorization: `Bearer ${options.token}` } : {},\n signal: controller.signal\n });\n } catch (error: unknown) {\n throw new Error(\n `Could not download the bundle from ${options.url}: ` +\n (error instanceof Error ? error.message : String(error))\n );\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n // The status is the diagnosis: 401/403 is a bad or missing token, 404 is\n // a bundle that was garbage-collected out from under a running service.\n throw new Error(\n `Could not download the bundle from ${options.url}: ${response.status} ${response.statusText}`\n );\n }\n\n const tarball = path.join(destination, \"bundle.tar.gz\");\n const body = Buffer.from(await response.arrayBuffer());\n if (body.length === 0) {\n throw new Error(`The bundle at ${options.url} is empty.`);\n }\n fs.writeFileSync(tarball, body);\n\n try {\n await extract(tarball, destination);\n } catch (error: unknown) {\n throw new Error(\n `The bundle downloaded from ${options.url} could not be unpacked ` +\n `(${body.length} bytes): ` + (error instanceof Error ? error.message : String(error))\n );\n } finally {\n // The archive is dead weight in an instance whose memory-backed temp\n // directory counts against its limit, and a Cloud Run instance's /tmp is\n // a tmpfs — leaving it there costs real memory for the life of the\n // instance.\n fs.rmSync(tarball, { force: true });\n }\n\n const root = bundleRootIn(destination);\n if (!root) {\n throw new Error(\n `The bundle downloaded from ${options.url} unpacked without a rebase-bundle.json. ` +\n `It is not a Rebase bundle, or it was truncated.`\n );\n }\n return root;\n}\n\n/**\n * Find the bundle root inside an unpacked directory.\n *\n * Tolerates one level of nesting, because whether a tarball has a top-level\n * directory depends on how it was created — `tar czf x.tgz dist-bundle` and\n * `tar czf x.tgz -C dist-bundle .` produce different shapes from the same\n * files, and both are things a build script does.\n */\nexport function bundleRootIn(directory: string): string | null {\n if (fs.existsSync(path.join(directory, \"rebase-bundle.json\"))) return directory;\n\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const nested = path.join(directory, entry.name);\n if (fs.existsSync(path.join(nested, \"rebase-bundle.json\"))) return nested;\n }\n return null;\n}\n","import path from \"path\";\nimport { createServer, type Server } from \"http\";\nimport { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { secureHeaders } from \"hono/secure-headers\";\nimport { getRequestListener } from \"@hono/node-server\";\nimport {\n DEFAULT_DATA_SOURCE_KEY,\n normalizeStorageSources,\n type DataSourceDefinition,\n type InitializedDriver,\n type StorageSourceDefinition\n} from \"@rebasepro/types\";\n\nimport { initializeRebaseBackend, type RebaseBackendInstance } from \"../init\";\nimport { loadCollectionsFromDirectory } from \"../collections/loader\";\nimport type { HonoEnv } from \"../api/types\";\nimport { logger } from \"../utils/logger\";\nimport { serveSPA } from \"../serve-spa\";\nimport { installShutdownHandlers } from \"../init/shutdown\";\nimport { listenWithPortRetry, cleanupDevPortFile } from \"../utils/dev-port\";\n\nimport { loadBootEnv, resolveCorsOrigin, resolveEnableSwagger, type RebaseBootEnv } from \"./env\";\nimport {\n BundleError,\n loadBundle,\n loadBundleConfigExports,\n loadBundleSchema,\n loadUsersCollection,\n type LoadedBundle\n} from \"./bundle\";\nimport { resolveDataSources, resolveStorageSources } from \"./sources\";\nimport { bundleResolutionRoots, initializeDataSources, probeDataSource, type InitializedDataSource } from \"./driver\";\nimport { resolveAuthOptions } from \"./options\";\nimport { createMetricsRoutes, createMetricsMiddleware } from \"../metrics\";\nimport { fetchBundle, shouldFetchBundle, BUNDLE_URL_ENV, BUNDLE_TOKEN_ENV } from \"./fetch-bundle.js\";\nimport { describeDriverSkew, readRuntimeVersion, schemaRecoveryGuidance } from \"./version-skew\";\n\n/** A running runtime, and the handle to stop it. */\nexport interface BootedRuntime {\n app: Hono<HonoEnv>;\n server: Server;\n backend: RebaseBackendInstance;\n bundle: LoadedBundle;\n env: RebaseBootEnv;\n /** The port actually bound, which in development may not be the one asked for. */\n port: number;\n dataSources: InitializedDataSource[];\n shutdown: () => Promise<void>;\n}\n\nexport interface BootOptions {\n /** Bundle directory. Defaults to `REBASE_BUNDLE` or `./dist-bundle`. */\n bundleDir?: string;\n /**\n * A bundle that has already been resolved.\n *\n * `rebase dev` passes one built from source (see `createSourceBundle`), so\n * development and production run the identical boot path rather than two\n * implementations that drift apart.\n */\n bundle?: LoadedBundle;\n /** Skip binding a port. Used by tests that drive `app.fetch` directly. */\n listen?: boolean;\n /** Install SIGTERM/SIGINT handlers. Off for tests. */\n handleSignals?: boolean;\n}\n\n/**\n * Boot a Rebase runtime from a built bundle.\n *\n * This is the entrypoint the official container image runs, and it is the same\n * code path a self-hosted deployment uses — there is no separate \"platform\"\n * runtime. Everything it does was previously the responsibility of a\n * hand-written `backend/src/index.ts` in every project: wiring CORS and security\n * headers, opening database connections, resolving storage, mounting health and\n * metrics, serving the client bundle, and shutting all of it down cleanly.\n *\n * Moving it here is what makes a project's *code* separable from the *engine*\n * that runs it: the bundle can then be handed to a newer runtime without being\n * rebuilt, which is the precondition for patching a fleet.\n */\nexport async function bootFromBundle(options: BootOptions = {}): Promise<BootedRuntime> {\n // Serverless platforms have no init container, so there may be nothing on\n // disk yet. `REBASE_BUNDLE_URL` means \"download it first\"; an explicit\n // bundle path always wins, because a platform that mounted one AND set a URL\n // is mid-migration between the two and the local copy is definitely there.\n //\n // This runs on EVERY cold start — a scale-from-zero, an instance recycled\n // after an hour idle — which is why the URL it is given is a stable endpoint\n // rather than a signed one that would have expired.\n const fetchedDir = !options.bundleDir && !options.bundle && shouldFetchBundle()\n ? await fetchBundle({\n url: process.env[BUNDLE_URL_ENV]!,\n token: process.env[BUNDLE_TOKEN_ENV]\n })\n : undefined;\n\n const bundleDir = options.bundleDir\n || fetchedDir\n || process.env.REBASE_BUNDLE\n || path.resolve(process.cwd(), \"dist-bundle\");\n\n // The bundle is located before the environment is validated, because\n // pointing at the wrong directory is the likeliest first-run mistake, and\n // \"no bundle here, build one\" is far more useful than being told\n // DATABASE_URL is missing — which it also is, but only because nothing has\n // been set up yet.\n const bundle = options.bundle ?? loadBundle(bundleDir);\n\n // Where dev-only state (the port file, the MCP discovery file) lives. A\n // source boot runs from the project root; a built bundle sits inside it.\n const devRoot = process.env.REBASE_DEV_PROJECT_ROOT || process.cwd();\n logger.info(\"Loaded bundle\", {\n app: bundle.manifest.app,\n kind: bundle.manifest.kind,\n schemaVersion: bundle.manifest.schemaVersion,\n builtAgainst: bundle.manifest.runtime?.builtAgainst\n });\n\n // A `static` bundle is a built SPA and nothing else — no collections, no data\n // sources, no database. It runs on this same image so a project's frontend\n // and admin apps are just more bundles, deployed and scaled independently of\n // the backend. Handled BEFORE `loadBootEnv`, which requires DATABASE_URL and\n // JWT_SECRET — a static app needs neither, and demanding them would be the\n // one thing that could stop a folder of assets from being served.\n if (bundle.manifest.kind === \"static\") {\n return bootStaticApp(bundle, devRoot, options);\n }\n\n const env = loadBootEnv();\n const isProduction = env.NODE_ENV === \"production\";\n\n // ── Declarations ─────────────────────────────────────────────────────────\n const configExports = await loadBundleConfigExports(bundle);\n const dataSourceDefs: DataSourceDefinition[] | undefined = configExports.dataSources;\n // `rebase.json` (recorded in the manifest) is authoritative; config code may\n // add sources it does not mention — a `direct`-transport bucket reached by a\n // provider SDK has no reason to appear in a document the platform reads for\n // provisioning. Merging rather than choosing is what keeps the console's view\n // and the tenant's reality the same list. A bundle built before the manifest\n // carried sources falls through to the config exports alone.\n const declaredStorage = normalizeStorageSources(\n bundle.manifest.storage?.sources,\n configExports.storageSources\n );\n const storageSourceDefs: StorageSourceDefinition[] | undefined =\n declaredStorage.length > 0 ? declaredStorage : undefined;\n\n // ── Databases ────────────────────────────────────────────────────────────\n const resolvedSources = resolveDataSources(process.env, dataSourceDefs);\n const schema = await loadBundleSchema(bundle);\n const driverRoots = bundleResolutionRoots(bundle.dir);\n const dataSources = await initializeDataSources(resolvedSources, schema, driverRoots);\n warnOnDriverSkew(dataSources, readRuntimeVersion(driverRoots));\n\n // ── HTTP ─────────────────────────────────────────────────────────────────\n const app = new Hono<HonoEnv>();\n\n app.use(\"/*\", cors({\n origin: resolveCorsOrigin(env),\n credentials: true\n }));\n app.use(\"/*\", secureHeaders({\n // An API serves assets and tokens to origins other than its own, so the\n // browser defaults are wrong here in two specific ways:\n //\n // - `crossOriginResourcePolicy` defaults to `same-origin`, which blocks a\n // frontend on another origin from loading anything this server serves.\n // - `crossOriginOpenerPolicy` defaults to `same-origin`, which severs\n // `window.opener` and breaks the OAuth popup sign-in that\n // `resolveAuthOptions` configures whenever GOOGLE_CLIENT_ID is set.\n //\n // Cross-origin access is still governed by CORS; these only stop the\n // browser from refusing before CORS is consulted.\n crossOriginResourcePolicy: \"cross-origin\",\n crossOriginOpenerPolicy: \"same-origin-allow-popups\"\n }));\n\n // Classified against the configured base path, not a hardcoded \"/api\" — a\n // project on a different base path would otherwise label every request\n // \"other\" and the per-surface breakdown would silently be empty.\n const metrics = env.REBASE_METRICS\n ? createMetricsMiddleware(env.REBASE_BASE_PATH)\n : undefined;\n if (metrics) {\n app.use(\"/*\", metrics.middleware);\n }\n\n const server = createServer(getRequestListener(app.fetch));\n\n // ── Backend ──────────────────────────────────────────────────────────────\n const usersCollection = await loadUsersCollection(bundle);\n const storage = resolveStorageSources(\n process.env,\n storageSourceDefs,\n path.join(bundle.dir, \"uploads\")\n );\n\n // ── Schema ───────────────────────────────────────────────────────────────\n //\n // Create any collection tables the database is missing, before the backend\n // starts serving. `initializeRebaseBackend` ensures AUTH tables; nothing\n // ensured collection tables, so a runtime booted against a fresh database\n // came up with working sign-in and a 500 on every `/api/data/*` route — the\n // state every managed tenant would have launched in.\n //\n // Additive only: the driver may create missing tables, columns and enum\n // types, and may never drop or rewrite. Destructive changes stay a\n // deliberate migration, because this runs unattended with nobody reading a\n // diff. `REBASE_MIGRATE_ON_BOOT=none` opts out entirely for a deployment\n // that manages its own schema.\n await ensureCollectionSchema(bundle, dataSources, env);\n\n const backend = await initializeRebaseBackend({\n server,\n app,\n basePath: env.REBASE_BASE_PATH,\n collectionsDir: bundle.collectionsDir,\n functionsDir: bundle.functionsDir,\n cronsDir: bundle.cronsDir,\n bootstrappers: dataSources.map(s => s.bootstrapper),\n dataSources: dataSourceDefs,\n storage,\n storageSources: storageSourceDefs,\n // Per-object access control comes from the project's own code — no\n // environment variable can express \"this user may read this key\".\n storageAuthorize: configExports.storageAuthorize,\n storagePublicRead: env.STORAGE_PUBLIC_READ,\n storageInsecureAllowAnyAuthenticated: env.STORAGE_ALLOW_ANY_AUTHENTICATED,\n callbacks: configExports.callbacks,\n auth: resolveAuthOptions(env, usersCollection),\n history: env.REBASE_HISTORY,\n enableSwagger: resolveEnableSwagger(env),\n compression: env.REBASE_COMPRESSION,\n maxBodySize: env.REBASE_MAX_BODY_SIZE,\n logging: env.LOG_LEVEL ? { level: env.LOG_LEVEL } : undefined,\n // CORS is installed above, before this call.\n corsHandled: true,\n // Published by the contract endpoint, so a client generated in another\n // repository can tell whether it is built against this schema.\n // Empty for a source boot: nothing was built, so the runtime computes a\n // version from the live collections instead of quoting one.\n schemaVersion: bundle.manifest.schemaVersion || undefined,\n runtimeVersion: bundle.manifest.runtime?.builtAgainst,\n // The schema editor rewrites collection *source* files. A bundle holds\n // compiled output, so there is nothing it could meaningfully edit —\n // and a running deployment is the last place that should be possible.\n schemaEditor: false\n });\n\n // ── RLS policies ───────────────────────────────────────────────────────────\n //\n // Now that the backend is up — auth tables and the `auth.*` helper functions\n // exist, the restricted user role is provisioned, and the collection tables\n // were created above — apply the collections' row-level-security policies.\n // Tables without them are not servable: authenticated requests run as a\n // restricted role, so a read with no policy returns nothing (a public\n // collection answers 401) and a write with no policy is denied. This is the\n // second half of what `db push` does, and the half a managed tenant could\n // not reach any other way. Ordered after `initializeRebaseBackend` on\n // purpose: `CREATE POLICY` validates the `auth.uid()` functions it references\n // exist, and those are created during auth initialization. Same\n // `REBASE_MIGRATE_ON_BOOT=none` opt-out as the table creation above.\n await ensureCollectionPolicies(bundle, dataSources, env);\n\n // Restrict metric labels to collections that exist, now that they do.\n metrics?.setKnownCollections(\n backend.collectionRegistry.getCollections()\n .map(collection => collection.slug)\n .filter((slug): slug is string => Boolean(slug))\n );\n\n // ── Health ───────────────────────────────────────────────────────────────\n // Not part of `initializeRebaseBackend` because it sits outside `basePath`:\n // orchestrators probe `/health`, not `/api/health`.\n app.get(\"/health\", async (c) => {\n const result = await backend.healthCheck();\n\n // `backend.healthCheck()` probes the default driver only. With several\n // databases configured, that would report a healthy server while every\n // collection routed to an unreachable secondary returns 500 — an\n // orchestrator would keep sending it traffic.\n const secondaries = await Promise.all(\n dataSources\n .filter(source => source.key !== DEFAULT_DATA_SOURCE_KEY)\n .map(async source => ({\n key: source.key,\n result: await probeDataSource(source)\n }))\n );\n\n const unhealthy = secondaries\n .filter(source => source.result && !source.result.healthy)\n .map(source => ({ key: source.key,\n error: source.result?.error }));\n const healthy = result.healthy && unhealthy.length === 0;\n\n return c.json({\n status: healthy ? \"ok\" : \"degraded\",\n latencyMs: result.latencyMs,\n ...(result.details ? { details: result.details } : {}),\n ...(unhealthy.length > 0 ? { dataSources: unhealthy } : {})\n }, healthy ? 200 : 503);\n });\n\n // Liveness vs readiness: `/health` touches the database, so a database blip\n // would make an orchestrator kill an otherwise healthy process. `/livez`\n // answers \"is this process running\", which is the question a liveness probe\n // is actually asking.\n app.get(\"/livez\", (c) => c.json({ status: \"ok\" }));\n\n // ── Metrics ──────────────────────────────────────────────────────────────\n if (metrics) {\n if (!env.REBASE_METRICS_TOKEN) {\n logger.warn(\n \"Metrics are enabled without REBASE_METRICS_TOKEN — /metrics is readable by anyone \" +\n \"who can reach this port. Set a token, or keep the port on a private network.\"\n );\n }\n app.route(\"/metrics\", createMetricsRoutes(metrics.registry, env.REBASE_METRICS_TOKEN));\n }\n\n // ── Static assets ────────────────────────────────────────────────────────\n // Mounted last: each app's `serveSPA` ends in a catch-all under its own\n // prefix, so anything registered after it would never be reached.\n //\n // `bundle.staticApps` arrives longest-path-first, which puts the \"/\"-rooted\n // app last. Ordering alone is not enough, though — every app also excludes\n // its siblings, or a miss under \"/admin\" would be answered with the site's\n // index.html at the admin's URL.\n if (env.REBASE_SERVE_STATIC) {\n for (const staticApp of bundle.staticApps) {\n const siblings = bundle.staticApps\n .filter(other => other !== staticApp)\n .map(other => other.path)\n .filter(other => other !== \"/\");\n logger.info(\"Serving static assets\", { path: staticApp.dir,\nat: staticApp.path });\n serveSPA(app, {\n frontendPath: staticApp.dir,\n basePath: staticApp.path,\n apiBasePath: env.REBASE_BASE_PATH,\n excludePaths: [\"/health\", \"/livez\", \"/metrics\", ...siblings],\n spa: staticApp.spa\n });\n }\n }\n\n // ── Listen ───────────────────────────────────────────────────────────────\n let port = env.PORT;\n if (options.listen !== false) {\n if (isProduction) {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(env.PORT, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n });\n logger.info(`Rebase runtime listening on port ${env.PORT}`);\n } else {\n port = await listenWithPortRetry(server, env.PORT, {\n portFileDir: devRoot,\n serviceKey: env.REBASE_SERVICE_KEY\n });\n // Phrased to match what `rebase dev` watches for before it starts\n // the frontend. One convention, shared by the template entrypoint\n // this replaced — changing the wording here silently breaks dev.\n logger.info(`Server running at http://localhost:${port}`);\n }\n }\n\n const closeConnections = async (): Promise<void> => {\n await Promise.allSettled(\n dataSources.map(source => source.connection.pool?.end())\n );\n if (!isProduction) cleanupDevPortFile(devRoot);\n };\n\n if (options.handleSignals !== false) {\n installShutdownHandlers(backend, { onCleanup: closeConnections });\n // The graceful path is not the only way a dev server ends. Without this,\n // a crash or a force-exit leaves `.rebase-dev-port` behind and the next\n // run inherits a port nothing is listening on.\n if (!isProduction) {\n process.on(\"exit\", () => cleanupDevPortFile(devRoot));\n }\n }\n\n return {\n app,\n server,\n backend,\n bundle,\n env,\n port,\n dataSources,\n shutdown: async () => {\n await backend.shutdown();\n await closeConnections();\n }\n };\n}\n\n/**\n * Boot a `static` bundle: serve its built SPA and nothing else.\n *\n * No database, no data sources, no backend — a static app is a folder of assets\n * plus an `index.html`. Kept deliberately minimal so it is cheap to run and\n * cannot fail for a reason a static site never should (a database blip, a\n * missing collection). Exposes the same `/livez` and `/health` the orchestrator\n * probes, so a static app is provisioned by the exact same deployment path as a\n * backend — the only difference is what the bundle contains.\n */\nasync function bootStaticApp(\n bundle: LoadedBundle,\n devRoot: string,\n options: BootOptions\n): Promise<BootedRuntime> {\n if (bundle.staticApps.length === 0) {\n throw new BundleError(\n \"A static bundle declares no assets to serve.\",\n \"Its manifest has `kind: \\\"static\\\"` but no `entry.static` — rebuild the app with `rebase build`.\"\n );\n }\n\n // Read only the handful of variables a static server uses, directly — the\n // full env schema requires a database and a JWT secret, which this path\n // deliberately does not.\n const isProduction = process.env.NODE_ENV === \"production\";\n const requestedPort = Number(process.env.PORT ?? \"3001\") || 3001;\n const basePath = process.env.REBASE_BASE_PATH || \"/api\";\n const metricsEnabled = process.env.REBASE_METRICS === \"true\";\n const metricsToken = process.env.REBASE_METRICS_TOKEN;\n\n const app = new Hono<HonoEnv>();\n\n // Assets must be loadable from other origins (a custom domain, the console),\n // so the same cross-origin relaxation the API path makes applies here.\n app.use(\"/*\", secureHeaders({\n crossOriginResourcePolicy: \"cross-origin\",\n crossOriginOpenerPolicy: \"same-origin-allow-popups\"\n }));\n\n const metrics = metricsEnabled ? createMetricsMiddleware(basePath) : undefined;\n if (metrics) app.use(\"/*\", metrics.middleware);\n\n const server = createServer(getRequestListener(app.fetch));\n\n // Liveness and readiness are the same for a static app: it is ready the\n // moment it can serve, and there is no database to make readiness lie.\n app.get(\"/livez\", (c) => c.json({ status: \"ok\" }));\n app.get(\"/health\", (c) => c.json({ status: \"ok\", latencyMs: 0 }));\n\n if (metrics) {\n app.route(\"/metrics\", createMetricsRoutes(metrics.registry, metricsToken));\n }\n\n // Mounted last: each app's serveSPA ends in a catch-all under its prefix.\n // Same ordering and sibling-exclusion rules as the backend path above.\n for (const staticApp of bundle.staticApps) {\n const siblings = bundle.staticApps\n .filter(other => other !== staticApp)\n .map(other => other.path)\n .filter(other => other !== \"/\");\n logger.info(\"Serving static app\", {\n app: bundle.manifest.app,\n path: staticApp.dir,\n at: staticApp.path\n });\n serveSPA(app, {\n frontendPath: staticApp.dir,\n basePath: staticApp.path,\n apiBasePath: basePath,\n excludePaths: [\"/health\", \"/livez\", \"/metrics\", ...siblings],\n spa: staticApp.spa\n });\n }\n\n let port = requestedPort;\n if (options.listen !== false) {\n if (isProduction) {\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(requestedPort, () => {\n server.removeListener(\"error\", reject);\n resolve();\n });\n });\n logger.info(`Rebase static runtime listening on port ${requestedPort}`);\n } else {\n port = await listenWithPortRetry(server, requestedPort, { portFileDir: devRoot });\n logger.info(`Server running at http://localhost:${port}`);\n }\n }\n\n // No backend and no data sources exist for a static app; the stub keeps the\n // returned shape uniform so callers (and shutdown) do not special-case it.\n const noopBackend = { shutdown: async () => {} } as unknown as RebaseBackendInstance;\n\n if (options.handleSignals !== false) {\n installShutdownHandlers(noopBackend, {\n onCleanup: async () => { if (!isProduction) cleanupDevPortFile(devRoot); }\n });\n if (!isProduction) process.on(\"exit\", () => cleanupDevPortFile(devRoot));\n }\n\n // A static app runs on a deliberately reduced env — only the fields it read\n // above are meaningful. Surfaced for callers/tests without pretending the\n // database-shaped fields exist.\n const env = {\n NODE_ENV: (process.env.NODE_ENV ?? \"development\"),\n PORT: requestedPort,\n REBASE_BASE_PATH: basePath,\n REBASE_METRICS: metricsEnabled,\n REBASE_METRICS_TOKEN: metricsToken\n } as unknown as RebaseBootEnv;\n\n return {\n app,\n server,\n backend: noopBackend,\n bundle,\n env,\n port,\n dataSources: [],\n shutdown: async () => {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n if (!isProduction) cleanupDevPortFile(devRoot);\n }\n };\n}\n\n/**\n * Boot and keep running, reporting failures the way a container should.\n *\n * A `BundleError` is a configuration problem with a known fix, so it prints the\n * message and its hint without a stack trace — the stack is noise when the\n * answer is \"set DATABASE_URL\". Anything else keeps its stack, because it is a\n * bug and the trace is the point.\n */\nexport async function runFromBundle(options: BootOptions = {}): Promise<BootedRuntime> {\n try {\n return await bootFromBundle(options);\n } catch (err) {\n if (err instanceof BundleError) {\n logger.error(err.message);\n if (err.hint) logger.error(err.hint);\n } else {\n logger.error(\"Failed to start the Rebase runtime\", {\n error: err instanceof Error ? err : new Error(String(err))\n });\n }\n process.exit(1);\n }\n}\n\n\n/**\n * Say so, once per boot, when a data source's driver is older than this runtime.\n *\n * The check exists because of how a managed deployment is assembled: the image\n * supplies `@rebasepro/server` (the entrypoint symlinks it over the bundle's\n * copy) while every driver comes from the bundle's own `deps.declared`, pinned\n * by the project's package.json. So the platform can ship a fix, roll every\n * tenant onto the new image, and still have none of them running the fixed\n * driver. Nothing detected that before this: the halves simply disagreed in\n * silence until some capability turned out to be missing three layers down.\n *\n * A warning rather than a refusal. Old drivers are usually fine — the pairing is\n * supported, and a boot that dies on version arithmetic would be a far worse\n * failure than the drift it is guarding against. This only has to make the skew\n * *visible*, so that the next person reading the log starts from the right\n * question.\n */\nexport function warnOnDriverSkew(\n dataSources: InitializedDataSource[],\n runtimeVersion: string | undefined\n): void {\n if (!runtimeVersion) return;\n\n for (const source of dataSources) {\n const skew = describeDriverSkew(source.driverVersion, runtimeVersion);\n if (!skew.stale) continue;\n logger.warn(\n `Driver version skew on data source \"${source.key}\": ` +\n `\"${source.driverPackage}\" is at ${source.driverVersion}, this runtime is ${runtimeVersion}. ` +\n \"A driver is installed from your bundle's dependencies, NOT supplied by the platform image, \" +\n \"so a newer runtime does not update it. Capabilities added after \" +\n `${source.driverVersion} are unavailable to this deployment — bump ` +\n `\"${source.driverPackage}\" in your project's package.json and redeploy.`\n );\n }\n}\n\n/**\n * Bring the database's collection tables up to date before serving.\n *\n * Delegates to whichever driver bootstrapped the default data source; a driver\n * without `ensureCollectionSchema` (a schemaless one, or an older build) skips\n * rather than failing, which is why this cannot break an existing deployment.\n *\n * Every path out of here says why, at info or louder. Guaranteeing the tables\n * exist is this function's entire job, so \"it declined, and said nothing\" is the\n * one outcome it must never produce: a deployment that skips comes up answering\n * sign-in and 500ing every `/api/data/*` route, and the operator's only evidence\n * is what these lines print. Silence here has already sent one investigation\n * chasing a stale runtime image that was not stale.\n *\n * Failure is fatal on purpose. Booting anyway would produce exactly the state\n * this exists to prevent — an app that answers sign-in and 500s every data\n * request — and a crash-looping pod with the DDL error in its logs is a far\n * better signal than a running one that silently cannot serve.\n */\nexport async function ensureCollectionSchema(\n bundle: LoadedBundle,\n dataSources: InitializedDataSource[],\n env: RebaseBootEnv\n): Promise<void> {\n // `info` is for the bundle shapes with legitimately nothing to create;\n // `warn` is for a bundle that asked for collection tables and is not getting\n // them. A backend carrying a config package is the shape that expects\n // tables, so every stop after that point is a real problem worth raising.\n const skip = (reason: string, level: \"info\" | \"warn\" = \"info\"): void => {\n logger[level](`Collection schema: skipped — ${reason}`);\n };\n\n const mode = env.REBASE_MIGRATE_ON_BOOT || \"ensure\";\n if (mode === \"none\") {\n skip(\"REBASE_MIGRATE_ON_BOOT=none, leaving the database schema untouched.\");\n return;\n }\n // A bundle without a config package introspects its collections FROM the\n // database, so there is nothing to create; a `static` bundle has no database\n // at all. Both conditions matter: gating on `kind` alone would push a\n // schema into an existing database that a project only meant to read.\n if (bundle.manifest.kind !== \"backend\") {\n skip(`this bundle's kind is \"${bundle.manifest.kind}\", which serves no database.`);\n return;\n }\n if (!bundle.manifest.entry?.config) {\n skip(\"this bundle declares no config package, so its collections are read from the database rather than from code.\");\n return;\n }\n // Reachable only when the config package exists but carries no collections\n // directory — a build that produced a manifest the runtime cannot act on,\n // which looks identical from the outside to a database that was never\n // migrated. Name the path so the two are told apart from the log alone.\n if (!bundle.collectionsDir) {\n skip(\n `this bundle declares a config package at \"${bundle.manifest.entry.config}\", but no collections directory resolved inside it. ` +\n \"Rebuild with `rebase build` and check the manifest's `entry.collections`.\",\n \"warn\"\n );\n return;\n }\n\n const primary = dataSources[0];\n if (!primary) {\n skip(\"no data source was initialized for this runtime.\", \"warn\");\n return;\n }\n if (!primary.bootstrapper.ensureCollectionSchema) {\n // What is missing is the method on the ADAPTER — the only object boot\n // ever sees — which is not the same as the driver package lacking the\n // code. Three unrelated causes collapse into this one symptom: a\n // schemaless driver, a driver too old to have it, and a driver that\n // implements it on a class the adapter never forwards. Only the middle\n // one is a version problem, so saying \"the driver does not implement\"\n // and naming versions points at the wrong suspect two times in three —\n // it sent one investigation after driver and runtime releases that were\n // both fine while a wrapper silently dropped the method in between.\n const skew = describeDriverSkew(primary.driverVersion, readRuntimeVersion(bundleResolutionRoots(bundle.dir)));\n skip(\n `the adapter from \"${primary.driverPackage}\" (engine \"${primary.engine}\") does not expose collection-table creation. ` +\n (skew.detail ? `${skew.detail} ` : \"\") +\n \"The driver package may well implement it on a class the adapter does not forward, so check the adapter's shape before blaming its version. \" +\n \"Collection tables will NOT be created, so every /api/data route will fail on a missing relation.\\n\" +\n schemaRecoveryGuidance({ staleDriver: skew.stale }),\n \"warn\"\n );\n return;\n }\n\n const collections = await loadCollectionsFromDirectory(bundle.collectionsDir);\n if (collections.length === 0) {\n skip(`no collections were loaded from \"${bundle.collectionsDir}\".`, \"warn\");\n return;\n }\n\n const { applied } = await primary.bootstrapper.ensureCollectionSchema(\n collections,\n preInitDriverResult(primary),\n message => logger.info(`schema: ${message}`)\n );\n logger.info(\n applied > 0\n ? `Applied ${applied} additive schema change(s) before boot.`\n : \"Collection schema is up to date.\"\n );\n}\n\n/**\n * The `InitializedDriver` to hand a bootstrapper before any driver exists.\n *\n * Both schema hooks are declared to take the result of `initializeDriver`, but\n * they deliberately run *before* it: the tables have to exist before the driver\n * introspects them and registers collections. So there is no real result to\n * pass, and the field the hooks actually read is `internals` — the driver's own\n * opaque handle, which at this point is exactly the connection the coordinator\n * just opened (`{ db, pool }`, where `db` is the drizzle instance).\n *\n * Wrapping it matters: the connection passed *bare* type-checks through any cast\n * and then reads `undefined.db` inside the driver, which surfaces as a boot\n * crash — `TypeError: Cannot read properties of undefined (reading 'db')` — on\n * every project whose driver implements these hooks. The cast is narrowed to the\n * one field a pre-init result cannot honestly supply, rather than `as never`\n * blanketing the whole argument.\n */\nfunction preInitDriverResult(source: InitializedDataSource): InitializedDriver {\n return { internals: source.connection } as unknown as InitializedDriver;\n}\n\n/**\n * Apply the project's RLS policies before serving — the companion to\n * {@link ensureCollectionSchema}, which creates the tables this makes servable.\n *\n * Runs after `initializeRebaseBackend`, not alongside table creation: the\n * generated policies call the `auth.*` helper functions, and `CREATE POLICY`\n * validates those exist, so this cannot run before auth is initialized. The\n * gate conditions mirror `ensureCollectionSchema` (mode, bundle shape, driver\n * support) — and because that function already ran and explained any skip on\n * this same boot, the benign gates here return quietly rather than logging the\n * same reason twice. The one thing it does say out loud is a driver that\n * created tables but cannot apply policies: that is the difference between a\n * served collection and a 401, and it must not pass in silence.\n */\nexport async function ensureCollectionPolicies(\n bundle: LoadedBundle,\n dataSources: InitializedDataSource[],\n env: RebaseBootEnv\n): Promise<void> {\n const mode = env.REBASE_MIGRATE_ON_BOOT || \"ensure\";\n if (mode === \"none\") return;\n if (bundle.manifest.kind !== \"backend\") return;\n if (!bundle.manifest.entry?.config) return;\n if (!bundle.collectionsDir) return;\n\n const primary = dataSources[0];\n if (!primary) return;\n if (!primary.bootstrapper.ensureCollectionPolicies) {\n // The tables may exist (ensureCollectionSchema ran) but their RLS does\n // not, so every user-context read is denied. Name it: a silent skip here\n // reads from outside the pod as \"the database has no data\".\n const skew = describeDriverSkew(primary.driverVersion, readRuntimeVersion(bundleResolutionRoots(bundle.dir)));\n logger.warn(\n `Collection policies: skipped — the \"${primary.driverPackage}\" driver (engine \"${primary.engine}\") ` +\n \"does not apply RLS policies at boot. \" +\n (skew.detail ? `${skew.detail} ` : \"\") +\n \"Collections will deny reads until policies are applied.\\n\" +\n schemaRecoveryGuidance({ staleDriver: skew.stale })\n );\n return;\n }\n\n const collections = await loadCollectionsFromDirectory(bundle.collectionsDir);\n if (collections.length === 0) return;\n\n const { applied } = await primary.bootstrapper.ensureCollectionPolicies(\n collections,\n preInitDriverResult(primary),\n message => logger.info(`policies: ${message}`)\n );\n logger.info(\n applied > 0\n ? `Applied ${applied} RLS policy statement(s) before serving.`\n : \"RLS policies are up to date.\"\n );\n}\n"],"x_google_ignoreList":[12,13],"mappings":"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"}
|