@rebasepro/server 0.16.0 → 0.16.1-canary.g0d7af95
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/{GCSStorageController-BEmDYFKc.js → GCSStorageController-Bl7nmhdv.js} +7 -6
- package/dist/{GCSStorageController-BEmDYFKc.js.map → GCSStorageController-Bl7nmhdv.js.map} +1 -1
- package/dist/{S3StorageController-B2EDXXMH.js → S3StorageController-CWvvrRpF.js} +7 -6
- package/dist/{S3StorageController-B2EDXXMH.js.map → S3StorageController-CWvvrRpF.js.map} +1 -1
- package/dist/{admin_block-DLILvzle.js → admin_block-BeypnEfb.js} +6 -6
- package/dist/admin_block-BeypnEfb.js.map +1 -0
- package/dist/api/ast-schema-editor.d.ts +23 -0
- package/dist/api/contract-routes.d.ts +1 -1
- package/dist/api/errors.d.ts +1 -1
- package/dist/api/index.d.ts +3 -3
- package/dist/api/live-schema-routes.d.ts +122 -0
- package/dist/api/logs-routes.d.ts +1 -1
- package/dist/api/mount.d.ts +41 -0
- package/dist/api/rest/api-generator.d.ts +2 -2
- package/dist/api/rest/index.d.ts +1 -1
- package/dist/api/rest/query-parser.d.ts +1 -1
- package/dist/api/schema-editor-routes.d.ts +1 -1
- package/dist/api/types.d.ts +12 -4
- package/dist/{schema-editor-routes-CV9k0w3G.js → ast-schema-editor-BrarYZCq.js} +37 -45
- package/dist/ast-schema-editor-BrarYZCq.js.map +1 -0
- package/dist/auth/adapter-middleware.d.ts +2 -2
- package/dist/auth/admin-roles-route.d.ts +2 -2
- package/dist/auth/admin-user-ops.d.ts +3 -3
- package/dist/auth/admin-users-route.d.ts +4 -6
- package/dist/auth/api-keys/api-key-middleware.d.ts +2 -2
- package/dist/auth/api-keys/api-key-permission-guard.d.ts +1 -1
- package/dist/auth/api-keys/api-key-routes.d.ts +2 -2
- package/dist/auth/api-keys/api-key-store.d.ts +1 -1
- package/dist/auth/api-keys/index.d.ts +9 -9
- package/dist/auth/apple-oauth.d.ts +2 -2
- package/dist/auth/auth-hooks.d.ts +4 -4
- package/dist/auth/bitbucket-oauth.d.ts +2 -2
- package/dist/auth/builtin-auth-adapter.d.ts +8 -4
- package/dist/auth/capabilities.d.ts +51 -0
- package/dist/auth/captcha.d.ts +86 -0
- package/dist/auth/cookie-utils.d.ts +2 -2
- package/dist/auth/discord-oauth.d.ts +2 -2
- package/dist/auth/facebook-oauth.d.ts +2 -2
- package/dist/auth/github-oauth.d.ts +2 -2
- package/dist/auth/gitlab-oauth.d.ts +2 -2
- package/dist/auth/google-oauth.d.ts +1 -1
- package/dist/auth/index.d.ts +58 -54
- package/dist/auth/jwks-routes.d.ts +1 -1
- package/dist/auth/jwt.d.ts +1 -1
- package/dist/auth/linkedin-oauth.d.ts +2 -2
- package/dist/auth/magic-link-routes.d.ts +10 -3
- package/dist/auth/mfa-gate.d.ts +1 -1
- package/dist/auth/mfa-routes.d.ts +3 -3
- package/dist/auth/microsoft-oauth.d.ts +2 -2
- package/dist/auth/middleware.d.ts +6 -7
- package/dist/auth/otp-routes.d.ts +89 -0
- package/dist/auth/rate-limiter.d.ts +2 -2
- package/dist/auth/require-auth.d.ts +1 -1
- package/dist/auth/reset-password-admin.d.ts +4 -4
- package/dist/auth/routes.d.ts +18 -10
- package/dist/auth/session-routes.d.ts +3 -3
- package/dist/auth/slack-oauth.d.ts +2 -2
- package/dist/auth/spotify-oauth.d.ts +2 -2
- package/dist/auth/token-revocation.d.ts +2 -2
- package/dist/auth/twitter-oauth.d.ts +2 -2
- package/dist/{auth-5Et5mnUA.js → auth-DU-nUjPp.js} +604 -4376
- package/dist/auth-DU-nUjPp.js.map +1 -0
- package/dist/backup/backup-common.d.ts +1 -1
- package/dist/backup/backup-routes.d.ts +3 -3
- package/dist/backup/index.d.ts +3 -3
- package/dist/{backup-C6ljYVTp.js → backup-CRdZkA6c.js} +7 -6
- package/dist/{backup-C6ljYVTp.js.map → backup-CRdZkA6c.js.map} +1 -1
- package/dist/boot/boot.d.ts +5 -5
- package/dist/boot/bundle.d.ts +10 -1
- package/dist/boot/driver.d.ts +1 -1
- package/dist/boot/env.d.ts +28 -1
- package/dist/boot/fetch-bundle.d.ts +144 -1
- package/dist/boot/options.d.ts +30 -6
- package/dist/boot/resource-adapters.d.ts +31 -0
- package/dist/boot/resource-loading.d.ts +10 -0
- package/dist/boot/role.d.ts +3 -2
- package/dist/boot/sources.d.ts +8 -2
- package/dist/boot/version-skew.d.ts +1 -1
- package/dist/collections/BackendCollectionRegistry.d.ts +1 -1
- package/dist/collections/loader.d.ts +1 -1
- package/dist/collections/validate-config.d.ts +13 -0
- package/dist/{contract-routes-DZ-LBpSL.js → contract-routes-D8TvxPLo.js} +8 -7
- package/dist/contract-routes-D8TvxPLo.js.map +1 -0
- package/dist/cron/cron-routes.d.ts +2 -2
- package/dist/cron/cron-scheduler.d.ts +3 -3
- package/dist/cron/index.d.ts +8 -8
- package/dist/{cron-loader-YhhQeVBM.js → cron-loader-d9WMFENB.js} +8 -7
- package/dist/{cron-loader-YhhQeVBM.js.map → cron-loader-d9WMFENB.js.map} +1 -1
- package/dist/{cron-routes-maM_RlUu.js → cron-routes-BsukhMGm.js} +9 -8
- package/dist/cron-routes-BsukhMGm.js.map +1 -0
- package/dist/{cron-scheduler-DIpYBmZP.js → cron-scheduler-BB82dWuU.js} +9 -9
- package/dist/cron-scheduler-BB82dWuU.js.map +1 -0
- package/dist/{cron-store-DfH_4Cd9.js → cron-store-CbFfQhbg.js} +11 -9
- package/dist/{cron-store-DfH_4Cd9.js.map → cron-store-CbFfQhbg.js.map} +1 -1
- package/dist/ddl-bootstrap-5YZCZ8qk.js +146 -0
- package/dist/ddl-bootstrap-5YZCZ8qk.js.map +1 -0
- package/dist/deploy/pod-contract.d.ts +139 -0
- package/dist/dev-secrets.d.ts +52 -0
- package/dist/{dynamic-import-Dvh-K5fl.js → dynamic-import-X40pTZUQ.js} +5 -4
- package/dist/{dynamic-import-Dvh-K5fl.js.map → dynamic-import-X40pTZUQ.js.map} +1 -1
- package/dist/email/dev-sink.d.ts +88 -0
- package/dist/email/index.d.ts +9 -7
- package/dist/email/link-base.d.ts +1 -1
- package/dist/email/smtp-email-service.d.ts +2 -2
- package/dist/email/templates.d.ts +12 -0
- package/dist/email/types.d.ts +18 -6
- package/dist/env.d.ts +1 -1
- package/dist/{errors-EBYiaJ2E.js → errors-DBwpj9N8.js} +8 -7
- package/dist/errors-DBwpj9N8.js.map +1 -0
- package/dist/{function-loader-DDS1v7YX.js → function-loader-LLdmBFoL.js} +9 -8
- package/dist/{function-loader-DDS1v7YX.js.map → function-loader-LLdmBFoL.js.map} +1 -1
- package/dist/{function-routes-Btcez1T-.js → function-routes-ClT6UQpD.js} +8 -7
- package/dist/function-routes-ClT6UQpD.js.map +1 -0
- package/dist/functions/context.d.ts +141 -0
- package/dist/functions/define-function.d.ts +1 -1
- package/dist/functions/function-routes.d.ts +9 -3
- package/dist/functions/guards.d.ts +76 -0
- package/dist/functions/index.d.ts +96 -5
- package/dist/functions/index.js +919 -0
- package/dist/functions/index.js.map +1 -0
- package/dist/functions/internal.d.ts +26 -0
- package/dist/functions/proxy.d.ts +1 -1
- package/dist/functions/request-timeout.d.ts +9 -1
- package/dist/functions/runtime-env.d.ts +92 -0
- package/dist/functions/wait-until.d.ts +74 -0
- package/dist/history/history-routes.d.ts +2 -2
- package/dist/history/index.d.ts +1 -1
- package/dist/history-recorder-B67maiTi.js +76 -0
- package/dist/history-recorder-B67maiTi.js.map +1 -0
- package/dist/history-store-oiqhb3HU.js +210 -0
- package/dist/history-store-oiqhb3HU.js.map +1 -0
- package/dist/index.d.ts +65 -54
- package/dist/index.es.js +3667 -328
- package/dist/index.es.js.map +1 -1
- package/dist/init/docs.d.ts +1 -1
- package/dist/init/middlewares.d.ts +1 -1
- package/dist/init/shutdown.d.ts +4 -0
- package/dist/init/storage.d.ts +1 -1
- package/dist/init/surfaces.d.ts +10 -0
- package/dist/init.d.ts +179 -22
- package/dist/internal-tables-DpxfPaEB.js +97 -0
- package/dist/internal-tables-DpxfPaEB.js.map +1 -0
- package/dist/jobs/index.d.ts +5 -5
- package/dist/{jobs-CyOKXXlu.js → jobs-B2ELModo.js} +11 -9
- package/dist/{jobs-CyOKXXlu.js.map → jobs-B2ELModo.js.map} +1 -1
- package/dist/{jwt-DxH9fLPt.js → jwt-DoHkMMWF.js} +9 -8
- package/dist/jwt-DoHkMMWF.js.map +1 -0
- package/dist/{logger-DfvF_8r-.js → logger-DS03e908.js} +104 -10
- package/dist/logger-DS03e908.js.map +1 -0
- package/dist/{logs-routes-CWBLQj2l.js → logs-routes-DB72iQSr.js} +36 -9
- package/dist/logs-routes-DB72iQSr.js.map +1 -0
- package/dist/metrics/history-recorder.d.ts +18 -0
- package/dist/metrics/history-store.d.ts +123 -0
- package/dist/metrics/index.d.ts +10 -2
- package/dist/{openapi-generator-BCKJRUS4.js → openapi-generator-FFGT0H6O.js} +7 -11
- package/dist/{openapi-generator-BCKJRUS4.js.map → openapi-generator-FFGT0H6O.js.map} +1 -1
- package/dist/{proxy-Bj5DVllb.js → proxy-CMymhnwG.js} +9 -6
- package/dist/{proxy-Bj5DVllb.js.map → proxy-CMymhnwG.js.map} +1 -1
- package/dist/query-parser--nstjRCh.js +355 -0
- package/dist/query-parser--nstjRCh.js.map +1 -0
- package/dist/{request-timeout-BuFoEKwT.js → request-timeout-C8gkc-j7.js} +21 -6
- package/dist/request-timeout-C8gkc-j7.js.map +1 -0
- package/dist/rls-audit/index.d.ts +111 -0
- package/dist/{rolldown-runtime-DSJWtz9O.js → rolldown-runtime-dW7B1o5h.js} +4 -3
- package/dist/schema-edit/apply-schema-change.d.ts +141 -0
- package/dist/schema-edit/github-repository.d.ts +67 -0
- package/dist/schema-edit/local-git-repository.d.ts +28 -0
- package/dist/schema-edit/project-root.d.ts +43 -0
- package/dist/schema-edit/remote-source.d.ts +25 -0
- package/dist/schema-edit/schema-edit-permissions.d.ts +129 -0
- package/dist/schema-editor-routes-Bf5h5Emf.js +87 -0
- package/dist/schema-editor-routes-Bf5h5Emf.js.map +1 -0
- package/dist/schemas-DBxgjM9A.js +4153 -0
- package/dist/schemas-DBxgjM9A.js.map +1 -0
- package/dist/{selection-_z6TM1DB.js → selection-CRpqKUbt.js} +6 -5
- package/dist/{selection-_z6TM1DB.js.map → selection-CRpqKUbt.js.map} +1 -1
- package/dist/services/webhook-service.d.ts +1 -1
- package/dist/singleton.d.ts +7 -0
- package/dist/{src-BPfYOeN4.js → src-B-CmIFMr.js} +8 -6
- package/dist/src-B-CmIFMr.js.map +1 -0
- package/dist/{src-CrCxd8km.js → src-Cdsw7DqV.js} +126 -5
- package/dist/src-Cdsw7DqV.js.map +1 -0
- package/dist/storage/GCSStorageController.d.ts +1 -1
- package/dist/storage/LocalStorageController.d.ts +1 -1
- package/dist/storage/S3StorageController.d.ts +1 -1
- package/dist/storage/cache-headers.d.ts +87 -0
- package/dist/storage/index.d.ts +11 -11
- package/dist/storage/path-pattern.d.ts +58 -0
- package/dist/storage/policies.d.ts +88 -0
- package/dist/storage/range.d.ts +63 -0
- package/dist/storage/rendition-cache.d.ts +45 -0
- package/dist/storage/routes.d.ts +17 -5
- package/dist/storage/storage-registry.d.ts +1 -1
- package/dist/storage/triggers.d.ts +66 -0
- package/dist/storage/tus-handler.d.ts +34 -3
- package/dist/topics/runtime.d.ts +68 -0
- package/dist/{types-DSnOC4mF.js → types-BfKcm9do.js} +5 -4
- package/dist/{types-DSnOC4mF.js.map → types-BfKcm9do.js.map} +1 -1
- package/dist/utils/host.d.ts +58 -0
- package/dist/utils/logger.d.ts +0 -15
- package/dist/utils/request-id.d.ts +1 -1
- package/functions/package.json +24 -0
- package/package.json +13 -7
- package/dist/admin_block-DLILvzle.js.map +0 -1
- package/dist/auth-5Et5mnUA.js.map +0 -1
- package/dist/contract-routes-DZ-LBpSL.js.map +0 -1
- package/dist/cron-routes-maM_RlUu.js.map +0 -1
- package/dist/cron-scheduler-DIpYBmZP.js.map +0 -1
- package/dist/ddl-bootstrap-Cywoj8Ta.js +0 -221
- package/dist/ddl-bootstrap-Cywoj8Ta.js.map +0 -1
- package/dist/errors-EBYiaJ2E.js.map +0 -1
- package/dist/function-routes-Btcez1T-.js.map +0 -1
- package/dist/jwt-DxH9fLPt.js.map +0 -1
- package/dist/logger-DfvF_8r-.js.map +0 -1
- package/dist/logs-routes-CWBLQj2l.js.map +0 -1
- package/dist/request-timeout-BuFoEKwT.js.map +0 -1
- package/dist/schema-editor-routes-CV9k0w3G.js.map +0 -1
- package/dist/src-BPfYOeN4.js.map +0 -1
- package/dist/src-CrCxd8km.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
-
import type { HonoEnv } from "../api/types";
|
|
3
|
-
import type { StorageController } from "../storage";
|
|
4
|
-
import { BackupDestination } from "./backup-common";
|
|
2
|
+
import type { HonoEnv } from "../api/types.js";
|
|
3
|
+
import type { StorageController } from "../storage/index.js";
|
|
4
|
+
import { BackupDestination } from "./backup-common.js";
|
|
5
5
|
export interface BackupRoutesConfig {
|
|
6
6
|
/**
|
|
7
7
|
* Resolve the current backup destination, or `null` when backups are not
|
package/dist/backup/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Storage-generic backup helpers and admin routes for the Backups panel.
|
|
3
3
|
* The `pg_dump`/`pg_restore` machinery lives in `@rebasepro/server-postgres`.
|
|
4
4
|
*/
|
|
5
|
-
export * from "./backup-common";
|
|
6
|
-
export { createBackupRoutes } from "./backup-routes";
|
|
7
|
-
export type { BackupRoutesConfig } from "./backup-routes";
|
|
5
|
+
export * from "./backup-common.js";
|
|
6
|
+
export { createBackupRoutes } from "./backup-routes.js";
|
|
7
|
+
export type { BackupRoutesConfig } from "./backup-routes.js";
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { createRequire as
|
|
2
|
-
import "process";
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import { n as
|
|
1
|
+
import { createRequire as __rebaseCreateRequire } from "module";
|
|
2
|
+
import __rebaseProcess from "process";
|
|
3
|
+
globalThis.process ??= __rebaseProcess;
|
|
4
|
+
__rebaseCreateRequire(import.meta.url);
|
|
5
|
+
import { n as __exportAll } from "./rolldown-runtime-dW7B1o5h.js";
|
|
6
|
+
import { n as errorHandler, t as ApiError } from "./errors-DBwpj9N8.js";
|
|
6
7
|
import fs from "fs";
|
|
7
8
|
import path from "path";
|
|
8
9
|
import { Hono } from "hono";
|
|
@@ -160,4 +161,4 @@ var backup_exports = /* @__PURE__ */ __exportAll({
|
|
|
160
161
|
//#endregion
|
|
161
162
|
export { parseBackupTimestamp as a, parseBackupDestination as i, createBackupRoutes as n, readBackupBytes as o, listBackupObjects as r, backup_exports as t };
|
|
162
163
|
|
|
163
|
-
//# sourceMappingURL=backup-
|
|
164
|
+
//# sourceMappingURL=backup-CRdZkA6c.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backup-C6ljYVTp.js","names":[],"sources":["../src/backup/backup-common.ts","../src/backup/backup-routes.ts","../src/backup/index.ts"],"sourcesContent":["/**\n * Storage-generic backup helpers used by the admin backup routes.\n *\n * These live in server (which owns {@link StorageController}) so the\n * admin API can list backups without depending on the Postgres driver —\n * `server` must not import from `server-postgres`. The `pg_dump`-side\n * copies of the tiny pure parsers live in `@rebasepro/server-postgres`;\n * keep the two in sync if the naming scheme ever changes.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { BackupInfo, BackupDestinationKind } from \"@rebasepro/types\";\nimport type { StorageController } from \"../storage\";\n\nexport type BackupDestination =\n | { kind: \"local\"; path: string }\n | { kind: \"s3\"; bucket: string; prefix: string }\n | { kind: \"gcs\"; bucket: string; prefix: string };\n\n/** Parse a destination string (`s3://…`, `gs://…`, or a local path). */\nexport function parseBackupDestination(out: string): BackupDestination {\n const s3 = out.match(/^s3:\\/\\/([^/]+)\\/?(.*)$/);\n if (s3) return { kind: \"s3\", bucket: s3[1], prefix: s3[2].replace(/\\/+$/, \"\") };\n const gcs = out.match(/^gs:\\/\\/([^/]+)\\/?(.*)$/);\n if (gcs) return { kind: \"gcs\", bucket: gcs[1], prefix: gcs[2].replace(/\\/+$/, \"\") };\n return { kind: \"local\", path: out };\n}\n\n/**\n * Recover the UTC creation time encoded in a `rebase-<db>-<ts>.dump` name.\n * Returns `null` for names that don't match, so foreign objects are ignored.\n */\nexport function parseBackupTimestamp(fileName: string): Date | null {\n const base = fileName.split(\"/\").pop() ?? fileName;\n const match = base.match(/-(\\d{8})T(\\d{6})Z\\.dump$/);\n if (!match) return null;\n const [, ymd, hms] = match;\n const iso =\n `${ymd.slice(0, 4)}-${ymd.slice(4, 6)}-${ymd.slice(6, 8)}` +\n `T${hms.slice(0, 2)}:${hms.slice(2, 4)}:${hms.slice(4, 6)}Z`;\n const date = new Date(iso);\n return Number.isNaN(date.getTime()) ? null : date;\n}\n\n/**\n * List the backups at a destination as {@link BackupInfo}, newest first.\n * Only `.dump` files are considered.\n */\nexport async function listBackupObjects(\n dest: BackupDestination,\n storage?: StorageController\n): Promise<BackupInfo[]> {\n if (dest.kind === \"local\") {\n if (!fs.existsSync(dest.path)) return [];\n const stat = fs.statSync(dest.path);\n const dir = stat.isDirectory() ? dest.path : path.dirname(dest.path);\n if (!fs.existsSync(dir)) return [];\n return fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(\".dump\"))\n .map((f): BackupInfo => {\n const full = path.join(dir, f);\n const st = fs.statSync(full);\n const createdAt = parseBackupTimestamp(f) ?? st.mtime;\n return {\n key: full,\n name: f,\n sizeBytes: st.size,\n createdAt: createdAt.toISOString(),\n destinationKind: \"local\"\n };\n })\n .sort(byNewest);\n }\n\n if (!storage) return [];\n const result = await storage.listObjects(dest.prefix ? `${dest.prefix}/` : \"\", {\n bucket: dest.bucket,\n maxResults: 1000\n });\n return result.items\n .map((item) => item.fullPath)\n .filter((key) => key.endsWith(\".dump\"))\n .map((key): BackupInfo => {\n const createdAt = parseBackupTimestamp(key);\n return {\n key,\n name: key.split(\"/\").pop() || key,\n createdAt: createdAt ? createdAt.toISOString() : undefined,\n destinationKind: dest.kind as BackupDestinationKind\n };\n })\n .sort(byNewest);\n}\n\nfunction byNewest(a: BackupInfo, b: BackupInfo): number {\n const ta = a.createdAt ? Date.parse(a.createdAt) : 0;\n const tb = b.createdAt ? Date.parse(b.createdAt) : 0;\n return tb - ta;\n}\n\n/** Read a single backup's bytes. Guards against path traversal for local. */\nexport async function readBackupBytes(\n dest: BackupDestination,\n key: string,\n storage?: StorageController\n): Promise<{ bytes: Uint8Array<ArrayBuffer>; name: string } | null> {\n if (dest.kind === \"local\") {\n const stat = fs.existsSync(dest.path) ? fs.statSync(dest.path) : null;\n const dir = stat?.isDirectory() ? dest.path : path.dirname(dest.path);\n const resolvedDir = path.resolve(dir);\n const resolved = path.resolve(key);\n // Only allow reads inside the backup directory, and only .dump files.\n if (!resolved.startsWith(resolvedDir + path.sep) || !resolved.endsWith(\".dump\")) {\n return null;\n }\n if (!fs.existsSync(resolved)) return null;\n return { bytes: new Uint8Array(fs.readFileSync(resolved)), name: path.basename(resolved) };\n }\n\n if (!storage) return null;\n if (!key.endsWith(\".dump\")) return null;\n const file = await storage.getObject(key, dest.bucket);\n if (!file) return null;\n return { bytes: new Uint8Array(await file.arrayBuffer()), name: key.split(\"/\").pop() || key };\n}\n","import { Hono } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\nimport { ApiError, errorHandler } from \"../api/errors\";\nimport type { StorageController } from \"../storage\";\nimport { BackupDestination, listBackupObjects, readBackupBytes } from \"./backup-common\";\n\nexport interface BackupRoutesConfig {\n /**\n * Resolve the current backup destination, or `null` when backups are not\n * configured (`BACKUP_DESTINATION` unset). Read lazily so a restart isn't\n * required to pick up config.\n */\n getDestination: () => BackupDestination | null;\n /** Storage controller for object-storage destinations. */\n storage?: StorageController;\n}\n\n/**\n * Admin REST routes for the Backups panel.\n *\n * Routes (mounted under `/admin/backups`, admin-guarded by the caller):\n * GET / → list available backups\n * GET /download → download a backup's bytes (?key=…)\n */\nexport function createBackupRoutes(config: BackupRoutesConfig): Hono<HonoEnv> {\n const router = new Hono<HonoEnv>();\n router.onError(errorHandler);\n\n router.get(\"/\", async (c) => {\n const dest = config.getDestination();\n if (!dest) {\n return c.json({ backups: [], destinationKind: \"local\" as const, configured: false });\n }\n const backups = await listBackupObjects(dest, config.storage);\n return c.json({ backups, destinationKind: dest.kind, configured: true });\n });\n\n router.get(\"/download\", async (c) => {\n const dest = config.getDestination();\n if (!dest) {\n throw ApiError.badRequest(\"Backups are not configured (set BACKUP_DESTINATION).\");\n }\n const key = c.req.query(\"key\");\n if (!key) {\n throw ApiError.badRequest(\"Missing 'key' query parameter.\");\n }\n const result = await readBackupBytes(dest, key, config.storage);\n if (!result) {\n throw ApiError.notFound(`Backup not found: ${key}`);\n }\n c.header(\"Content-Type\", \"application/octet-stream\");\n c.header(\"Content-Disposition\", `attachment; filename=\"${result.name}\"`);\n return c.body(result.bytes);\n });\n\n return router;\n}\n","/**\n * Storage-generic backup helpers and admin routes for the Backups panel.\n * The `pg_dump`/`pg_restore` machinery lives in `@rebasepro/server-postgres`.\n */\nexport * from \"./backup-common\";\nexport { createBackupRoutes } from \"./backup-routes\";\nexport type { BackupRoutesConfig } from \"./backup-routes\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"backup-CRdZkA6c.js","names":[],"sources":["../src/backup/backup-common.ts","../src/backup/backup-routes.ts","../src/backup/index.ts"],"sourcesContent":["/**\n * Storage-generic backup helpers used by the admin backup routes.\n *\n * These live in server (which owns {@link StorageController}) so the\n * admin API can list backups without depending on the Postgres driver —\n * `server` must not import from `server-postgres`. The `pg_dump`-side\n * copies of the tiny pure parsers live in `@rebasepro/server-postgres`;\n * keep the two in sync if the naming scheme ever changes.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport type { BackupInfo, BackupDestinationKind } from \"@rebasepro/types\";\nimport type { StorageController } from \"../storage\";\n\nexport type BackupDestination =\n | { kind: \"local\"; path: string }\n | { kind: \"s3\"; bucket: string; prefix: string }\n | { kind: \"gcs\"; bucket: string; prefix: string };\n\n/** Parse a destination string (`s3://…`, `gs://…`, or a local path). */\nexport function parseBackupDestination(out: string): BackupDestination {\n const s3 = out.match(/^s3:\\/\\/([^/]+)\\/?(.*)$/);\n if (s3) return { kind: \"s3\", bucket: s3[1], prefix: s3[2].replace(/\\/+$/, \"\") };\n const gcs = out.match(/^gs:\\/\\/([^/]+)\\/?(.*)$/);\n if (gcs) return { kind: \"gcs\", bucket: gcs[1], prefix: gcs[2].replace(/\\/+$/, \"\") };\n return { kind: \"local\", path: out };\n}\n\n/**\n * Recover the UTC creation time encoded in a `rebase-<db>-<ts>.dump` name.\n * Returns `null` for names that don't match, so foreign objects are ignored.\n */\nexport function parseBackupTimestamp(fileName: string): Date | null {\n const base = fileName.split(\"/\").pop() ?? fileName;\n const match = base.match(/-(\\d{8})T(\\d{6})Z\\.dump$/);\n if (!match) return null;\n const [, ymd, hms] = match;\n const iso =\n `${ymd.slice(0, 4)}-${ymd.slice(4, 6)}-${ymd.slice(6, 8)}` +\n `T${hms.slice(0, 2)}:${hms.slice(2, 4)}:${hms.slice(4, 6)}Z`;\n const date = new Date(iso);\n return Number.isNaN(date.getTime()) ? null : date;\n}\n\n/**\n * List the backups at a destination as {@link BackupInfo}, newest first.\n * Only `.dump` files are considered.\n */\nexport async function listBackupObjects(\n dest: BackupDestination,\n storage?: StorageController\n): Promise<BackupInfo[]> {\n if (dest.kind === \"local\") {\n if (!fs.existsSync(dest.path)) return [];\n const stat = fs.statSync(dest.path);\n const dir = stat.isDirectory() ? dest.path : path.dirname(dest.path);\n if (!fs.existsSync(dir)) return [];\n return fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(\".dump\"))\n .map((f): BackupInfo => {\n const full = path.join(dir, f);\n const st = fs.statSync(full);\n const createdAt = parseBackupTimestamp(f) ?? st.mtime;\n return {\n key: full,\n name: f,\n sizeBytes: st.size,\n createdAt: createdAt.toISOString(),\n destinationKind: \"local\"\n };\n })\n .sort(byNewest);\n }\n\n if (!storage) return [];\n const result = await storage.listObjects(dest.prefix ? `${dest.prefix}/` : \"\", {\n bucket: dest.bucket,\n maxResults: 1000\n });\n return result.items\n .map((item) => item.fullPath)\n .filter((key) => key.endsWith(\".dump\"))\n .map((key): BackupInfo => {\n const createdAt = parseBackupTimestamp(key);\n return {\n key,\n name: key.split(\"/\").pop() || key,\n createdAt: createdAt ? createdAt.toISOString() : undefined,\n destinationKind: dest.kind as BackupDestinationKind\n };\n })\n .sort(byNewest);\n}\n\nfunction byNewest(a: BackupInfo, b: BackupInfo): number {\n const ta = a.createdAt ? Date.parse(a.createdAt) : 0;\n const tb = b.createdAt ? Date.parse(b.createdAt) : 0;\n return tb - ta;\n}\n\n/** Read a single backup's bytes. Guards against path traversal for local. */\nexport async function readBackupBytes(\n dest: BackupDestination,\n key: string,\n storage?: StorageController\n): Promise<{ bytes: Uint8Array<ArrayBuffer>; name: string } | null> {\n if (dest.kind === \"local\") {\n const stat = fs.existsSync(dest.path) ? fs.statSync(dest.path) : null;\n const dir = stat?.isDirectory() ? dest.path : path.dirname(dest.path);\n const resolvedDir = path.resolve(dir);\n const resolved = path.resolve(key);\n // Only allow reads inside the backup directory, and only .dump files.\n if (!resolved.startsWith(resolvedDir + path.sep) || !resolved.endsWith(\".dump\")) {\n return null;\n }\n if (!fs.existsSync(resolved)) return null;\n return { bytes: new Uint8Array(fs.readFileSync(resolved)), name: path.basename(resolved) };\n }\n\n if (!storage) return null;\n if (!key.endsWith(\".dump\")) return null;\n const file = await storage.getObject(key, dest.bucket);\n if (!file) return null;\n return { bytes: new Uint8Array(await file.arrayBuffer()), name: key.split(\"/\").pop() || key };\n}\n","import { Hono } from \"hono\";\nimport type { HonoEnv } from \"../api/types\";\nimport { ApiError, errorHandler } from \"../api/errors\";\nimport type { StorageController } from \"../storage\";\nimport { BackupDestination, listBackupObjects, readBackupBytes } from \"./backup-common\";\n\nexport interface BackupRoutesConfig {\n /**\n * Resolve the current backup destination, or `null` when backups are not\n * configured (`BACKUP_DESTINATION` unset). Read lazily so a restart isn't\n * required to pick up config.\n */\n getDestination: () => BackupDestination | null;\n /** Storage controller for object-storage destinations. */\n storage?: StorageController;\n}\n\n/**\n * Admin REST routes for the Backups panel.\n *\n * Routes (mounted under `/admin/backups`, admin-guarded by the caller):\n * GET / → list available backups\n * GET /download → download a backup's bytes (?key=…)\n */\nexport function createBackupRoutes(config: BackupRoutesConfig): Hono<HonoEnv> {\n const router = new Hono<HonoEnv>();\n router.onError(errorHandler);\n\n router.get(\"/\", async (c) => {\n const dest = config.getDestination();\n if (!dest) {\n return c.json({ backups: [], destinationKind: \"local\" as const, configured: false });\n }\n const backups = await listBackupObjects(dest, config.storage);\n return c.json({ backups, destinationKind: dest.kind, configured: true });\n });\n\n router.get(\"/download\", async (c) => {\n const dest = config.getDestination();\n if (!dest) {\n throw ApiError.badRequest(\"Backups are not configured (set BACKUP_DESTINATION).\");\n }\n const key = c.req.query(\"key\");\n if (!key) {\n throw ApiError.badRequest(\"Missing 'key' query parameter.\");\n }\n const result = await readBackupBytes(dest, key, config.storage);\n if (!result) {\n throw ApiError.notFound(`Backup not found: ${key}`);\n }\n c.header(\"Content-Type\", \"application/octet-stream\");\n c.header(\"Content-Disposition\", `attachment; filename=\"${result.name}\"`);\n return c.body(result.bytes);\n });\n\n return router;\n}\n","/**\n * Storage-generic backup helpers and admin routes for the Backups panel.\n * The `pg_dump`/`pg_restore` machinery lives in `@rebasepro/server-postgres`.\n */\nexport * from \"./backup-common\";\nexport { createBackupRoutes } from \"./backup-routes\";\nexport type { BackupRoutesConfig } from \"./backup-routes\";\n"],"mappings":"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"}
|
package/dist/boot/boot.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type Server } from "http";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
|
-
import { type RebaseBackendInstance } from "../init";
|
|
4
|
-
import type { HonoEnv } from "../api/types";
|
|
5
|
-
import { type RebaseBootEnv } from "./env";
|
|
6
|
-
import { type LoadedBundle } from "./bundle";
|
|
7
|
-
import { type InitializedDataSource } from "./driver";
|
|
3
|
+
import { type RebaseBackendInstance } from "../init.js";
|
|
4
|
+
import type { HonoEnv } from "../api/types.js";
|
|
5
|
+
import { type RebaseBootEnv } from "./env.js";
|
|
6
|
+
import { type LoadedBundle } from "./bundle.js";
|
|
7
|
+
import { type InitializedDataSource } from "./driver.js";
|
|
8
8
|
/** A running runtime, and the handle to stop it. */
|
|
9
9
|
export interface BootedRuntime {
|
|
10
10
|
app: Hono<HonoEnv>;
|
package/dist/boot/bundle.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CollectionConfig, type CollectionCallbacks, type DataSourceDefinition, type RebaseBundleManifest, type StorageSourceDefinition } from "@rebasepro/types";
|
|
2
|
-
import type { StorageAuthorize } from "../storage/types";
|
|
2
|
+
import type { StorageAuthorize } from "../storage/types.js";
|
|
3
3
|
/** Thrown when a bundle cannot be read, or claims a contract this runtime cannot honour. */
|
|
4
4
|
export declare class BundleError extends Error {
|
|
5
5
|
readonly hint?: string | undefined;
|
|
@@ -31,6 +31,15 @@ export interface LoadedStaticApp {
|
|
|
31
31
|
/** Serve `index.html` for unmatched paths under `path`. */
|
|
32
32
|
spa: boolean;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The file that makes a directory a bundle.
|
|
36
|
+
*
|
|
37
|
+
* Exported because `fetch-bundle.ts` has to recognise the same thing after
|
|
38
|
+
* unpacking, and when it had its own idea of the name — `rebase-bundle.json`,
|
|
39
|
+
* which nothing has ever written — every download was rejected as "not a Rebase
|
|
40
|
+
* bundle". A marker with two spellings is a marker with none.
|
|
41
|
+
*/
|
|
42
|
+
export declare const MANIFEST_FILENAME = "manifest.json";
|
|
34
43
|
/**
|
|
35
44
|
* Read and validate a bundle's manifest.
|
|
36
45
|
*
|
package/dist/boot/driver.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BackendBootstrapper, DatabaseAdapter } from "@rebasepro/types";
|
|
2
|
-
import type { ResolvedDataSourceConfig } from "./sources";
|
|
2
|
+
import type { ResolvedDataSourceConfig } from "./sources.js";
|
|
3
3
|
/**
|
|
4
4
|
* The connection handle a driver hands back at boot: the client object, the
|
|
5
5
|
* pool to close on shutdown, and how to probe it.
|
package/dist/boot/env.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { type RebaseEnv } from "../env";
|
|
2
|
+
import { type RebaseEnv } from "../env.js";
|
|
3
3
|
/**
|
|
4
4
|
* The environment a bundle-booted runtime understands.
|
|
5
5
|
*
|
|
@@ -52,6 +52,11 @@ declare const bootEnvExtension: z.ZodObject<{
|
|
|
52
52
|
true: "true";
|
|
53
53
|
false: "false";
|
|
54
54
|
}>>, z.ZodTransform<boolean, "" | "true" | "false">>;
|
|
55
|
+
STORAGE_RENDITION_CACHE: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
56
|
+
"": "";
|
|
57
|
+
true: "true";
|
|
58
|
+
false: "false";
|
|
59
|
+
}>>, z.ZodTransform<boolean, "" | "true" | "false">>;
|
|
55
60
|
STORAGE_ALLOW_ANY_AUTHENTICATED: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
56
61
|
"": "";
|
|
57
62
|
true: "true";
|
|
@@ -67,6 +72,23 @@ declare const bootEnvExtension: z.ZodObject<{
|
|
|
67
72
|
true: "true";
|
|
68
73
|
false: "false";
|
|
69
74
|
}>>, z.ZodTransform<boolean, "" | "true" | "false">>;
|
|
75
|
+
AUTH_MAGIC_LINK: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
76
|
+
"": "";
|
|
77
|
+
true: "true";
|
|
78
|
+
false: "false";
|
|
79
|
+
}>>, z.ZodTransform<boolean, "" | "true" | "false">>;
|
|
80
|
+
AUTH_EMAIL_OTP: z.ZodPipe<z.ZodDefault<z.ZodEnum<{
|
|
81
|
+
"": "";
|
|
82
|
+
true: "true";
|
|
83
|
+
false: "false";
|
|
84
|
+
}>>, z.ZodTransform<boolean, "" | "true" | "false">>;
|
|
85
|
+
CAPTCHA_PROVIDER: z.ZodOptional<z.ZodEnum<{
|
|
86
|
+
"": "";
|
|
87
|
+
turnstile: "turnstile";
|
|
88
|
+
hcaptcha: "hcaptcha";
|
|
89
|
+
}>>;
|
|
90
|
+
CAPTCHA_SECRET: z.ZodOptional<z.ZodString>;
|
|
91
|
+
CAPTCHA_ROUTES: z.ZodOptional<z.ZodString>;
|
|
70
92
|
AUTH_COOKIE_SAME_SITE: z.ZodOptional<z.ZodEnum<{
|
|
71
93
|
"": "";
|
|
72
94
|
Strict: "Strict";
|
|
@@ -113,6 +135,11 @@ declare const bootEnvExtension: z.ZodObject<{
|
|
|
113
135
|
true: "true";
|
|
114
136
|
false: "false";
|
|
115
137
|
}>>, z.ZodTransform<boolean | undefined, "" | "true" | "false" | undefined>>;
|
|
138
|
+
REBASE_RLS_AUDIT: z.ZodPipe<z.ZodOptional<z.ZodEnum<{
|
|
139
|
+
"": "";
|
|
140
|
+
true: "true";
|
|
141
|
+
false: "false";
|
|
142
|
+
}>>, z.ZodTransform<boolean | undefined, "" | "true" | "false" | undefined>>;
|
|
116
143
|
REBASE_FUNCTIONS_ONLY: z.ZodOptional<z.ZodString>;
|
|
117
144
|
REBASE_FUNCTIONS_EXCLUDE: z.ZodOptional<z.ZodString>;
|
|
118
145
|
REBASE_FUNCTIONS_UPSTREAM: z.ZodOptional<z.ZodString>;
|
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
export declare const BUNDLE_URL_ENV = "REBASE_BUNDLE_URL";
|
|
3
3
|
/** Bearer token for that fetch. Does not expire — see the module note. */
|
|
4
4
|
export declare const BUNDLE_TOKEN_ENV = "REBASE_BUNDLE_TOKEN";
|
|
5
|
+
/**
|
|
6
|
+
* Where a fetched bundle is unpacked. Defaults to a fresh temp directory.
|
|
7
|
+
*
|
|
8
|
+
* A platform sets this to a volume it sized on purpose, because the unpack and
|
|
9
|
+
* the dependency install are the two things in a pod's life that need real
|
|
10
|
+
* disk. Left unset the bundle lands under the OS temp directory, which on a
|
|
11
|
+
* container is the writable layer and on Cloud Run is a tmpfs — fine for a
|
|
12
|
+
* small bundle, and the thing to change first when one is not.
|
|
13
|
+
*
|
|
14
|
+
* It is deliberately a *fixed* directory when set, not a fresh one per boot: a
|
|
15
|
+
* container that restarts inside a live pod finds the tree it already unpacked
|
|
16
|
+
* and installed, so a restart costs a manifest check rather than a download and
|
|
17
|
+
* an `npm ci`. `REBASE_BUNDLE` is still the one that means "a bundle is already
|
|
18
|
+
* here, do not fetch at all" — this only says where to put one.
|
|
19
|
+
*/
|
|
20
|
+
export declare const BUNDLE_FETCH_DIR_ENV = "REBASE_BUNDLE_FETCH_DIR";
|
|
5
21
|
export interface FetchBundleOptions {
|
|
6
22
|
url: string;
|
|
7
23
|
token?: string;
|
|
@@ -11,8 +27,29 @@ export interface FetchBundleOptions {
|
|
|
11
27
|
fetchImpl?: typeof fetch;
|
|
12
28
|
/** Injected for tests. */
|
|
13
29
|
extract?: (tarball: string, destination: string) => Promise<void>;
|
|
14
|
-
/** How long
|
|
30
|
+
/** How long a single download attempt may take before it is abandoned. */
|
|
15
31
|
timeoutMs?: number;
|
|
32
|
+
/**
|
|
33
|
+
* How many times to try the download.
|
|
34
|
+
*
|
|
35
|
+
* A pod starting during a control-plane rollout, or racing its own DNS, gets
|
|
36
|
+
* one transient failure and would otherwise CrashLoop on it — and a
|
|
37
|
+
* CrashLoop re-runs the whole boot, so the retry is cheaper than the restart
|
|
38
|
+
* it replaces.
|
|
39
|
+
*/
|
|
40
|
+
attempts?: number;
|
|
41
|
+
/** Delay between attempts. */
|
|
42
|
+
retryDelayMs?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Install the bundle's declared dependencies after unpacking.
|
|
45
|
+
*
|
|
46
|
+
* On by default: a bundle that declares dependencies and has none installed
|
|
47
|
+
* cannot boot, and this is the only step between the two. Turned off for a
|
|
48
|
+
* bundle that was vendored at build time, and by tests.
|
|
49
|
+
*/
|
|
50
|
+
installDependencies?: boolean;
|
|
51
|
+
/** Injected for tests. */
|
|
52
|
+
installImpl?: (bundleRoot: string) => Promise<void>;
|
|
16
53
|
}
|
|
17
54
|
/**
|
|
18
55
|
* Whether this process should fetch its bundle rather than read one from disk.
|
|
@@ -31,6 +68,112 @@ export declare function shouldFetchBundle(env?: NodeJS.ProcessEnv): boolean;
|
|
|
31
68
|
* refuse. Writing the whole tarball first means a truncated download is caught
|
|
32
69
|
* by `tar` as a corrupt archive, which is an error.
|
|
33
70
|
*/
|
|
71
|
+
/**
|
|
72
|
+
* Install the bundle's declared dependencies, in place.
|
|
73
|
+
*
|
|
74
|
+
* `npm ci` when a lockfile is present and `npm install` otherwise — a bundle
|
|
75
|
+
* that shipped a lockfile gets a reproducible install, one that did not still
|
|
76
|
+
* boots.
|
|
77
|
+
*
|
|
78
|
+
* `--ignore-scripts` is not optional. The runtime image's entrypoint refuses to
|
|
79
|
+
* run lifecycle scripts, and an install that ran them here would void that
|
|
80
|
+
* guarantee at every pod start, executing arbitrary code from the dependency
|
|
81
|
+
* tree before the process this is meant to be booting exists.
|
|
82
|
+
*
|
|
83
|
+
* The npm cache is dropped afterwards because it is, at that point, a
|
|
84
|
+
* byte-for-byte duplicate of the tree beside it and nothing reads it again —
|
|
85
|
+
* the runtime never installs twice in one process. Keeping it doubles the
|
|
86
|
+
* high-water mark on a disk that is usually the binding constraint.
|
|
87
|
+
*/
|
|
88
|
+
export declare function installBundleDependencies(bundleRoot: string, exec?: (cmd: string, args: string[], opts: object) => Promise<unknown>): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Packages the runtime image provides and a bundle must not carry its own copy of.
|
|
91
|
+
*
|
|
92
|
+
* Exactly one, deliberately. `@rebasepro/server` holds the framework singleton,
|
|
93
|
+
* and a second copy is not merely wasteful — it is a total, silent breakage of
|
|
94
|
+
* custom functions. Every function imports `defineFunction` from
|
|
95
|
+
* `@rebasepro/server`, so it resolves the BUNDLE's copy, which is a different
|
|
96
|
+
* module instance from the one `runFromBundle` booted. The singleton
|
|
97
|
+
* initialised by the boot is invisible to it, so `rebase.data`,
|
|
98
|
+
* `rebase.dataAsAdmin` and `rebase.storage` throw "server not initialized yet"
|
|
99
|
+
* on every request, in a process that is otherwise healthy and reports itself
|
|
100
|
+
* ready. Seen in production as every custom-function route 500ing while
|
|
101
|
+
* `/api/data/*` served fine.
|
|
102
|
+
*
|
|
103
|
+
* It arrives transitively: `@rebasepro/admin` and `@rebasepro/server-postgres`
|
|
104
|
+
* both depend on it, and nearly every project declares one of them.
|
|
105
|
+
*
|
|
106
|
+
* NOT every package the image ships. The image installs the narrow set of
|
|
107
|
+
* dependencies the runtime itself needs, while the bundle's install resolved
|
|
108
|
+
* each package's FULL tree — so redirecting a package at the image's copy can
|
|
109
|
+
* point it at a tree missing something. `@rebasepro/server-postgres` is the
|
|
110
|
+
* proof: the image's copy has no `chokidar`, and redirecting it took the
|
|
111
|
+
* database driver down and crash-looped the pod. `@rebasepro/server` is the one
|
|
112
|
+
* package where the redirect is both necessary (it holds the singleton) and
|
|
113
|
+
* provably safe (the process is already running from the image's copy).
|
|
114
|
+
*/
|
|
115
|
+
/**
|
|
116
|
+
* Where the runtime image keeps its own `node_modules`, when there is an image.
|
|
117
|
+
*
|
|
118
|
+
* An environment variable, set by the image, rather than something derived from
|
|
119
|
+
* this module's own location. Deriving it is the obvious approach and it does
|
|
120
|
+
* not survive the build: `__filename` is undefined in the ESM bundle vite emits,
|
|
121
|
+
* and `import.meta.url` is a syntax error under the CJS transform the jest
|
|
122
|
+
* suites use — so any version of this that reads its own path works in exactly
|
|
123
|
+
* one of the two places it has to.
|
|
124
|
+
*
|
|
125
|
+
* Found by booting the built image (`tooling/scripts/check-runtime-image-boots.mjs`),
|
|
126
|
+
* which is the only thing that runs the artifact this ships as. The unit tests
|
|
127
|
+
* were green.
|
|
128
|
+
*
|
|
129
|
+
* Absent outside a container, where there is no second copy to collapse and
|
|
130
|
+
* nothing to do.
|
|
131
|
+
*/
|
|
132
|
+
export declare const RUNTIME_MODULES_ENV = "REBASE_RUNTIME_MODULES";
|
|
133
|
+
/**
|
|
134
|
+
* The packages the runtime image supplies to a fetched bundle.
|
|
135
|
+
*
|
|
136
|
+
* Must match `RUNTIME_PROVIDED` in `packages/cli/src/bundle.ts` and in
|
|
137
|
+
* `infra/docker/entrypoint.mjs`; `tooling/scripts/test/runtime-provided.test.mjs` fails if any
|
|
138
|
+
* of the three drift. The bundler STRIPS these from a bundle's declared
|
|
139
|
+
* dependencies on the promise that the image supplies them, so a shorter list
|
|
140
|
+
* here means the builder removed a dependency that nothing then provides, and
|
|
141
|
+
* every function and cron importing it fails to load with `Cannot find package`
|
|
142
|
+
* behind a container that reports itself healthy.
|
|
143
|
+
*
|
|
144
|
+
* This list carried only `@rebasepro/server` while the bundler stripped five —
|
|
145
|
+
* the same four-package gap that broke the non-fetch path, reproduced on the
|
|
146
|
+
* fetch path because this list was written before that fix and no gate watched
|
|
147
|
+
* this file.
|
|
148
|
+
*/
|
|
149
|
+
export declare const RUNTIME_PROVIDED_PACKAGES: readonly ["@rebasepro/server", "@rebasepro/types", "@rebasepro/client", "@rebasepro/common", "@rebasepro/utils"];
|
|
150
|
+
/**
|
|
151
|
+
* Collapse a duplicate framework copy in the bundle onto the image's.
|
|
152
|
+
*
|
|
153
|
+
* Node resolves a module's identity by its real path, so replacing the
|
|
154
|
+
* duplicate with a symlink makes the two one instance again. It is also the
|
|
155
|
+
* honest version of what was already true: the image's copy is the one that
|
|
156
|
+
* booted and owns the process, so a bundle pinning a different version was
|
|
157
|
+
* never running that version — it just carried a second, dead one alongside it.
|
|
158
|
+
*
|
|
159
|
+
* Non-fatal by design. A project with no custom functions is unaffected by the
|
|
160
|
+
* duplicate, and refusing to boot over it would turn a degraded start into no
|
|
161
|
+
* start at all.
|
|
162
|
+
*
|
|
163
|
+
* @param imageModules the runtime image's own `node_modules`. Absent, there is
|
|
164
|
+
* nothing to dedupe against and this is a no-op — which is the case in every
|
|
165
|
+
* context except a container built from the runtime image.
|
|
166
|
+
*/
|
|
167
|
+
export declare function dedupeRuntimePackages(bundleRoot: string, imageModules: string | undefined): string[];
|
|
168
|
+
/**
|
|
169
|
+
* Download, unpack and prepare a bundle, returning the directory it landed in.
|
|
170
|
+
*
|
|
171
|
+
* Downloads to a file rather than streaming into `tar`, deliberately. A stream
|
|
172
|
+
* that dies mid-transfer leaves `tar` having successfully extracted a prefix of
|
|
173
|
+
* the archive and exiting 0 — the half-unpacked bundle this module exists to
|
|
174
|
+
* refuse. Writing the whole tarball first means a truncated download is caught
|
|
175
|
+
* by `tar` as a corrupt archive, which is an error.
|
|
176
|
+
*/
|
|
34
177
|
export declare function fetchBundle(options: FetchBundleOptions): Promise<string>;
|
|
35
178
|
/**
|
|
36
179
|
* Find the bundle root inside an unpacked directory.
|
package/dist/boot/options.d.ts
CHANGED
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
import type { CollectionConfig } from "@rebasepro/types";
|
|
2
|
-
import type { RebaseAuthConfig } from "../init";
|
|
3
|
-
import type { EmailConfig } from "../email";
|
|
4
|
-
import type {
|
|
2
|
+
import type { RebaseAuthConfig } from "../init.js";
|
|
3
|
+
import type { EmailConfig } from "../email/index.js";
|
|
4
|
+
import type { CaptchaConfig } from "../auth/captcha.js";
|
|
5
|
+
import type { RebaseBootEnv } from "./env.js";
|
|
5
6
|
/**
|
|
6
|
-
* Build the email configuration
|
|
7
|
+
* Build the email configuration.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
9
|
+
* With `SMTP_HOST`, that is a real SMTP transport. Without it, outside
|
|
10
|
+
* production, it is the development sink: mail is captured and its links are
|
|
11
|
+
* printed, so `POST /auth/magic-link` and `POST /auth/forgot-password` complete
|
|
12
|
+
* on a fresh project instead of answering `503 EMAIL_NOT_CONFIGURED`. The token
|
|
13
|
+
* was always minted and valid; only delivery was missing.
|
|
14
|
+
*
|
|
15
|
+
* Three conditions, all required, none configurable:
|
|
16
|
+
*
|
|
17
|
+
* - no `SMTP_HOST` — a configured mail server always wins;
|
|
18
|
+
* - `NODE_ENV` is not `production` — a captured reset mail carries a working
|
|
19
|
+
* token, so this must not be reachable there (see `dev-sink.ts`);
|
|
20
|
+
* - an absolute `FRONTEND_URL`, or the emailed link has no base and is dead on
|
|
21
|
+
* arrival — which is the condition `assertEmailLinkBases` fails the boot on.
|
|
22
|
+
*
|
|
23
|
+
* When any of those does not hold this returns `undefined`, exactly as before,
|
|
24
|
+
* and the auth routes report the missing service for themselves.
|
|
10
25
|
*/
|
|
11
26
|
export declare function resolveEmailOptions(env: RebaseBootEnv): EmailConfig | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Bot protection from the environment, or `undefined` when it is not configured.
|
|
29
|
+
*
|
|
30
|
+
* Both halves are required together. A provider with no secret cannot verify
|
|
31
|
+
* anything, so it is left off here and `resolveCaptchaVerifier` refuses the boot
|
|
32
|
+
* if something else turns it on — the one failure this feature must not have is
|
|
33
|
+
* being silently absent while the config says otherwise.
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveCaptchaOptions(env: RebaseBootEnv): CaptchaConfig | undefined;
|
|
12
36
|
/**
|
|
13
37
|
* Build the auth configuration from the environment and the bundle's users
|
|
14
38
|
* collection.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The graph, expressed as the shapes the existing subsystems already take.
|
|
3
|
+
*
|
|
4
|
+
* The data layer consumes `DataSourceDefinition[]` and the storage layer
|
|
5
|
+
* consumes `StorageSourceDefinition[]`, and both work. Nothing about the
|
|
6
|
+
* resource graph requires rewriting them: the graph is a better *declaration*,
|
|
7
|
+
* not a different runtime. So it is translated at the boundary, once, and
|
|
8
|
+
* everything downstream is untouched.
|
|
9
|
+
*
|
|
10
|
+
* Doing it the other way round — teaching each subsystem to read the graph —
|
|
11
|
+
* would have meant touching the pool manager, the storage registry and the
|
|
12
|
+
* collection resolver to land a config change, which is how a config change
|
|
13
|
+
* becomes a rewrite and then does not ship.
|
|
14
|
+
*/
|
|
15
|
+
import { type DataSourceDefinition, type ResourceGraph, type StorageSourceDefinition } from "@rebasepro/types";
|
|
16
|
+
/** Databases in the graph, as the data layer's definitions. */
|
|
17
|
+
export declare function graphToDataSources(graph: ResourceGraph): DataSourceDefinition[];
|
|
18
|
+
/** Buckets in the graph, as the storage layer's definitions. */
|
|
19
|
+
export declare function graphToStorageSources(graph: ResourceGraph): StorageSourceDefinition[];
|
|
20
|
+
/** Topics in the graph, for the runtime to publish through and the worker to wire. */
|
|
21
|
+
export declare function graphTopics(graph: ResourceGraph): ResourceGraph["resources"];
|
|
22
|
+
/**
|
|
23
|
+
* Refuse a config still carrying a replaced key.
|
|
24
|
+
*
|
|
25
|
+
* Throws on the first one rather than collecting: unlike a manifest, where a
|
|
26
|
+
* reader wants every problem at once, this is a single edit per key and the
|
|
27
|
+
* message is long enough that three of them would bury each other.
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertNoReplacedResourceConfig(config: Record<string, unknown>): void;
|
|
30
|
+
/** The keys this refuses, for a doctor check and for the tests that pin them. */
|
|
31
|
+
export declare function replacedResourceConfigKeys(): string[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ResourceGraph } from "@rebasepro/types";
|
|
2
|
+
import { type LoadedBundle } from "./bundle.js";
|
|
3
|
+
/**
|
|
4
|
+
* Evaluate a bundle's resource declarations and return the graph.
|
|
5
|
+
*
|
|
6
|
+
* A project with no `resources.ts` is normal and returns whatever the config
|
|
7
|
+
* index already registered — which for most projects is nothing, and a single
|
|
8
|
+
* default database is then synthesised downstream exactly as before.
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadBundleResourceGraph(bundle: LoadedBundle): Promise<ResourceGraph>;
|
package/dist/boot/role.d.ts
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* a role that quietly runs no scheduler, or two roles that both provision the
|
|
14
14
|
* schema, are failures nothing in a boot log makes obvious.
|
|
15
15
|
*/
|
|
16
|
-
import type { RuntimeOwnershipOptions, RuntimeSurfaceOptions } from "../init/surfaces";
|
|
17
|
-
import type { FunctionSelection } from "../functions/selection";
|
|
16
|
+
import type { RuntimeOwnershipOptions, RuntimeSurfaceOptions } from "../init/surfaces.js";
|
|
17
|
+
import type { FunctionSelection } from "../functions/selection.js";
|
|
18
18
|
/** The four shapes a runtime process can boot in. */
|
|
19
19
|
export type RebaseRuntimeRole = "all" | "api" | "functions" | "worker";
|
|
20
20
|
/** Everything a role decides, resolved. */
|
|
@@ -34,6 +34,7 @@ export interface RoleEnv {
|
|
|
34
34
|
REBASE_ROLE?: RebaseRuntimeRole;
|
|
35
35
|
REBASE_CRON_SCHEDULER?: boolean;
|
|
36
36
|
REBASE_JOB_WORKERS?: boolean;
|
|
37
|
+
REBASE_RLS_AUDIT?: boolean;
|
|
37
38
|
REBASE_MIGRATE_ON_BOOT?: "none" | "ensure" | "push" | "";
|
|
38
39
|
REBASE_FUNCTIONS_ONLY?: string;
|
|
39
40
|
REBASE_FUNCTIONS_EXCLUDE?: string;
|
package/dist/boot/sources.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DataSourceDefinition, type StorageSourceDefinition } from "@rebasepro/types";
|
|
2
|
-
import type { BackendStorageConfig } from "../storage/types";
|
|
2
|
+
import type { BackendStorageConfig } from "../storage/types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Resolving *named* data and storage sources from the environment.
|
|
5
5
|
*
|
|
@@ -79,7 +79,13 @@ export declare function resolveDataSources(env: EnvBag, definitions: DataSourceD
|
|
|
79
79
|
* once, in `initializeStorage`, which logs precisely why storage is disabled.
|
|
80
80
|
* Duplicating it would mean two places to keep in agreement.
|
|
81
81
|
*/
|
|
82
|
-
export declare function resolveStorageBackend(env: EnvBag, key: string, engineHint: string | undefined, defaultBasePath: string
|
|
82
|
+
export declare function resolveStorageBackend(env: EnvBag, key: string, engineHint: string | undefined, defaultBasePath: string,
|
|
83
|
+
/**
|
|
84
|
+
* The credential set this source shares, from its declaration. Only the
|
|
85
|
+
* account-scoped bindings — the ones describing the provider rather than the
|
|
86
|
+
* bucket — consult it. See `StorageSourceDefinition.account`.
|
|
87
|
+
*/
|
|
88
|
+
accountHint?: string): BackendStorageConfig | undefined;
|
|
83
89
|
/**
|
|
84
90
|
* Resolve every server-transport storage source into a controller config map.
|
|
85
91
|
*
|
|
@@ -87,7 +87,7 @@ export declare function readPackageVersion(packageDir: string): string | undefin
|
|
|
87
87
|
* The version of `@rebasepro/server` this deployment is actually running.
|
|
88
88
|
*
|
|
89
89
|
* Resolved from the same roots the drivers are, and that is the point rather
|
|
90
|
-
* than a convenience. In a managed container `docker/entrypoint.mjs` replaces
|
|
90
|
+
* than a convenience. In a managed container `infra/docker/entrypoint.mjs` replaces
|
|
91
91
|
* `/bundle/node_modules/@rebasepro/server` with a link to the image's copy, so
|
|
92
92
|
* reading the manifest *through the bundle* reports the version that will
|
|
93
93
|
* really execute — which is exactly the number the driver has to be compared
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CollectionRegistry } from "@rebasepro/common";
|
|
2
|
-
import { CollectionRegistryInterface } from "../db/interfaces";
|
|
2
|
+
import { CollectionRegistryInterface } from "../db/interfaces.js";
|
|
3
3
|
/**
|
|
4
4
|
* Backend-agnostic collection registry.
|
|
5
5
|
* Satisfies CollectionRegistryInterface through inheritance from CollectionRegistry.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CollectionConfig, SecurityRule } from "@rebasepro/types";
|
|
2
|
-
import { type ValidateCollectionConfigOptions } from "./validate-config";
|
|
2
|
+
import { type ValidateCollectionConfigOptions } from "./validate-config.js";
|
|
3
3
|
/**
|
|
4
4
|
* The one definition of "the collections".
|
|
5
5
|
*
|
|
@@ -33,6 +33,19 @@
|
|
|
33
33
|
export type UnknownKeyPolicy = "warn" | "error" | "off";
|
|
34
34
|
export interface ConfigProblem {
|
|
35
35
|
severity: "error" | "warning";
|
|
36
|
+
/**
|
|
37
|
+
* What kind of wrong this is, because the two read very differently and the
|
|
38
|
+
* remedies differ.
|
|
39
|
+
*
|
|
40
|
+
* - `"key"` — a key this version does not read, whether renamed, removed or
|
|
41
|
+
* simply unrecognised. The feature it configures is absent; the config is
|
|
42
|
+
* otherwise coherent. `REBASE_STRICT_COLLECTION_CONFIG` governs how loud
|
|
43
|
+
* the unrecognised half of this is.
|
|
44
|
+
* - `"incoherent"` — every key is recognised and the *combination* cannot do
|
|
45
|
+
* what it says. That policy has no bearing on these, and saying it did
|
|
46
|
+
* sent people to an environment variable that would not have helped.
|
|
47
|
+
*/
|
|
48
|
+
kind: "key" | "incoherent";
|
|
36
49
|
/** Dotted path into the config, e.g. `posts.properties.author`. */
|
|
37
50
|
path: string;
|
|
38
51
|
message: string;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { createRequire as
|
|
2
|
-
import "process";
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import "./
|
|
6
|
-
import
|
|
1
|
+
import { createRequire as __rebaseCreateRequire } from "module";
|
|
2
|
+
import __rebaseProcess from "process";
|
|
3
|
+
globalThis.process ??= __rebaseProcess;
|
|
4
|
+
__rebaseCreateRequire(import.meta.url);
|
|
5
|
+
import { n as __exportAll } from "./rolldown-runtime-dW7B1o5h.js";
|
|
6
|
+
import "./src-Cdsw7DqV.js";
|
|
7
|
+
import { t as logger } from "./logger-DS03e908.js";
|
|
7
8
|
import { Hono } from "hono";
|
|
8
9
|
//#region ../types/src/types/project_manifest.ts
|
|
9
10
|
/** Header carrying the schema version an SDK was generated from. */
|
|
@@ -261,4 +262,4 @@ function createContractRoutes(config) {
|
|
|
261
262
|
//#endregion
|
|
262
263
|
export { createContractRoutes as n, computeSchemaVersion as r, contract_routes_exports as t };
|
|
263
264
|
|
|
264
|
-
//# sourceMappingURL=contract-routes-
|
|
265
|
+
//# sourceMappingURL=contract-routes-D8TvxPLo.js.map
|