@rebasepro/cli 0.25.0 → 0.25.1
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/{agent-setup-B5AKHOgt.js → agent-setup-BYb2Tbdz.js} +2 -2
- package/dist/{agent-setup-B5AKHOgt.js.map → agent-setup-BYb2Tbdz.js.map} +1 -1
- package/dist/{api-keys-Tm7zvAPe.js → api-keys-CSMbsmAn.js} +3 -4
- package/dist/{api-keys-Tm7zvAPe.js.map → api-keys-CSMbsmAn.js.map} +1 -1
- package/dist/{apps-BsU_ILbP.js → apps-iBXNZhVN.js} +6 -7
- package/dist/{apps-BsU_ILbP.js.map → apps-iBXNZhVN.js.map} +1 -1
- package/dist/{atlas-dev-database-OWtqnG7W.js → atlas-dev-database-BusbHP6n.js} +4 -4
- package/dist/{atlas-dev-database-OWtqnG7W.js.map → atlas-dev-database-BusbHP6n.js.map} +1 -1
- package/dist/{auth-Vl2hFKXP.js → auth-DRsTWPky.js} +6 -7
- package/dist/{auth-Vl2hFKXP.js.map → auth-DRsTWPky.js.map} +1 -1
- package/dist/{branch-pointer-9DnwkFJJ.js → branch-pointer-Bn_FjNld.js} +1 -1
- package/dist/{build-BBgT8EJZ.js → build-et7Rccxi.js} +6 -7
- package/dist/{build-BBgT8EJZ.js.map → build-et7Rccxi.js.map} +1 -1
- package/dist/{bundle-DtCCCr4w.js → bundle-DlqkDYSe.js} +3 -3
- package/dist/{bundle-DtCCCr4w.js.map → bundle-DlqkDYSe.js.map} +1 -1
- package/dist/{cloud-BpH0_bmV.js → cloud-B-ZIjHrA.js} +10 -11
- package/dist/{cloud-BpH0_bmV.js.map → cloud-B-ZIjHrA.js.map} +1 -1
- package/dist/commands/dev.d.ts +12 -0
- package/dist/commands/generate_sdk.d.ts +4 -2
- package/dist/commands/init.d.ts +20 -0
- package/dist/commands/start.d.ts +10 -0
- package/dist/commands/upgrade.d.ts +12 -0
- package/dist/{consent-ClRHmcxf.js → consent-BaB-eQKG.js} +2 -2
- package/dist/{consent-ClRHmcxf.js.map → consent-BaB-eQKG.js.map} +1 -1
- package/dist/{console-CEGm0XNc.js → console-BlD9kjFW.js} +4 -4
- package/dist/{console-CEGm0XNc.js.map → console-BlD9kjFW.js.map} +1 -1
- package/dist/{context-CyflUrKg.js → context-DHiiiJ5C.js} +3 -4
- package/dist/context-DHiiiJ5C.js.map +1 -0
- package/dist/{daemon-CknkDjd6.js → daemon-DDMRbz4T.js} +160 -5
- package/dist/daemon-DDMRbz4T.js.map +1 -0
- package/dist/{daemon-entry-CbLRrgzy.js → daemon-entry-zOC1revO.js} +6 -3
- package/dist/daemon-entry-zOC1revO.js.map +1 -0
- package/dist/{db-CRNpA5mH.js → db-9P6MnmdC.js} +90 -50
- package/dist/db-9P6MnmdC.js.map +1 -0
- package/dist/{derive-CsoFGAnK.js → derive-MTdClnkc.js} +2 -2
- package/dist/{derive-CsoFGAnK.js.map → derive-MTdClnkc.js.map} +1 -1
- package/dist/{dev-C0pbMmhS.js → dev-BDN_OKXA.js} +183 -23
- package/dist/dev-BDN_OKXA.js.map +1 -0
- package/dist/dev-db/daemon.d.ts +41 -0
- package/dist/dev-db/pull.d.ts +33 -5
- package/dist/dev-db/state.d.ts +9 -0
- package/dist/{dev-preflight-unHpiYO1.js → dev-preflight-FT9GbJVj.js} +73 -27
- package/dist/dev-preflight-FT9GbJVj.js.map +1 -0
- package/dist/{dev-server-B1UYifZJ.js → dev-server-CIZwAfZa.js} +14 -3
- package/dist/dev-server-CIZwAfZa.js.map +1 -0
- package/dist/{doctor-CATRdWm6.js → doctor-D8YXz7df.js} +6 -6
- package/dist/doctor-D8YXz7df.js.map +1 -0
- package/dist/{eject-DuasTr-F.js → eject-izG2KjMo.js} +3 -4
- package/dist/{eject-DuasTr-F.js.map → eject-izG2KjMo.js.map} +1 -1
- package/dist/{fold-static-hDHtDfTq.js → fold-static-CybSay_W.js} +3 -3
- package/dist/{fold-static-hDHtDfTq.js.map → fold-static-CybSay_W.js.map} +1 -1
- package/dist/{generate_sdk-Cvg5jjJF.js → generate_sdk-B4R65oUV.js} +21 -11
- package/dist/generate_sdk-B4R65oUV.js.map +1 -0
- package/dist/index.es.js +36 -37
- package/dist/index.es.js.map +1 -1
- package/dist/{init-BWAwHPtz.js → init-DYaeppEN.js} +50 -62
- package/dist/init-DYaeppEN.js.map +1 -0
- package/dist/invoked-command-CG_rIa_o.js +55 -0
- package/dist/invoked-command-CG_rIa_o.js.map +1 -0
- package/dist/last-dev-database-B_75fxZC.js +2 -0
- package/dist/{manifest-DRp0UVTj.js → manifest-nvPdLlJY.js} +2 -2
- package/dist/{manifest-DRp0UVTj.js.map → manifest-nvPdLlJY.js.map} +1 -1
- package/dist/{normalize-imports-BoBVh5tU.js → normalize-imports-BYw8ad87.js} +3 -3
- package/dist/{normalize-imports-BoBVh5tU.js.map → normalize-imports-BYw8ad87.js.map} +1 -1
- package/dist/{prepare-DdnU70z8.js → prepare-1rVNd2PF.js} +5 -4
- package/dist/{prepare-DdnU70z8.js.map → prepare-1rVNd2PF.js.map} +1 -1
- package/dist/project-g4K6kV1t.js +701 -0
- package/dist/project-g4K6kV1t.js.map +1 -0
- package/dist/{pull-C3PXduzl.js → pull-DDMpsZ5r.js} +131 -24
- package/dist/pull-DDMpsZ5r.js.map +1 -0
- package/dist/refusal-ReeeGP8a.js +26 -0
- package/dist/refusal-ReeeGP8a.js.map +1 -0
- package/dist/resolve-BQUAC3Wi.js +2 -0
- package/dist/{resources-BdNRDEAy.js → resources-CovP8AZ-.js} +4 -5
- package/dist/{resources-BdNRDEAy.js.map → resources-CovP8AZ-.js.map} +1 -1
- package/dist/{schema-B0-p6T1O.js → schema-nuxvvc50.js} +5 -6
- package/dist/{schema-B0-p6T1O.js.map → schema-nuxvvc50.js.map} +1 -1
- package/dist/{skills-DfnTeyRz.js → skills-DeUIsZcT.js} +3 -4
- package/dist/{skills-DfnTeyRz.js.map → skills-DeUIsZcT.js.map} +1 -1
- package/dist/{start-BmEZkS0n.js → start-RzZqDroW.js} +20 -7
- package/dist/start-RzZqDroW.js.map +1 -0
- package/dist/{state-CCB-FAQ9.js → state-CYdBvnwA.js} +3 -2
- package/dist/state-CYdBvnwA.js.map +1 -0
- package/dist/{status-BJ26yZOo.js → status-D9Zm88NZ.js} +8 -9
- package/dist/{status-BJ26yZOo.js.map → status-D9Zm88NZ.js.map} +1 -1
- package/dist/{storage-DKPUBTWG.js → storage-BB3umRfw.js} +3 -4
- package/dist/{storage-DKPUBTWG.js.map → storage-BB3umRfw.js.map} +1 -1
- package/dist/{telemetry-EMFRVRQi.js → telemetry-HfU5uAh1.js} +2 -2
- package/dist/{telemetry-EMFRVRQi.js.map → telemetry-HfU5uAh1.js.map} +1 -1
- package/dist/{telemetry-m9czTNGR.js → telemetry-TseNLk6X.js} +4 -4
- package/dist/{telemetry-m9czTNGR.js.map → telemetry-TseNLk6X.js.map} +1 -1
- package/dist/{upgrade-DjihWuZL.js → upgrade-apiPKKE_.js} +26 -4
- package/dist/{upgrade-DjihWuZL.js.map → upgrade-apiPKKE_.js.map} +1 -1
- package/dist/utils/args.d.ts +32 -3
- package/dist/utils/boot-retry.d.ts +41 -0
- package/dist/utils/dev-preflight.d.ts +34 -1
- package/dist/utils/dev-server.d.ts +11 -0
- package/dist/utils/project.d.ts +5 -1
- package/dist/utils/unknown-command.d.ts +4 -0
- package/package.json +7 -7
- package/templates/resource-graphs/blank.json +25 -0
- package/templates/resource-graphs/blog.json +28 -0
- package/templates/resource-graphs/ecommerce.json +28 -0
- package/templates/resource-graphs/headless.json +22 -0
- package/templates/template/.env.example +5 -4
- package/templates/template/frontend/src/App.tsx +10 -9
- package/dist/args-BX0YD14a.js +0 -266
- package/dist/args-BX0YD14a.js.map +0 -1
- package/dist/context-CyflUrKg.js.map +0 -1
- package/dist/daemon-CknkDjd6.js.map +0 -1
- package/dist/daemon-entry-CbLRrgzy.js.map +0 -1
- package/dist/db-CRNpA5mH.js.map +0 -1
- package/dist/dev-C0pbMmhS.js.map +0 -1
- package/dist/dev-preflight-unHpiYO1.js.map +0 -1
- package/dist/dev-server-B1UYifZJ.js.map +0 -1
- package/dist/doctor-CATRdWm6.js.map +0 -1
- package/dist/generate_sdk-Cvg5jjJF.js.map +0 -1
- package/dist/init-BWAwHPtz.js.map +0 -1
- package/dist/last-dev-database-c_dKz1S3.js +0 -2
- package/dist/project-Wp2zoyeN.js +0 -349
- package/dist/project-Wp2zoyeN.js.map +0 -1
- package/dist/pull-C3PXduzl.js.map +0 -1
- package/dist/resolve-CNQjsatH.js +0 -2
- package/dist/start-BmEZkS0n.js.map +0 -1
- package/dist/state-CCB-FAQ9.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eject-DuasTr-F.js","names":[],"sources":["../src/commands/eject.ts"],"sourcesContent":["/**\n * CLI command: rebase eject\n *\n * The supported route from the managed runtime to a custom one.\n *\n * Without it, `runtime: \"custom\"` is a mode a user can only reach by\n * hand-writing an entrypoint they have never seen. The template used to solve\n * that by scaffolding `backend/src/index.ts` into every project — ~190 lines\n * configuring CORS, auth, cookies, storage and history, which the managed\n * runtime never loads. It was the most important-looking file in a new project\n * and editing it did nothing.\n *\n * So the file moved here. A managed project does not carry it; a project that\n * asks for it gets it together with the Dockerfile and the manifest change that\n * make it actually run.\n *\n * There is deliberately no `rebase uneject`. Going back is deleting two files\n * and editing one line, and a command that silently discarded a user's server\n * code would be worse than its absence.\n */\nimport chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { RebaseBackendAppConfig } from \"@rebasepro/types\";\nimport { requireProjectRoot } from \"../utils/project\";\nimport { findBackendApp, loadManifest, ManifestError, resolveBackendPaths, writeManifest } from \"../manifest\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/** Walk up to the package root, which holds `templates/`. */\nfunction findCliRoot(from: string): string | null {\n const root = path.parse(from).root;\n let dir = from;\n while (dir && dir !== root) {\n if (fs.existsSync(path.join(dir, \"templates\", \"eject\"))) return dir;\n dir = path.dirname(dir);\n }\n return null;\n}\n\n/**\n * The two ways one project's payload differs from another's.\n *\n * Neither is a flag: both were decided at `rebase init` time. `--headless`\n * deletes `config/collections`, `backend/src/schema.generated.ts` and\n * `frontend/`, so a payload that assumes them emits an entrypoint importing\n * three files that are not there and a Dockerfile whose first `COPY` fails.\n */\ninterface ProjectShape {\n /**\n * Collections declared in code, under `<config>/collections`. Without them\n * the server derives its API from the live database instead — the same\n * signal `rebase build` reads.\n */\n collections: boolean;\n /** A `frontend` workspace for the image to build and the entrypoint to serve. */\n frontend: boolean;\n}\n\n/**\n * The block names the payload may switch on. A typo has to be an error.\n *\n * Typed as keys of {@link ProjectShape}, which is what makes that true: `as\n * const` alone gave these two string literals and tied them to nothing, so a\n * flag renamed on the interface left this list naming a block that no longer\n * exists, and the template kept switching on it.\n */\nconst SHAPE_FLAGS: readonly (keyof ProjectShape)[] = [\"collections\", \"frontend\"];\n\n/** Narrow a marker name to a flag, having checked it is one. */\nfunction isShapeFlag(name: string): name is keyof ProjectShape {\n return (SHAPE_FLAGS as readonly string[]).includes(name);\n}\n\n/**\n * Render one payload file for this project.\n *\n * The payload is one set of files rather than one per flavour, because the\n * flavours differ by about a dozen lines and two copies of a 230-line\n * entrypoint are how copies drift — the payload had already drifted from\n * `app/backend/src/index.ts` over `cronsDir`, which silently stopped every cron\n * job in an ejected project. So both branches live in the file, marked with\n * lines that are comments in TypeScript, YAML and Dockerfiles alike:\n *\n * // {{#collections}}\n * import { tables } from \"./schema.generated.js\";\n * // {{/collections}}\n * // {{^collections}}\n * // No schema module: this project introspects the database.\n * // {{/collections}}\n *\n * `{{#name}}` keeps its block when the flag is on, `{{^name}}` when it is off,\n * and the marker lines themselves never reach the user. The template stays\n * valid TypeScript with every marker line removed, which is the flavour a\n * typechecker would see.\n */\nexport function renderPayload(contents: string, shape: ProjectShape, projectName: string): string {\n const out: string[] = [];\n let open: { name: string; keep: boolean } | null = null;\n\n for (const line of contents.split(\"\\n\")) {\n const marker = /^\\s*(?:\\/\\/|#)\\s*\\{\\{([#^/])([A-Za-z]+)\\}\\}\\s*$/.exec(line);\n if (!marker) {\n if (!open || open.keep) out.push(line);\n continue;\n }\n const [, kind, name] = marker;\n if (kind === \"/\") {\n if (!open || open.name !== name) {\n throw new Error(`Eject template: {{/${name}}} does not close an open block.`);\n }\n open = null;\n continue;\n }\n if (open) throw new Error(`Eject template: {{${kind}${name}}} inside an open ${open.name} block.`);\n if (!isShapeFlag(name)) {\n throw new Error(`Eject template: unknown block {{${kind}${name}}}.`);\n }\n // `shape[name]` directly: the check above narrows `name` to a key of\n // `ProjectShape`, which is what the `as unknown as Record<string,\n // boolean>` on the shape was standing in for — and that cast also meant\n // nothing checked that the block names and the interface agree.\n open = { name,\nkeep: kind === \"#\" ? shape[name] === true : shape[name] !== true };\n }\n\n if (open) throw new Error(`Eject template: {{#${open.name}}} was never closed.`);\n // A replacer function: the name is read from package.json unchecked, and a\n // replacement string would expand any `$&`, `$'` or `$$` in it.\n return out.join(\"\\n\").replace(/\\{\\{PROJECT_NAME\\}\\}/g, () => projectName);\n}\n\n/** Files the eject payload contributes, as `<source> → <destination>`. */\nconst PAYLOAD: { from: string; to: string; overwrite: boolean }[] = [\n // The entrypoint IS the point of ejecting, so it replaces whatever is\n // there — but only with `--force`, and only after keeping the old file as\n // `.bak`. `runtime: \"custom\"` (the guard below) means \"already ejected\",\n // not \"nobody wrote a server here\": a managed project can have a\n // hand-written `backend/src/index.ts` that `rebase dev` has been running.\n { from: \"backend/src/index.ts\",\nto: \"backend/src/index.ts\",\noverwrite: true },\n { from: \"backend/src/env.ts\",\nto: \"backend/src/env.ts\",\noverwrite: true },\n // The declarations the emitted server imports. Never overwritten — a\n // project that already declares its resources owns that file, and replacing\n // it would silently drop every bucket and database it named. Written when\n // absent because the entrypoint imports it unconditionally: an ejected\n // server that cannot resolve its own resources does not start.\n { from: \"config/resources.ts\",\nto: \"config/resources.ts\",\noverwrite: false },\n // Never overwritten: a Dockerfile someone already wrote is theirs, and so is\n // a compose file they have edited. The scaffolded `docker-compose.yml` is\n // deliberately left alone — it runs the managed shape, and going back should\n // stay a one-line change rather than a restore from git.\n { from: \"Dockerfile\",\nto: \"Dockerfile\",\noverwrite: false },\n { from: \"docker-compose.custom.yml\",\nto: \"docker-compose.custom.yml\",\noverwrite: false }\n];\n\n/**\n * The project's name, for the `{{PROJECT_NAME}}` the payload carries.\n *\n * Falls back to the directory name — a compose project name is cosmetic, and a\n * missing or unreadable package.json is not a reason to refuse to eject.\n */\nfunction projectNameOf(projectRoot: string): string {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(projectRoot, \"package.json\"), \"utf8\"));\n if (typeof pkg.name === \"string\" && pkg.name.trim()) return pkg.name.trim();\n } catch {\n // fall through\n }\n return path.basename(projectRoot);\n}\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase eject\")} — take ownership of the server process\n\nWrites the backend entrypoint and a Dockerfile into this project, and flips its\nbackend to ${chalk.cyan('runtime: \"custom\"')}. From then on this repository builds its own\nimage: platform runtime upgrades no longer reach it, and CORS, auth wiring,\nstorage and shutdown become yours to configure.\n\n${chalk.bold(\"Usage\")}\n rebase eject [app] Take ownership of the server process\n\n${chalk.bold(\"Options\")}\n --dry-run List what would change, and change nothing\n --force Replace an existing backend/src/index.ts or\n env.ts, keeping the current file as <name>.bak\n -h, --help Show this help\n`.trim());\n}\n\nexport async function ejectCommand(rawArgs: string[] = []): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n const { flags: args, positionals } = parseCommandArgs({\n spec: {\n \"--dry-run\": Boolean,\n \"--force\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"eject\",\n maxPositionals: 1\n });\n\n const projectRoot = requireProjectRoot();\n const dryRun = Boolean(args[\"--dry-run\"]);\n const force = Boolean(args[\"--force\"]);\n // Strict parsing rejects an undeclared flag rather than filing it under the\n // positionals, so the first one is the app — there is nothing to filter out.\n const requested = positionals[0];\n\n let loaded;\n try {\n loaded = loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\n console.error(chalk.red(`✗ ${err.message}`));\n for (const issue of err.issues) {\n console.error(chalk.dim(` ${issue.path}: ${issue.message}`));\n }\n process.exit(1);\n }\n throw err;\n }\n\n const { manifest } = loaded;\n\n let appName: string;\n let app: RebaseBackendAppConfig;\n\n if (requested) {\n const declared = manifest.apps[requested];\n if (!declared) {\n console.error(chalk.red(`✗ No app named \"${requested}\" in rebase.json.`));\n console.error(chalk.dim(` Declared: ${Object.keys(manifest.apps).join(\", \") || \"(none)\"}`));\n process.exit(1);\n }\n if (declared.type !== \"backend\") {\n // Ejecting is about who runs the server. A static app has no server.\n console.error(chalk.red(`✗ \"${requested}\" is a ${declared.type} app — only a backend can be ejected.`));\n process.exit(1);\n }\n appName = requested;\n app = declared;\n } else {\n const backend = findBackendApp(manifest);\n if (!backend) {\n console.error(chalk.red(\"✗ This repository declares no backend app.\"));\n console.error(chalk.dim(\" Only the repository that declares the backend chooses its runtime.\"));\n process.exit(1);\n }\n appName = backend.name;\n app = backend.app;\n }\n\n if (app.runtime === \"custom\") {\n console.error(chalk.red(`✗ \"${appName}\" is already ejected — it declares runtime: \"custom\".`));\n console.error(chalk.dim(` Its entrypoint is ${app.dockerfile ?? \"Dockerfile\"} and backend/src/index.ts.`));\n process.exit(1);\n }\n\n const cliRoot = findCliRoot(__dirname);\n if (!cliRoot) {\n console.error(chalk.red(\"✗ Could not locate the eject templates. Reinstall @rebasepro/cli.\"));\n process.exit(1);\n }\n const payloadDir = path.join(cliRoot!, \"templates\", \"eject\");\n\n // What the payload has to look like here. Read from the project rather than\n // asked for: `--headless` left no collections and no frontend, and an\n // entrypoint importing either would not compile.\n const paths = resolveBackendPaths(app, projectRoot);\n const shape: ProjectShape = {\n collections: paths.hasCollections,\n frontend: fs.existsSync(path.join(projectRoot, \"frontend\"))\n };\n\n // Decide everything before writing anything, so --dry-run and the real run\n // report the same list and a mid-way failure cannot leave a half-ejected\n // project.\n const planned: { to: string; action: \"write\" | \"keep\" | \"overwrite\" }[] = [];\n const blocked: string[] = [];\n for (const file of PAYLOAD) {\n const source = path.join(payloadDir, file.from);\n if (!fs.existsSync(source)) {\n console.error(chalk.red(`✗ The eject template is missing ${file.from}. Reinstall @rebasepro/cli.`));\n process.exit(1);\n }\n const exists = fs.existsSync(path.join(projectRoot, file.to));\n if (exists && file.overwrite && !force) blocked.push(file.to);\n planned.push({\n to: file.to,\n action: !exists ? \"write\" : file.overwrite ? \"overwrite\" : \"keep\"\n });\n }\n\n if (blocked.length > 0) {\n // A managed backend never loads `backend/src/index.ts`, but `rebase dev`\n // does — it picks the entrypoint by file existence — so this file is very\n // often a server someone is running and editing. Replacing it without\n // being asked is the one unrecoverable thing this command could do.\n console.error(chalk.red(\"✗ Ejecting would replace a file this project already has:\"));\n for (const item of blocked) console.error(chalk.red(` ${item}`));\n console.error(chalk.dim(\" Eject writes its own entrypoint — it does not adopt yours.\"));\n console.error(chalk.dim(\" Move the file aside, or re-run with --force, which keeps the current\"));\n console.error(chalk.dim(\" contents as <name>.bak.\"));\n process.exit(1);\n }\n\n if (dryRun) {\n console.log(chalk.bold(`Would eject \"${appName}\" to a custom runtime:`));\n console.log(\"\");\n for (const item of planned) {\n if (item.action === \"write\") console.log(` ${chalk.green(\"write\")} ${item.to}`);\n else if (item.action === \"overwrite\") {\n console.log(` ${chalk.yellow(\"overwrite\")} ${item.to} ${chalk.dim(`(kept as ${item.to}.bak)`)}`);\n } else console.log(` ${chalk.dim(\"keep\")} ${item.to} ${chalk.dim(\"(already exists)\")}`);\n }\n console.log(` ${chalk.green(\"write\")} rebase.json ${chalk.dim('(runtime: \"custom\")')}`);\n // Not part of the payload table, but it is changed on the real run, and\n // a dry run's whole purpose is to enumerate what changes.\n if (fs.existsSync(path.join(projectRoot, \"backend\", \"package.json\"))) {\n console.log(` ${chalk.green(\"write\")} backend/package.json ${chalk.dim(\"(main, dev and start scripts)\")}`);\n }\n console.log(\"\");\n console.log(chalk.dim(\"Nothing was changed.\"));\n return;\n }\n\n const projectName = projectNameOf(projectRoot);\n const backups: string[] = [];\n for (const [index, file] of PAYLOAD.entries()) {\n if (planned[index].action === \"keep\") continue;\n const destination = path.join(projectRoot, file.to);\n if (planned[index].action === \"overwrite\") {\n fs.copyFileSync(destination, `${destination}.bak`);\n backups.push(`${file.to}.bak`);\n }\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n const contents = renderPayload(\n fs.readFileSync(path.join(payloadDir, file.from), \"utf8\"),\n shape,\n projectName\n );\n fs.writeFileSync(destination, contents, \"utf8\");\n }\n\n const dockerfile = app.dockerfile ?? \"Dockerfile\";\n manifest.apps[appName] = {\n ...app,\n runtime: \"custom\",\n dockerfile,\n port: app.port ?? 8080\n };\n writeManifest(projectRoot, manifest);\n\n // The backend workspace stops being a package the runtime reads and becomes\n // one that is run. Its scripts have to say so, or `npm start` in the image\n // has nothing to call.\n restoreBackendScripts(projectRoot);\n\n console.log(\"\");\n console.log(chalk.green(`✓ Ejected \"${appName}\" to a custom runtime.`));\n console.log(\"\");\n console.log(` ${chalk.cyan(\"backend/src/index.ts\".padEnd(26))} your entrypoint — the runtime no longer boots the bundle`);\n console.log(` ${chalk.cyan(\"backend/src/env.ts\".padEnd(26))} the environment it reads`);\n console.log(` ${chalk.cyan(dockerfile.padEnd(26))} your image`);\n console.log(` ${chalk.cyan(\"docker-compose.custom.yml\".padEnd(26))} runs it`);\n console.log(` ${chalk.cyan(\"rebase.json\".padEnd(26))} runtime: custom`);\n for (const backup of backups) {\n console.log(` ${chalk.cyan(backup.padEnd(26))} what was there before`);\n }\n console.log(\"\");\n console.log(chalk.yellow(\" You now own CORS, auth wiring, storage and shutdown. Platform runtime\"));\n console.log(chalk.yellow(\" upgrades no longer reach this project.\"));\n if (!shape.collections) {\n console.log(chalk.yellow(\" This project declares no collections, so the entrypoint derives them\"));\n console.log(chalk.yellow(\" from the live database, as the managed runtime did.\"));\n }\n console.log(\"\");\n console.log(chalk.dim(` ${chalk.cyan(\"docker compose -f docker-compose.custom.yml up --build\")}`));\n console.log(chalk.dim(\" docker-compose.yml is untouched — it still runs the managed shape if you go back.\"));\n console.log(\"\");\n}\n\n/**\n * Point the backend workspace's scripts at the entrypoint that now exists.\n *\n * A managed project's backend package deliberately declares no `main` and no\n * `start`: there is no entrypoint to name. Ejecting creates one.\n */\nfunction restoreBackendScripts(projectRoot: string): void {\n const packagePath = path.join(projectRoot, \"backend\", \"package.json\");\n if (!fs.existsSync(packagePath)) return;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(fs.readFileSync(packagePath, \"utf8\"));\n } catch {\n // A malformed package.json is the user's to fix, and refusing to finish\n // the eject over it would leave the project half-changed.\n console.log(chalk.yellow(\" ⚠ backend/package.json is not valid JSON — its scripts were left alone.\"));\n return;\n }\n\n const scripts = (parsed.scripts ?? {}) as Record<string, string>;\n parsed.main ??= \"src/index.ts\";\n scripts.dev ??= 'tsx watch --include=\"../config/**/*\" --include=\"./functions/**/*\" src/index.ts';\n scripts.start ??= \"node dist/backend/src/index.js\";\n parsed.scripts = scripts;\n\n fs.writeFileSync(packagePath, `${JSON.stringify(parsed, null, 4)}\\n`, \"utf8\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eject-izG2KjMo.js","names":[],"sources":["../src/commands/eject.ts"],"sourcesContent":["/**\n * CLI command: rebase eject\n *\n * The supported route from the managed runtime to a custom one.\n *\n * Without it, `runtime: \"custom\"` is a mode a user can only reach by\n * hand-writing an entrypoint they have never seen. The template used to solve\n * that by scaffolding `backend/src/index.ts` into every project — ~190 lines\n * configuring CORS, auth, cookies, storage and history, which the managed\n * runtime never loads. It was the most important-looking file in a new project\n * and editing it did nothing.\n *\n * So the file moved here. A managed project does not carry it; a project that\n * asks for it gets it together with the Dockerfile and the manifest change that\n * make it actually run.\n *\n * There is deliberately no `rebase uneject`. Going back is deleting two files\n * and editing one line, and a command that silently discarded a user's server\n * code would be worse than its absence.\n */\nimport chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { RebaseBackendAppConfig } from \"@rebasepro/types\";\nimport { requireProjectRoot } from \"../utils/project\";\nimport { findBackendApp, loadManifest, ManifestError, resolveBackendPaths, writeManifest } from \"../manifest\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/** Walk up to the package root, which holds `templates/`. */\nfunction findCliRoot(from: string): string | null {\n const root = path.parse(from).root;\n let dir = from;\n while (dir && dir !== root) {\n if (fs.existsSync(path.join(dir, \"templates\", \"eject\"))) return dir;\n dir = path.dirname(dir);\n }\n return null;\n}\n\n/**\n * The two ways one project's payload differs from another's.\n *\n * Neither is a flag: both were decided at `rebase init` time. `--headless`\n * deletes `config/collections`, `backend/src/schema.generated.ts` and\n * `frontend/`, so a payload that assumes them emits an entrypoint importing\n * three files that are not there and a Dockerfile whose first `COPY` fails.\n */\ninterface ProjectShape {\n /**\n * Collections declared in code, under `<config>/collections`. Without them\n * the server derives its API from the live database instead — the same\n * signal `rebase build` reads.\n */\n collections: boolean;\n /** A `frontend` workspace for the image to build and the entrypoint to serve. */\n frontend: boolean;\n}\n\n/**\n * The block names the payload may switch on. A typo has to be an error.\n *\n * Typed as keys of {@link ProjectShape}, which is what makes that true: `as\n * const` alone gave these two string literals and tied them to nothing, so a\n * flag renamed on the interface left this list naming a block that no longer\n * exists, and the template kept switching on it.\n */\nconst SHAPE_FLAGS: readonly (keyof ProjectShape)[] = [\"collections\", \"frontend\"];\n\n/** Narrow a marker name to a flag, having checked it is one. */\nfunction isShapeFlag(name: string): name is keyof ProjectShape {\n return (SHAPE_FLAGS as readonly string[]).includes(name);\n}\n\n/**\n * Render one payload file for this project.\n *\n * The payload is one set of files rather than one per flavour, because the\n * flavours differ by about a dozen lines and two copies of a 230-line\n * entrypoint are how copies drift — the payload had already drifted from\n * `app/backend/src/index.ts` over `cronsDir`, which silently stopped every cron\n * job in an ejected project. So both branches live in the file, marked with\n * lines that are comments in TypeScript, YAML and Dockerfiles alike:\n *\n * // {{#collections}}\n * import { tables } from \"./schema.generated.js\";\n * // {{/collections}}\n * // {{^collections}}\n * // No schema module: this project introspects the database.\n * // {{/collections}}\n *\n * `{{#name}}` keeps its block when the flag is on, `{{^name}}` when it is off,\n * and the marker lines themselves never reach the user. The template stays\n * valid TypeScript with every marker line removed, which is the flavour a\n * typechecker would see.\n */\nexport function renderPayload(contents: string, shape: ProjectShape, projectName: string): string {\n const out: string[] = [];\n let open: { name: string; keep: boolean } | null = null;\n\n for (const line of contents.split(\"\\n\")) {\n const marker = /^\\s*(?:\\/\\/|#)\\s*\\{\\{([#^/])([A-Za-z]+)\\}\\}\\s*$/.exec(line);\n if (!marker) {\n if (!open || open.keep) out.push(line);\n continue;\n }\n const [, kind, name] = marker;\n if (kind === \"/\") {\n if (!open || open.name !== name) {\n throw new Error(`Eject template: {{/${name}}} does not close an open block.`);\n }\n open = null;\n continue;\n }\n if (open) throw new Error(`Eject template: {{${kind}${name}}} inside an open ${open.name} block.`);\n if (!isShapeFlag(name)) {\n throw new Error(`Eject template: unknown block {{${kind}${name}}}.`);\n }\n // `shape[name]` directly: the check above narrows `name` to a key of\n // `ProjectShape`, which is what the `as unknown as Record<string,\n // boolean>` on the shape was standing in for — and that cast also meant\n // nothing checked that the block names and the interface agree.\n open = { name,\nkeep: kind === \"#\" ? shape[name] === true : shape[name] !== true };\n }\n\n if (open) throw new Error(`Eject template: {{#${open.name}}} was never closed.`);\n // A replacer function: the name is read from package.json unchecked, and a\n // replacement string would expand any `$&`, `$'` or `$$` in it.\n return out.join(\"\\n\").replace(/\\{\\{PROJECT_NAME\\}\\}/g, () => projectName);\n}\n\n/** Files the eject payload contributes, as `<source> → <destination>`. */\nconst PAYLOAD: { from: string; to: string; overwrite: boolean }[] = [\n // The entrypoint IS the point of ejecting, so it replaces whatever is\n // there — but only with `--force`, and only after keeping the old file as\n // `.bak`. `runtime: \"custom\"` (the guard below) means \"already ejected\",\n // not \"nobody wrote a server here\": a managed project can have a\n // hand-written `backend/src/index.ts` that `rebase dev` has been running.\n { from: \"backend/src/index.ts\",\nto: \"backend/src/index.ts\",\noverwrite: true },\n { from: \"backend/src/env.ts\",\nto: \"backend/src/env.ts\",\noverwrite: true },\n // The declarations the emitted server imports. Never overwritten — a\n // project that already declares its resources owns that file, and replacing\n // it would silently drop every bucket and database it named. Written when\n // absent because the entrypoint imports it unconditionally: an ejected\n // server that cannot resolve its own resources does not start.\n { from: \"config/resources.ts\",\nto: \"config/resources.ts\",\noverwrite: false },\n // Never overwritten: a Dockerfile someone already wrote is theirs, and so is\n // a compose file they have edited. The scaffolded `docker-compose.yml` is\n // deliberately left alone — it runs the managed shape, and going back should\n // stay a one-line change rather than a restore from git.\n { from: \"Dockerfile\",\nto: \"Dockerfile\",\noverwrite: false },\n { from: \"docker-compose.custom.yml\",\nto: \"docker-compose.custom.yml\",\noverwrite: false }\n];\n\n/**\n * The project's name, for the `{{PROJECT_NAME}}` the payload carries.\n *\n * Falls back to the directory name — a compose project name is cosmetic, and a\n * missing or unreadable package.json is not a reason to refuse to eject.\n */\nfunction projectNameOf(projectRoot: string): string {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(projectRoot, \"package.json\"), \"utf8\"));\n if (typeof pkg.name === \"string\" && pkg.name.trim()) return pkg.name.trim();\n } catch {\n // fall through\n }\n return path.basename(projectRoot);\n}\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase eject\")} — take ownership of the server process\n\nWrites the backend entrypoint and a Dockerfile into this project, and flips its\nbackend to ${chalk.cyan('runtime: \"custom\"')}. From then on this repository builds its own\nimage: platform runtime upgrades no longer reach it, and CORS, auth wiring,\nstorage and shutdown become yours to configure.\n\n${chalk.bold(\"Usage\")}\n rebase eject [app] Take ownership of the server process\n\n${chalk.bold(\"Options\")}\n --dry-run List what would change, and change nothing\n --force Replace an existing backend/src/index.ts or\n env.ts, keeping the current file as <name>.bak\n -h, --help Show this help\n`.trim());\n}\n\nexport async function ejectCommand(rawArgs: string[] = []): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n\n const { flags: args, positionals } = parseCommandArgs({\n spec: {\n \"--dry-run\": Boolean,\n \"--force\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"eject\",\n maxPositionals: 1\n });\n\n const projectRoot = requireProjectRoot();\n const dryRun = Boolean(args[\"--dry-run\"]);\n const force = Boolean(args[\"--force\"]);\n // Strict parsing rejects an undeclared flag rather than filing it under the\n // positionals, so the first one is the app — there is nothing to filter out.\n const requested = positionals[0];\n\n let loaded;\n try {\n loaded = loadManifest(projectRoot);\n } catch (err) {\n if (err instanceof ManifestError) {\n console.error(chalk.red(`✗ ${err.message}`));\n for (const issue of err.issues) {\n console.error(chalk.dim(` ${issue.path}: ${issue.message}`));\n }\n process.exit(1);\n }\n throw err;\n }\n\n const { manifest } = loaded;\n\n let appName: string;\n let app: RebaseBackendAppConfig;\n\n if (requested) {\n const declared = manifest.apps[requested];\n if (!declared) {\n console.error(chalk.red(`✗ No app named \"${requested}\" in rebase.json.`));\n console.error(chalk.dim(` Declared: ${Object.keys(manifest.apps).join(\", \") || \"(none)\"}`));\n process.exit(1);\n }\n if (declared.type !== \"backend\") {\n // Ejecting is about who runs the server. A static app has no server.\n console.error(chalk.red(`✗ \"${requested}\" is a ${declared.type} app — only a backend can be ejected.`));\n process.exit(1);\n }\n appName = requested;\n app = declared;\n } else {\n const backend = findBackendApp(manifest);\n if (!backend) {\n console.error(chalk.red(\"✗ This repository declares no backend app.\"));\n console.error(chalk.dim(\" Only the repository that declares the backend chooses its runtime.\"));\n process.exit(1);\n }\n appName = backend.name;\n app = backend.app;\n }\n\n if (app.runtime === \"custom\") {\n console.error(chalk.red(`✗ \"${appName}\" is already ejected — it declares runtime: \"custom\".`));\n console.error(chalk.dim(` Its entrypoint is ${app.dockerfile ?? \"Dockerfile\"} and backend/src/index.ts.`));\n process.exit(1);\n }\n\n const cliRoot = findCliRoot(__dirname);\n if (!cliRoot) {\n console.error(chalk.red(\"✗ Could not locate the eject templates. Reinstall @rebasepro/cli.\"));\n process.exit(1);\n }\n const payloadDir = path.join(cliRoot!, \"templates\", \"eject\");\n\n // What the payload has to look like here. Read from the project rather than\n // asked for: `--headless` left no collections and no frontend, and an\n // entrypoint importing either would not compile.\n const paths = resolveBackendPaths(app, projectRoot);\n const shape: ProjectShape = {\n collections: paths.hasCollections,\n frontend: fs.existsSync(path.join(projectRoot, \"frontend\"))\n };\n\n // Decide everything before writing anything, so --dry-run and the real run\n // report the same list and a mid-way failure cannot leave a half-ejected\n // project.\n const planned: { to: string; action: \"write\" | \"keep\" | \"overwrite\" }[] = [];\n const blocked: string[] = [];\n for (const file of PAYLOAD) {\n const source = path.join(payloadDir, file.from);\n if (!fs.existsSync(source)) {\n console.error(chalk.red(`✗ The eject template is missing ${file.from}. Reinstall @rebasepro/cli.`));\n process.exit(1);\n }\n const exists = fs.existsSync(path.join(projectRoot, file.to));\n if (exists && file.overwrite && !force) blocked.push(file.to);\n planned.push({\n to: file.to,\n action: !exists ? \"write\" : file.overwrite ? \"overwrite\" : \"keep\"\n });\n }\n\n if (blocked.length > 0) {\n // A managed backend never loads `backend/src/index.ts`, but `rebase dev`\n // does — it picks the entrypoint by file existence — so this file is very\n // often a server someone is running and editing. Replacing it without\n // being asked is the one unrecoverable thing this command could do.\n console.error(chalk.red(\"✗ Ejecting would replace a file this project already has:\"));\n for (const item of blocked) console.error(chalk.red(` ${item}`));\n console.error(chalk.dim(\" Eject writes its own entrypoint — it does not adopt yours.\"));\n console.error(chalk.dim(\" Move the file aside, or re-run with --force, which keeps the current\"));\n console.error(chalk.dim(\" contents as <name>.bak.\"));\n process.exit(1);\n }\n\n if (dryRun) {\n console.log(chalk.bold(`Would eject \"${appName}\" to a custom runtime:`));\n console.log(\"\");\n for (const item of planned) {\n if (item.action === \"write\") console.log(` ${chalk.green(\"write\")} ${item.to}`);\n else if (item.action === \"overwrite\") {\n console.log(` ${chalk.yellow(\"overwrite\")} ${item.to} ${chalk.dim(`(kept as ${item.to}.bak)`)}`);\n } else console.log(` ${chalk.dim(\"keep\")} ${item.to} ${chalk.dim(\"(already exists)\")}`);\n }\n console.log(` ${chalk.green(\"write\")} rebase.json ${chalk.dim('(runtime: \"custom\")')}`);\n // Not part of the payload table, but it is changed on the real run, and\n // a dry run's whole purpose is to enumerate what changes.\n if (fs.existsSync(path.join(projectRoot, \"backend\", \"package.json\"))) {\n console.log(` ${chalk.green(\"write\")} backend/package.json ${chalk.dim(\"(main, dev and start scripts)\")}`);\n }\n console.log(\"\");\n console.log(chalk.dim(\"Nothing was changed.\"));\n return;\n }\n\n const projectName = projectNameOf(projectRoot);\n const backups: string[] = [];\n for (const [index, file] of PAYLOAD.entries()) {\n if (planned[index].action === \"keep\") continue;\n const destination = path.join(projectRoot, file.to);\n if (planned[index].action === \"overwrite\") {\n fs.copyFileSync(destination, `${destination}.bak`);\n backups.push(`${file.to}.bak`);\n }\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n const contents = renderPayload(\n fs.readFileSync(path.join(payloadDir, file.from), \"utf8\"),\n shape,\n projectName\n );\n fs.writeFileSync(destination, contents, \"utf8\");\n }\n\n const dockerfile = app.dockerfile ?? \"Dockerfile\";\n manifest.apps[appName] = {\n ...app,\n runtime: \"custom\",\n dockerfile,\n port: app.port ?? 8080\n };\n writeManifest(projectRoot, manifest);\n\n // The backend workspace stops being a package the runtime reads and becomes\n // one that is run. Its scripts have to say so, or `npm start` in the image\n // has nothing to call.\n restoreBackendScripts(projectRoot);\n\n console.log(\"\");\n console.log(chalk.green(`✓ Ejected \"${appName}\" to a custom runtime.`));\n console.log(\"\");\n console.log(` ${chalk.cyan(\"backend/src/index.ts\".padEnd(26))} your entrypoint — the runtime no longer boots the bundle`);\n console.log(` ${chalk.cyan(\"backend/src/env.ts\".padEnd(26))} the environment it reads`);\n console.log(` ${chalk.cyan(dockerfile.padEnd(26))} your image`);\n console.log(` ${chalk.cyan(\"docker-compose.custom.yml\".padEnd(26))} runs it`);\n console.log(` ${chalk.cyan(\"rebase.json\".padEnd(26))} runtime: custom`);\n for (const backup of backups) {\n console.log(` ${chalk.cyan(backup.padEnd(26))} what was there before`);\n }\n console.log(\"\");\n console.log(chalk.yellow(\" You now own CORS, auth wiring, storage and shutdown. Platform runtime\"));\n console.log(chalk.yellow(\" upgrades no longer reach this project.\"));\n if (!shape.collections) {\n console.log(chalk.yellow(\" This project declares no collections, so the entrypoint derives them\"));\n console.log(chalk.yellow(\" from the live database, as the managed runtime did.\"));\n }\n console.log(\"\");\n console.log(chalk.dim(` ${chalk.cyan(\"docker compose -f docker-compose.custom.yml up --build\")}`));\n console.log(chalk.dim(\" docker-compose.yml is untouched — it still runs the managed shape if you go back.\"));\n console.log(\"\");\n}\n\n/**\n * Point the backend workspace's scripts at the entrypoint that now exists.\n *\n * A managed project's backend package deliberately declares no `main` and no\n * `start`: there is no entrypoint to name. Ejecting creates one.\n */\nfunction restoreBackendScripts(projectRoot: string): void {\n const packagePath = path.join(projectRoot, \"backend\", \"package.json\");\n if (!fs.existsSync(packagePath)) return;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(fs.readFileSync(packagePath, \"utf8\"));\n } catch {\n // A malformed package.json is the user's to fix, and refusing to finish\n // the eject over it would leave the project half-changed.\n console.log(chalk.yellow(\" ⚠ backend/package.json is not valid JSON — its scripts were left alone.\"));\n return;\n }\n\n const scripts = (parsed.scripts ?? {}) as Record<string, string>;\n parsed.main ??= \"src/index.ts\";\n scripts.dev ??= 'tsx watch --include=\"../config/**/*\" --include=\"./functions/**/*\" src/index.ts';\n scripts.start ??= \"node dist/backend/src/index.js\";\n parsed.scripts = scripts;\n\n fs.writeFileSync(packagePath, `${JSON.stringify(parsed, null, 4)}\\n`, \"utf8\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;;AAG7D,SAAS,YAAY,MAA6B;CAC9C,MAAM,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC;CAC9B,IAAI,MAAM;CACV,OAAO,OAAO,QAAQ,MAAM;EACxB,IAAI,GAAG,WAAW,KAAK,KAAK,KAAK,aAAa,OAAO,CAAC,GAAG,OAAO;EAChE,MAAM,KAAK,QAAQ,GAAG;CAC1B;CACA,OAAO;AACX;;;;;;;;;AA6BA,IAAM,cAA+C,CAAC,eAAe,UAAU;;AAG/E,SAAS,YAAY,MAA0C;CAC3D,OAAQ,YAAkC,SAAS,IAAI;AAC3D;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,cAAc,UAAkB,OAAqB,aAA6B;CAC9F,MAAM,MAAgB,CAAC;CACvB,IAAI,OAA+C;CAEnD,KAAK,MAAM,QAAQ,SAAS,MAAM,IAAI,GAAG;EACrC,MAAM,SAAS,kDAAkD,KAAK,IAAI;EAC1E,IAAI,CAAC,QAAQ;GACT,IAAI,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,IAAI;GACrC;EACJ;EACA,MAAM,GAAG,MAAM,QAAQ;EACvB,IAAI,SAAS,KAAK;GACd,IAAI,CAAC,QAAQ,KAAK,SAAS,MACvB,MAAM,IAAI,MAAM,sBAAsB,KAAK,iCAAiC;GAEhF,OAAO;GACP;EACJ;EACA,IAAI,MAAM,MAAM,IAAI,MAAM,qBAAqB,OAAO,KAAK,oBAAoB,KAAK,KAAK,QAAQ;EACjG,IAAI,CAAC,YAAY,IAAI,GACjB,MAAM,IAAI,MAAM,mCAAmC,OAAO,KAAK,IAAI;EAMvE,OAAO;GAAE;GACjB,MAAM,SAAS,MAAM,MAAM,UAAU,OAAO,MAAM,UAAU;EAAK;CAC7D;CAEA,IAAI,MAAM,MAAM,IAAI,MAAM,sBAAsB,KAAK,KAAK,qBAAqB;CAG/E,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,QAAQ,+BAA+B,WAAW;AAC5E;;AAGA,IAAM,UAA8D;CAMhE;EAAE,MAAM;EACZ,IAAI;EACJ,WAAW;CAAK;CACZ;EAAE,MAAM;EACZ,IAAI;EACJ,WAAW;CAAK;CAMZ;EAAE,MAAM;EACZ,IAAI;EACJ,WAAW;CAAM;CAKb;EAAE,MAAM;EACZ,IAAI;EACJ,WAAW;CAAM;CACb;EAAE,MAAM;EACZ,IAAI;EACJ,WAAW;CAAM;AACjB;;;;;;;AAQA,SAAS,cAAc,aAA6B;CAChD,IAAI;EACA,MAAM,MAAM,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,aAAa,cAAc,GAAG,MAAM,CAAC;EACtF,IAAI,OAAO,IAAI,SAAS,YAAY,IAAI,KAAK,KAAK,GAAG,OAAO,IAAI,KAAK,KAAK;CAC9E,QAAQ,CAER;CACA,OAAO,KAAK,SAAS,WAAW;AACpC;AAEA,SAAS,YAAkB;CACvB,QAAQ,IAAI;EACd,MAAM,KAAK,cAAc,EAAE;;;aAGhB,MAAM,KAAK,qBAAmB,EAAE;;;;EAI3C,MAAM,KAAK,OAAO,EAAE;;;EAGpB,MAAM,KAAK,SAAS,EAAE;;;;;EAKtB,KAAK,CAAC;AACR;AAEA,eAAsB,aAAa,UAAoB,CAAC,GAAkB;CACtE,IAAI,UAAU,OAAO,GAAG;EACpB,UAAU;EACV;CACJ;CAEA,MAAM,EAAE,OAAO,MAAM,gBAAgB,iBAAiB;EAClD,MAAM;GACF,aAAa;GACb,WAAW;EACf;EACA;EACA,cAAc;EACd,SAAS;EACT,gBAAgB;CACpB,CAAC;CAED,MAAM,cAAc,mBAAmB;CACvC,MAAM,SAAS,QAAQ,KAAK,YAAY;CACxC,MAAM,QAAQ,QAAQ,KAAK,UAAU;CAGrC,MAAM,YAAY,YAAY;CAE9B,IAAI;CACJ,IAAI;EACA,SAAS,aAAa,WAAW;CACrC,SAAS,KAAK;EACV,IAAI,eAAe,eAAe;GAC9B,QAAQ,MAAM,MAAM,IAAI,KAAK,IAAI,SAAS,CAAC;GAC3C,KAAK,MAAM,SAAS,IAAI,QACpB,QAAQ,MAAM,MAAM,IAAI,OAAO,MAAM,KAAK,IAAI,MAAM,SAAS,CAAC;GAElE,QAAQ,KAAK,CAAC;EAClB;EACA,MAAM;CACV;CAEA,MAAM,EAAE,aAAa;CAErB,IAAI;CACJ,IAAI;CAEJ,IAAI,WAAW;EACX,MAAM,WAAW,SAAS,KAAK;EAC/B,IAAI,CAAC,UAAU;GACX,QAAQ,MAAM,MAAM,IAAI,mBAAmB,UAAU,kBAAkB,CAAC;GACxE,QAAQ,MAAM,MAAM,IAAI,eAAe,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,IAAI,KAAK,UAAU,CAAC;GAC3F,QAAQ,KAAK,CAAC;EAClB;EACA,IAAI,SAAS,SAAS,WAAW;GAE7B,QAAQ,MAAM,MAAM,IAAI,MAAM,UAAU,SAAS,SAAS,KAAK,sCAAsC,CAAC;GACtG,QAAQ,KAAK,CAAC;EAClB;EACA,UAAU;EACV,MAAM;CACV,OAAO;EACH,MAAM,UAAU,eAAe,QAAQ;EACvC,IAAI,CAAC,SAAS;GACV,QAAQ,MAAM,MAAM,IAAI,4CAA4C,CAAC;GACrE,QAAQ,MAAM,MAAM,IAAI,sEAAsE,CAAC;GAC/F,QAAQ,KAAK,CAAC;EAClB;EACA,UAAU,QAAQ;EAClB,MAAM,QAAQ;CAClB;CAEA,IAAI,IAAI,YAAY,UAAU;EAC1B,QAAQ,MAAM,MAAM,IAAI,MAAM,QAAQ,sDAAsD,CAAC;EAC7F,QAAQ,MAAM,MAAM,IAAI,uBAAuB,IAAI,cAAc,aAAa,2BAA2B,CAAC;EAC1G,QAAQ,KAAK,CAAC;CAClB;CAEA,MAAM,UAAU,YAAY,SAAS;CACrC,IAAI,CAAC,SAAS;EACV,QAAQ,MAAM,MAAM,IAAI,mEAAmE,CAAC;EAC5F,QAAQ,KAAK,CAAC;CAClB;CACA,MAAM,aAAa,KAAK,KAAK,SAAU,aAAa,OAAO;CAM3D,MAAM,QAAsB;EACxB,aAFU,oBAAoB,KAAK,WAEtB,CAAA,CAAM;EACnB,UAAU,GAAG,WAAW,KAAK,KAAK,aAAa,UAAU,CAAC;CAC9D;CAKA,MAAM,UAAoE,CAAC;CAC3E,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,SAAS;EACxB,MAAM,SAAS,KAAK,KAAK,YAAY,KAAK,IAAI;EAC9C,IAAI,CAAC,GAAG,WAAW,MAAM,GAAG;GACxB,QAAQ,MAAM,MAAM,IAAI,mCAAmC,KAAK,KAAK,4BAA4B,CAAC;GAClG,QAAQ,KAAK,CAAC;EAClB;EACA,MAAM,SAAS,GAAG,WAAW,KAAK,KAAK,aAAa,KAAK,EAAE,CAAC;EAC5D,IAAI,UAAU,KAAK,aAAa,CAAC,OAAO,QAAQ,KAAK,KAAK,EAAE;EAC5D,QAAQ,KAAK;GACT,IAAI,KAAK;GACT,QAAQ,CAAC,SAAS,UAAU,KAAK,YAAY,cAAc;EAC/D,CAAC;CACL;CAEA,IAAI,QAAQ,SAAS,GAAG;EAKpB,QAAQ,MAAM,MAAM,IAAI,2DAA2D,CAAC;EACpF,KAAK,MAAM,QAAQ,SAAS,QAAQ,MAAM,MAAM,IAAI,SAAS,MAAM,CAAC;EACpE,QAAQ,MAAM,MAAM,IAAI,8DAA8D,CAAC;EACvF,QAAQ,MAAM,MAAM,IAAI,wEAAwE,CAAC;EACjG,QAAQ,MAAM,MAAM,IAAI,2BAA2B,CAAC;EACpD,QAAQ,KAAK,CAAC;CAClB;CAEA,IAAI,QAAQ;EACR,QAAQ,IAAI,MAAM,KAAK,gBAAgB,QAAQ,uBAAuB,CAAC;EACvE,QAAQ,IAAI,EAAE;EACd,KAAK,MAAM,QAAQ,SACf,IAAI,KAAK,WAAW,SAAS,QAAQ,IAAI,KAAK,MAAM,MAAM,OAAO,EAAE,QAAQ,KAAK,IAAI;OAC/E,IAAI,KAAK,WAAW,aACrB,QAAQ,IAAI,KAAK,MAAM,OAAO,WAAW,EAAE,IAAI,KAAK,GAAG,GAAG,MAAM,IAAI,YAAY,KAAK,GAAG,MAAM,GAAG;OAC9F,QAAQ,IAAI,KAAK,MAAM,IAAI,MAAM,EAAE,SAAS,KAAK,GAAG,GAAG,MAAM,IAAI,kBAAkB,GAAG;EAEjG,QAAQ,IAAI,KAAK,MAAM,MAAM,OAAO,EAAE,oBAAoB,MAAM,IAAI,uBAAqB,GAAG;EAG5F,IAAI,GAAG,WAAW,KAAK,KAAK,aAAa,WAAW,cAAc,CAAC,GAC/D,QAAQ,IAAI,KAAK,MAAM,MAAM,OAAO,EAAE,6BAA6B,MAAM,IAAI,+BAA+B,GAAG;EAEnH,QAAQ,IAAI,EAAE;EACd,QAAQ,IAAI,MAAM,IAAI,sBAAsB,CAAC;EAC7C;CACJ;CAEA,MAAM,cAAc,cAAc,WAAW;CAC7C,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,CAAC,OAAO,SAAS,QAAQ,QAAQ,GAAG;EAC3C,IAAI,QAAQ,MAAM,CAAC,WAAW,QAAQ;EACtC,MAAM,cAAc,KAAK,KAAK,aAAa,KAAK,EAAE;EAClD,IAAI,QAAQ,MAAM,CAAC,WAAW,aAAa;GACvC,GAAG,aAAa,aAAa,GAAG,YAAY,KAAK;GACjD,QAAQ,KAAK,GAAG,KAAK,GAAG,KAAK;EACjC;EACA,GAAG,UAAU,KAAK,QAAQ,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;EAC3D,MAAM,WAAW,cACb,GAAG,aAAa,KAAK,KAAK,YAAY,KAAK,IAAI,GAAG,MAAM,GACxD,OACA,WACJ;EACA,GAAG,cAAc,aAAa,UAAU,MAAM;CAClD;CAEA,MAAM,aAAa,IAAI,cAAc;CACrC,SAAS,KAAK,WAAW;EACrB,GAAG;EACH,SAAS;EACT;EACA,MAAM,IAAI,QAAQ;CACtB;CACA,cAAc,aAAa,QAAQ;CAKnC,sBAAsB,WAAW;CAEjC,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,MAAM,cAAc,QAAQ,uBAAuB,CAAC;CACtE,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,KAAK,MAAM,KAAK,uBAAuB,OAAO,EAAE,CAAC,EAAE,0DAA0D;CACzH,QAAQ,IAAI,KAAK,MAAM,KAAK,qBAAqB,OAAO,EAAE,CAAC,EAAE,0BAA0B;CACvF,QAAQ,IAAI,KAAK,MAAM,KAAK,WAAW,OAAO,EAAE,CAAC,EAAE,YAAY;CAC/D,QAAQ,IAAI,KAAK,MAAM,KAAK,4BAA4B,OAAO,EAAE,CAAC,EAAE,SAAS;CAC7E,QAAQ,IAAI,KAAK,MAAM,KAAK,cAAc,OAAO,EAAE,CAAC,EAAE,iBAAiB;CACvE,KAAK,MAAM,UAAU,SACjB,QAAQ,IAAI,KAAK,MAAM,KAAK,OAAO,OAAO,EAAE,CAAC,EAAE,uBAAuB;CAE1E,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,OAAO,yEAAyE,CAAC;CACnG,QAAQ,IAAI,MAAM,OAAO,0CAA0C,CAAC;CACpE,IAAI,CAAC,MAAM,aAAa;EACpB,QAAQ,IAAI,MAAM,OAAO,wEAAwE,CAAC;EAClG,QAAQ,IAAI,MAAM,OAAO,uDAAuD,CAAC;CACrF;CACA,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,IAAI,KAAK,MAAM,KAAK,wDAAwD,GAAG,CAAC;CAClG,QAAQ,IAAI,MAAM,IAAI,qFAAqF,CAAC;CAC5G,QAAQ,IAAI,EAAE;AAClB;;;;;;;AAQA,SAAS,sBAAsB,aAA2B;CACtD,MAAM,cAAc,KAAK,KAAK,aAAa,WAAW,cAAc;CACpE,IAAI,CAAC,GAAG,WAAW,WAAW,GAAG;CAEjC,IAAI;CACJ,IAAI;EACA,SAAS,KAAK,MAAM,GAAG,aAAa,aAAa,MAAM,CAAC;CAC5D,QAAQ;EAGJ,QAAQ,IAAI,MAAM,OAAO,2EAA2E,CAAC;EACrG;CACJ;CAEA,MAAM,UAAW,OAAO,WAAW,CAAC;CACpC,OAAO,SAAS;CAChB,QAAQ,QAAQ;CAChB,QAAQ,UAAU;CAClB,OAAO,UAAU;CAEjB,GAAG,cAAc,aAAa,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,KAAK,MAAM;AAChF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { u as compareMountOrder, v as staticAppAddress } from "./manifest-
|
|
2
|
-
import { _ as foldStaticIntoBundle, b as toolStdio } from "./bundle-
|
|
1
|
+
import { u as compareMountOrder, v as staticAppAddress } from "./manifest-nvPdLlJY.js";
|
|
2
|
+
import { _ as foldStaticIntoBundle, b as toolStdio } from "./bundle-DlqkDYSe.js";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import path from "path";
|
|
@@ -198,4 +198,4 @@ async function foldFrontendIntoBundle(options) {
|
|
|
198
198
|
//#endregion
|
|
199
199
|
export { staticBuildEnv as i, foldFrontendIntoBundle as n, foldableApps as r, assertBuiltForPath as t };
|
|
200
200
|
|
|
201
|
-
//# sourceMappingURL=fold-static-
|
|
201
|
+
//# sourceMappingURL=fold-static-CybSay_W.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fold-static-hDHtDfTq.js","names":[],"sources":["../src/fold-static.ts"],"sourcesContent":["/**\n * Folding a project's static apps into its backend bundle.\n *\n * Shared by `rebase build` and `rebase cloud deploy` deliberately. It lived in\n * the build *command* first, and `deploy` rebuilds the bundle itself — so a\n * deploy silently produced a bundle without the frontend, packed 164 KB where\n * 39 MB was expected, and the site 404'd on the managed runtime exactly as if\n * folding had never been written. Two callers building the same artefact must\n * share the step that completes it.\n *\n * Why fold at all: `bootFromBundle` serves static apps from `entry.static`\n * behind `REBASE_SERVE_STATIC` (default on). A managed tenant runs one pod, so\n * putting the built assets in the bundle gives it the shape a custom container\n * already had — site at `/`, admin at `/admin`, API at `/api` — which is the\n * only honest baseline for calling the managed runtime a drop-in replacement.\n *\n * **Every** static app is folded, each at its declared path. Folding used to\n * pick exactly one and refuse when it found two, which meant a project with a\n * site and an admin panel deployed with neither.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execa } from \"execa\";\nimport chalk from \"chalk\";\nimport { foldStaticIntoBundle } from \"./bundle\";\nimport { compareMountOrder, staticAppAddress } from \"./manifest\";\nimport { toolStdio } from \"./utils/tool-stdio\";\n\n/** The apps section of a project manifest, as much of it as folding needs. */\nexport interface FoldableManifest {\n apps?: Record<string, {\n type?: string;\n build?: string;\n output?: string;\n path?: string;\n spa?: boolean;\n cms?: string;\n }>;\n}\n\nexport interface FoldOptions {\n projectRoot: string;\n manifest: FoldableManifest;\n /** The backend bundle directory, already written. */\n bundleDir: string;\n /** Skip running each app's own build command; fold what is already built. */\n skipBuild?: boolean;\n /**\n * The static apps already built in this run, shared with `buildAssetApp`.\n * An app named here is not built again; an app built here is added. One\n * `rebase build` used to run the admin's `vite build && tsc` twice — once\n * to fold it, once for its own static bundle — with the same command, the\n * same environment and the same output directory.\n */\n builtApps?: Set<string>;\n log?: (message: string) => void;\n /** Send each app's build output to stderr: the caller's stdout carries a result. See `toolStdio`. */\n quietStdout?: boolean;\n}\n\nexport interface FoldOutcome {\n appName: string;\n fileCount: number;\n /** Public base path this app was folded in at. */\n path: string;\n /** The one hostname it answers on, when its `path` names one. */\n host?: string;\n}\n\n/** A static app as folding sees it, with the manifest's defaults applied. */\nexport interface FoldableApp {\n name: string;\n build?: string;\n output?: string;\n /**\n * Public base path, defaulted to `/`. Always a path: when the manifest's\n * `path` is a URL, this is the part after the hostname, which is what the\n * app is built for and mounted at.\n */\n path: string;\n /** The one hostname this app answers on, when its `path` is a URL. */\n host?: string;\n /** SPA fallback, defaulted to `true`. */\n spa: boolean;\n /** Where this app mounts the Rebase CMS, if it does. */\n cms?: string;\n}\n\n/**\n * Every static app in the manifest, in mount order.\n *\n * Longest path first, so the `/`-rooted app is registered last — its catch-all\n * would otherwise claim its siblings' URLs — and, at an equal path, the app with\n * a hostname before the one without (see `compareMountOrder`). Pure, so the\n * ordering is testable without a filesystem.\n */\nexport function foldableApps(manifest: FoldableManifest): {\n apps: FoldableApp[];\n /** Apps that cannot be folded, and why. */\n skipped: { name: string; reason: string }[];\n} {\n const apps: FoldableApp[] = [];\n const skipped: { name: string; reason: string }[] = [];\n\n for (const [name, app] of Object.entries(manifest.apps ?? {})) {\n if (app?.type !== \"static\") continue;\n if (!app.output) {\n skipped.push({ name,\nreason: `\"${name}\" declares no output directory — not folded in.` });\n continue;\n }\n const { host, path: appPath } = staticAppAddress(name, app);\n apps.push({\n name,\n build: app.build,\n output: app.output,\n path: appPath,\n ...(host ? { host } : {}),\n spa: app.spa ?? true,\n cms: app.cms\n });\n }\n\n apps.sort(compareMountOrder);\n return { apps,\nskipped };\n}\n\n/**\n * Assert a built app's assets are actually rooted at the path it is served from.\n *\n * An app mounted at `/admin` but built with Vite's default `base: \"/\"` emits\n * `<script src=\"/assets/index-a1b2.js\">`. The server serves `index.html` fine\n * and 404s every asset: a blank page, no server error, nothing in the logs. It\n * is the single most expensive silent failure in this design, so it is a build\n * error rather than a runtime surprise.\n *\n * Only `<script src>` and `<link href>` are inspected — those are what a bundler\n * rewrites through `base`. Author-written anchors and canonical URLs are not\n * evidence of a misbuild.\n */\nexport function assertBuiltForPath(\n indexHtml: string,\n basePath: string,\n appName: string\n): void {\n if (basePath === \"/\") return;\n\n const offenders: string[] = [];\n const pattern = /<(?:script|link)\\b[^>]*?\\b(?:src|href)\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n for (const match of indexHtml.matchAll(pattern)) {\n const ref = match[1];\n if (!ref.startsWith(\"/\")) continue;\n if (ref === `${basePath}` || ref.startsWith(`${basePath}/`)) continue;\n offenders.push(ref);\n }\n\n if (offenders.length === 0) return;\n\n throw new Error(\n `\"${appName}\" is declared at ${basePath} but its build emitted assets rooted at /.\\n` +\n ` index.html references: ${offenders.slice(0, 3).join(\", \")}\\n` +\n \" The app would load a blank page. Set `base` from REBASE_APP_BASE in its\\n\" +\n \" build config — see docs/apps-and-runtimes.md §4.2.\"\n );\n}\n\n/**\n * The environment every static app is built with, wherever that build is driven from.\n *\n * Shared because there are two drivers — `foldFrontendIntoBundle` here, and\n * `buildAssetApp` in `build.ts` for a standalone `type: \"static\"` app — and they\n * had already drifted: the path variables were duplicated into both, so a fix\n * applied to one shipped a bundle built the old way from the other. One function\n * makes that impossible rather than merely unlikely.\n *\n * ## REBASE_APP_*\n *\n * The declared path is a build-time input, not only a serving concern: Vite\n * reads `base` from REBASE_APP_BASE, and the trailing slash is that field's\n * convention. See `assertBuiltForPath`.\n *\n * For an app declared at a URL these carry the path part only — `/` for\n * `https://admin.example.com`. The hostname is where the platform routes the\n * app, not something its assets should name: an absolute `base` would pin\n * every script to production, so `vite preview` and any other hostname the app\n * is opened on would load it from somewhere else.\n *\n * ## NODE_ENV\n *\n * A built app is a production artifact by construction, so build it as one. Not\n * a formality: the scaffold's `.env` carries `NODE_ENV=development` for the dev\n * backend, and Vite's `loadEnv` promotes a `NODE_ENV` found in an env file into\n * the build unless the environment already sets one. So `rebase build` and\n * `rebase cloud deploy` shipped a *development* bundle — `import.meta.env.DEV\n * === true`, development React, dev-only branches live — from commands whose\n * whole purpose is to produce something deployable. Setting it here is what\n * closes it: Vite consults the env file's NODE_ENV only when `process.env`\n * has none.\n *\n * ## VITE_API_URL\n *\n * An app served by the backend it talks to has its API on its own origin by\n * construction, so a baked-in absolute URL can only be wrong. It was: that same\n * `.env` carries `VITE_API_URL=http://localhost:3001` and\n * `frontend/vite.config.ts` reads the project root via `envDir: \"..\"`, so a\n * stock deploy shipped a site whose every request went to whoever ran the build\n * — passing every server-side health check on the way out. Blanking it here\n * fixes the bundle even for a project whose `.env` predates the `init` fix, or\n * was written by hand. Empty is the right value rather than a missing one: the\n * client falls back to `window.location.origin`, which keeps working when a\n * custom domain is added.\n *\n * Vite prioritises `process.env.VITE_*` over `.env` files, so an explicit\n * `VITE_API_URL=https://api.example.com rebase cloud deploy` still wins — the\n * cross-origin escape hatch stays open, it just has to be deliberate. Nothing on\n * this path loads the project `.env` into `process.env`, so a value inherited\n * here really was set by the caller.\n */\nexport function staticBuildEnv(appPath: string, appName: string): Record<string, string> {\n return {\n REBASE_APP_PATH: appPath,\n REBASE_APP_BASE: appPath === \"/\" ? \"/\" : `${appPath}/`,\n REBASE_APP_NAME: appName,\n NODE_ENV: \"production\",\n VITE_API_URL: process.env.VITE_API_URL ?? \"\"\n };\n}\n\n/**\n * Build the project's static apps and fold them into the backend bundle.\n *\n * Throws rather than exiting, so the caller decides whether a missing frontend\n * should fail its command — a `build` may reasonably want to stop, and so should\n * a deploy, but that is not this function's call to make.\n */\nexport async function foldFrontendIntoBundle(options: FoldOptions): Promise<FoldOutcome[]> {\n const { projectRoot, manifest, bundleDir, skipBuild } = options;\n const log = options.log ?? ((m: string) => console.log(m));\n\n const { apps, skipped } = foldableApps(manifest);\n for (const { reason } of skipped) log(chalk.yellow(` ⚠ ${reason}`));\n if (apps.length === 0) return [];\n\n const outcomes: FoldOutcome[] = [];\n\n for (const app of apps) {\n if (app.build && !skipBuild && !options.builtApps?.has(app.name)) {\n await execa(app.build, {\n cwd: projectRoot,\n stdio: toolStdio(options.quietStdout),\n shell: true,\n env: staticBuildEnv(app.path, app.name)\n });\n options.builtApps?.add(app.name);\n }\n\n const assetsDir = path.join(projectRoot, app.output as string);\n if (!fs.existsSync(assetsDir)) {\n // Exited 0 and produced nothing where the manifest says it should.\n // Folding that ships an empty site, which from the outside is\n // indistinguishable from a broken deploy.\n throw new Error(\n `\"${app.name}\" declared output \"${app.output}\" does not exist after building — ` +\n \"the bundle would ship without a frontend.\"\n );\n }\n\n const indexHtml = path.join(assetsDir, \"index.html\");\n if (fs.existsSync(indexHtml)) {\n assertBuiltForPath(fs.readFileSync(indexHtml, \"utf8\"), app.path, app.name);\n }\n\n const { fileCount } = foldStaticIntoBundle({\n bundleDir,\n assetsDir,\n appName: app.name,\n path: app.path,\n host: app.host,\n spa: app.spa,\n cms: app.cms\n });\n outcomes.push({ appName: app.name,\nfileCount,\npath: app.path,\n...(app.host ? { host: app.host } : {}) });\n }\n\n return outcomes;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fold-static-CybSay_W.js","names":[],"sources":["../src/fold-static.ts"],"sourcesContent":["/**\n * Folding a project's static apps into its backend bundle.\n *\n * Shared by `rebase build` and `rebase cloud deploy` deliberately. It lived in\n * the build *command* first, and `deploy` rebuilds the bundle itself — so a\n * deploy silently produced a bundle without the frontend, packed 164 KB where\n * 39 MB was expected, and the site 404'd on the managed runtime exactly as if\n * folding had never been written. Two callers building the same artefact must\n * share the step that completes it.\n *\n * Why fold at all: `bootFromBundle` serves static apps from `entry.static`\n * behind `REBASE_SERVE_STATIC` (default on). A managed tenant runs one pod, so\n * putting the built assets in the bundle gives it the shape a custom container\n * already had — site at `/`, admin at `/admin`, API at `/api` — which is the\n * only honest baseline for calling the managed runtime a drop-in replacement.\n *\n * **Every** static app is folded, each at its declared path. Folding used to\n * pick exactly one and refuse when it found two, which meant a project with a\n * site and an admin panel deployed with neither.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport { execa } from \"execa\";\nimport chalk from \"chalk\";\nimport { foldStaticIntoBundle } from \"./bundle\";\nimport { compareMountOrder, staticAppAddress } from \"./manifest\";\nimport { toolStdio } from \"./utils/tool-stdio\";\n\n/** The apps section of a project manifest, as much of it as folding needs. */\nexport interface FoldableManifest {\n apps?: Record<string, {\n type?: string;\n build?: string;\n output?: string;\n path?: string;\n spa?: boolean;\n cms?: string;\n }>;\n}\n\nexport interface FoldOptions {\n projectRoot: string;\n manifest: FoldableManifest;\n /** The backend bundle directory, already written. */\n bundleDir: string;\n /** Skip running each app's own build command; fold what is already built. */\n skipBuild?: boolean;\n /**\n * The static apps already built in this run, shared with `buildAssetApp`.\n * An app named here is not built again; an app built here is added. One\n * `rebase build` used to run the admin's `vite build && tsc` twice — once\n * to fold it, once for its own static bundle — with the same command, the\n * same environment and the same output directory.\n */\n builtApps?: Set<string>;\n log?: (message: string) => void;\n /** Send each app's build output to stderr: the caller's stdout carries a result. See `toolStdio`. */\n quietStdout?: boolean;\n}\n\nexport interface FoldOutcome {\n appName: string;\n fileCount: number;\n /** Public base path this app was folded in at. */\n path: string;\n /** The one hostname it answers on, when its `path` names one. */\n host?: string;\n}\n\n/** A static app as folding sees it, with the manifest's defaults applied. */\nexport interface FoldableApp {\n name: string;\n build?: string;\n output?: string;\n /**\n * Public base path, defaulted to `/`. Always a path: when the manifest's\n * `path` is a URL, this is the part after the hostname, which is what the\n * app is built for and mounted at.\n */\n path: string;\n /** The one hostname this app answers on, when its `path` is a URL. */\n host?: string;\n /** SPA fallback, defaulted to `true`. */\n spa: boolean;\n /** Where this app mounts the Rebase CMS, if it does. */\n cms?: string;\n}\n\n/**\n * Every static app in the manifest, in mount order.\n *\n * Longest path first, so the `/`-rooted app is registered last — its catch-all\n * would otherwise claim its siblings' URLs — and, at an equal path, the app with\n * a hostname before the one without (see `compareMountOrder`). Pure, so the\n * ordering is testable without a filesystem.\n */\nexport function foldableApps(manifest: FoldableManifest): {\n apps: FoldableApp[];\n /** Apps that cannot be folded, and why. */\n skipped: { name: string; reason: string }[];\n} {\n const apps: FoldableApp[] = [];\n const skipped: { name: string; reason: string }[] = [];\n\n for (const [name, app] of Object.entries(manifest.apps ?? {})) {\n if (app?.type !== \"static\") continue;\n if (!app.output) {\n skipped.push({ name,\nreason: `\"${name}\" declares no output directory — not folded in.` });\n continue;\n }\n const { host, path: appPath } = staticAppAddress(name, app);\n apps.push({\n name,\n build: app.build,\n output: app.output,\n path: appPath,\n ...(host ? { host } : {}),\n spa: app.spa ?? true,\n cms: app.cms\n });\n }\n\n apps.sort(compareMountOrder);\n return { apps,\nskipped };\n}\n\n/**\n * Assert a built app's assets are actually rooted at the path it is served from.\n *\n * An app mounted at `/admin` but built with Vite's default `base: \"/\"` emits\n * `<script src=\"/assets/index-a1b2.js\">`. The server serves `index.html` fine\n * and 404s every asset: a blank page, no server error, nothing in the logs. It\n * is the single most expensive silent failure in this design, so it is a build\n * error rather than a runtime surprise.\n *\n * Only `<script src>` and `<link href>` are inspected — those are what a bundler\n * rewrites through `base`. Author-written anchors and canonical URLs are not\n * evidence of a misbuild.\n */\nexport function assertBuiltForPath(\n indexHtml: string,\n basePath: string,\n appName: string\n): void {\n if (basePath === \"/\") return;\n\n const offenders: string[] = [];\n const pattern = /<(?:script|link)\\b[^>]*?\\b(?:src|href)\\s*=\\s*[\"']([^\"']+)[\"']/gi;\n for (const match of indexHtml.matchAll(pattern)) {\n const ref = match[1];\n if (!ref.startsWith(\"/\")) continue;\n if (ref === `${basePath}` || ref.startsWith(`${basePath}/`)) continue;\n offenders.push(ref);\n }\n\n if (offenders.length === 0) return;\n\n throw new Error(\n `\"${appName}\" is declared at ${basePath} but its build emitted assets rooted at /.\\n` +\n ` index.html references: ${offenders.slice(0, 3).join(\", \")}\\n` +\n \" The app would load a blank page. Set `base` from REBASE_APP_BASE in its\\n\" +\n \" build config — see docs/apps-and-runtimes.md §4.2.\"\n );\n}\n\n/**\n * The environment every static app is built with, wherever that build is driven from.\n *\n * Shared because there are two drivers — `foldFrontendIntoBundle` here, and\n * `buildAssetApp` in `build.ts` for a standalone `type: \"static\"` app — and they\n * had already drifted: the path variables were duplicated into both, so a fix\n * applied to one shipped a bundle built the old way from the other. One function\n * makes that impossible rather than merely unlikely.\n *\n * ## REBASE_APP_*\n *\n * The declared path is a build-time input, not only a serving concern: Vite\n * reads `base` from REBASE_APP_BASE, and the trailing slash is that field's\n * convention. See `assertBuiltForPath`.\n *\n * For an app declared at a URL these carry the path part only — `/` for\n * `https://admin.example.com`. The hostname is where the platform routes the\n * app, not something its assets should name: an absolute `base` would pin\n * every script to production, so `vite preview` and any other hostname the app\n * is opened on would load it from somewhere else.\n *\n * ## NODE_ENV\n *\n * A built app is a production artifact by construction, so build it as one. Not\n * a formality: the scaffold's `.env` carries `NODE_ENV=development` for the dev\n * backend, and Vite's `loadEnv` promotes a `NODE_ENV` found in an env file into\n * the build unless the environment already sets one. So `rebase build` and\n * `rebase cloud deploy` shipped a *development* bundle — `import.meta.env.DEV\n * === true`, development React, dev-only branches live — from commands whose\n * whole purpose is to produce something deployable. Setting it here is what\n * closes it: Vite consults the env file's NODE_ENV only when `process.env`\n * has none.\n *\n * ## VITE_API_URL\n *\n * An app served by the backend it talks to has its API on its own origin by\n * construction, so a baked-in absolute URL can only be wrong. It was: that same\n * `.env` carries `VITE_API_URL=http://localhost:3001` and\n * `frontend/vite.config.ts` reads the project root via `envDir: \"..\"`, so a\n * stock deploy shipped a site whose every request went to whoever ran the build\n * — passing every server-side health check on the way out. Blanking it here\n * fixes the bundle even for a project whose `.env` predates the `init` fix, or\n * was written by hand. Empty is the right value rather than a missing one: the\n * client falls back to `window.location.origin`, which keeps working when a\n * custom domain is added.\n *\n * Vite prioritises `process.env.VITE_*` over `.env` files, so an explicit\n * `VITE_API_URL=https://api.example.com rebase cloud deploy` still wins — the\n * cross-origin escape hatch stays open, it just has to be deliberate. Nothing on\n * this path loads the project `.env` into `process.env`, so a value inherited\n * here really was set by the caller.\n */\nexport function staticBuildEnv(appPath: string, appName: string): Record<string, string> {\n return {\n REBASE_APP_PATH: appPath,\n REBASE_APP_BASE: appPath === \"/\" ? \"/\" : `${appPath}/`,\n REBASE_APP_NAME: appName,\n NODE_ENV: \"production\",\n VITE_API_URL: process.env.VITE_API_URL ?? \"\"\n };\n}\n\n/**\n * Build the project's static apps and fold them into the backend bundle.\n *\n * Throws rather than exiting, so the caller decides whether a missing frontend\n * should fail its command — a `build` may reasonably want to stop, and so should\n * a deploy, but that is not this function's call to make.\n */\nexport async function foldFrontendIntoBundle(options: FoldOptions): Promise<FoldOutcome[]> {\n const { projectRoot, manifest, bundleDir, skipBuild } = options;\n const log = options.log ?? ((m: string) => console.log(m));\n\n const { apps, skipped } = foldableApps(manifest);\n for (const { reason } of skipped) log(chalk.yellow(` ⚠ ${reason}`));\n if (apps.length === 0) return [];\n\n const outcomes: FoldOutcome[] = [];\n\n for (const app of apps) {\n if (app.build && !skipBuild && !options.builtApps?.has(app.name)) {\n await execa(app.build, {\n cwd: projectRoot,\n stdio: toolStdio(options.quietStdout),\n shell: true,\n env: staticBuildEnv(app.path, app.name)\n });\n options.builtApps?.add(app.name);\n }\n\n const assetsDir = path.join(projectRoot, app.output as string);\n if (!fs.existsSync(assetsDir)) {\n // Exited 0 and produced nothing where the manifest says it should.\n // Folding that ships an empty site, which from the outside is\n // indistinguishable from a broken deploy.\n throw new Error(\n `\"${app.name}\" declared output \"${app.output}\" does not exist after building — ` +\n \"the bundle would ship without a frontend.\"\n );\n }\n\n const indexHtml = path.join(assetsDir, \"index.html\");\n if (fs.existsSync(indexHtml)) {\n assertBuiltForPath(fs.readFileSync(indexHtml, \"utf8\"), app.path, app.name);\n }\n\n const { fileCount } = foldStaticIntoBundle({\n bundleDir,\n assetsDir,\n appName: app.name,\n path: app.path,\n host: app.host,\n spa: app.spa,\n cms: app.cms\n });\n outcomes.push({ appName: app.name,\nfileCount,\npath: app.path,\n...(app.host ? { host: app.host } : {}) });\n }\n\n return outcomes;\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { n as getPMCommands, t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
|
|
2
|
-
import { c as findProjectRoot, d as readEnvFile } from "./project-
|
|
3
|
-
import { d as findBackendApp, m as manifestExists, p as loadManifest, x as writeManifest } from "./manifest-
|
|
4
|
-
import {
|
|
2
|
+
import { c as findProjectRoot, d as readEnvFile } from "./project-g4K6kV1t.js";
|
|
3
|
+
import { d as findBackendApp, m as manifestExists, p as loadManifest, x as writeManifest } from "./manifest-nvPdLlJY.js";
|
|
4
|
+
import { t as DEV_BACKEND_URL_ENV } from "./dev-server-CIZwAfZa.js";
|
|
5
|
+
import { M as readLink } from "./context-DHiiiJ5C.js";
|
|
5
6
|
import { n as COLLECTIONS_PATH_RULE, t as COLLECTIONS_FLAG_HELP } from "./path-flags-BFgG9V6y.js";
|
|
7
|
+
import { t as Refusal } from "./refusal-ReeeGP8a.js";
|
|
6
8
|
import { n as isLoadedCollectionFile } from "./collection-drift-BKj_BoMq.js";
|
|
7
9
|
import chalk from "chalk";
|
|
8
10
|
import fs from "fs";
|
|
@@ -142,21 +144,25 @@ function rememberRegistration(projectRoot) {
|
|
|
142
144
|
*
|
|
143
145
|
* A path to a single module is read as the runtime reads one: its
|
|
144
146
|
* `backendCollections`, or its `collections`.
|
|
147
|
+
*
|
|
148
|
+
* A missing directory, a missing jiti and a module that exports no collections
|
|
149
|
+
* are `Refusal`s: the message says all there is. A collection file that throws
|
|
150
|
+
* on import is not: that is the project's own code failing, and the stack
|
|
151
|
+
* `--debug` prints points at the line, so `bin/rebase.js` keeps its hint.
|
|
145
152
|
*/
|
|
146
153
|
async function loadCollections(collectionsDir) {
|
|
147
154
|
const absDir = path.resolve(collectionsDir);
|
|
148
|
-
if (!fs.existsSync(absDir)) throw new
|
|
155
|
+
if (!fs.existsSync(absDir)) throw new Refusal(`Collections directory not found: ${absDir} (${COLLECTIONS_PATH_RULE})`);
|
|
149
156
|
let jiti;
|
|
150
157
|
try {
|
|
151
158
|
const jitiModule = await import("jiti");
|
|
152
159
|
jiti = jitiModule.default || jitiModule;
|
|
153
160
|
} catch {
|
|
154
|
-
|
|
161
|
+
throw new Refusal(`Could not load 'jiti'. Install it with: ${[
|
|
155
162
|
...getPMCommands(detectPackageManager()).install,
|
|
156
163
|
"-D",
|
|
157
164
|
"jiti"
|
|
158
|
-
].join(" ");
|
|
159
|
-
throw new Error(`Could not load 'jiti'. Install it with: ${installCmd}\njiti is required to dynamically import TypeScript collection definitions.`);
|
|
165
|
+
].join(" ")}\njiti is required to dynamically import TypeScript collection definitions.`);
|
|
160
166
|
}
|
|
161
167
|
if (!fs.statSync(absDir).isDirectory()) {
|
|
162
168
|
const mod = jiti(path.dirname(absDir), {
|
|
@@ -165,7 +171,7 @@ async function loadCollections(collectionsDir) {
|
|
|
165
171
|
})(absDir);
|
|
166
172
|
const listed = mod.backendCollections ?? mod.collections ?? mod.default;
|
|
167
173
|
if (Array.isArray(listed)) return listed;
|
|
168
|
-
throw new
|
|
174
|
+
throw new Refusal(`Could not extract collections from ${absDir}.\nA single collections module exports \`backendCollections\` or \`collections\`: an array of collections.`);
|
|
169
175
|
}
|
|
170
176
|
const jitiInstance = jiti(absDir, {
|
|
171
177
|
interopDefault: true,
|
|
@@ -304,10 +310,14 @@ function mayUseAmbientKey(target, cwd) {
|
|
|
304
310
|
* the one it actually got to `.rebase/state.json`. Printing a hardcoded
|
|
305
311
|
* `localhost:3001` sent people to a port nothing was listening on — or, with
|
|
306
312
|
* several projects on one machine, to a different project's backend. Prefer the
|
|
307
|
-
* port
|
|
308
|
-
*
|
|
313
|
+
* port `rebase dev` says it is starting the backend on (`DEV_BACKEND_URL_ENV`:
|
|
314
|
+
* it regenerates the SDK before the backend binds), then the port this project
|
|
315
|
+
* last ran on; fall back to the literal only when the project has never been
|
|
316
|
+
* started.
|
|
309
317
|
*/
|
|
310
318
|
function resolveExampleBaseUrl(cwd) {
|
|
319
|
+
const fromDev = process.env[DEV_BACKEND_URL_ENV]?.trim();
|
|
320
|
+
if (fromDev) return fromDev;
|
|
311
321
|
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
312
322
|
try {
|
|
313
323
|
const state = JSON.parse(fs.readFileSync(path.join(projectRoot, ".rebase", "state.json"), "utf-8"));
|
|
@@ -486,4 +496,4 @@ export const SCHEMA_VERSION = ${JSON.stringify(schemaVersion)};
|
|
|
486
496
|
//#endregion
|
|
487
497
|
export { generateSdkCommand };
|
|
488
498
|
|
|
489
|
-
//# sourceMappingURL=generate_sdk-
|
|
499
|
+
//# sourceMappingURL=generate_sdk-B4R65oUV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate_sdk-B4R65oUV.js","names":[],"sources":["../src/commands/generate_sdk.ts"],"sourcesContent":["/**\n * CLI command: generate-sdk\n *\n * Reads every collection file in a directory (default: ./config/collections) —\n * the files the backend serves, not the barrel's list — generates a typed\n * TypeScript SDK, and writes it to the output directory (default: ./generated/sdk).\n *\n * Uses jiti for dynamic TypeScript import of collection files.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport { CollectionConfig, computeSchemaVersion, deserializeCollections } from \"@rebasepro/types\";\nimport { CodegenError, generateSDK, GeneratedFile, toCollectionAccessor } from \"@rebasepro/codegen\";\nimport { detectPackageManager, getPMCommands } from \"../utils/package-manager\";\nimport { findProjectRoot, readEnvFile } from \"../utils/project\";\nimport { DEV_BACKEND_URL_ENV } from \"../utils/dev-server\";\nimport { Refusal } from \"../utils/refusal\";\nimport { findBackendApp, loadManifest, manifestExists, writeManifest } from \"../manifest\";\nimport { readLink } from \"./cloud/context\";\nimport { COLLECTIONS_FLAG_HELP, COLLECTIONS_PATH_RULE } from \"../utils/path-flags\";\nimport { isLoadedCollectionFile } from \"../utils/collection-drift\";\n\ninterface GenerateSDKArgs {\n collectionsDir: string;\n output: string;\n cwd: string;\n /**\n * Where to read the schema from instead of local source.\n *\n * `link` uses this checkout's linked project; anything else is treated as\n * the base URL of a Rebase backend. This is what lets a repository that\n * contains no collections — a separate frontend, a second web app — generate\n * a typed client from the project it talks to.\n */\n from?: string;\n /** Bearer token for the contract endpoint. Falls back to REBASE_SERVICE_KEY. */\n token?: string;\n /**\n * Also register the generated `Database` for server-side code: write the\n * types and the `Register` augmentation into `config/generated/`. See\n * {@link writeRegistration}.\n */\n register?: boolean;\n /**\n * The directory holding `rebase.json`, where `--register` is remembered.\n * Found from `cwd` when not given.\n */\n projectRoot?: string;\n help?: boolean;\n}\n\n/** What `--register` writes, and what marks a project as having opted in. */\nexport const REGISTER_FILE = \"register.ts\";\n\n/** The first line of {@link REGISTER_FILE}: a file without it is the developer's own. */\nconst REGISTER_MARKER = \"// Auto-generated by `rebase generate-sdk --register`. Do not edit.\";\n\nconst REGISTER_SOURCE = `${REGISTER_MARKER}\n//\n// Registers this project's generated \\`Database\\` on \\`@rebasepro/types\\`, so\n// \\`context.data\\` in collection callbacks, \\`rebase.dataAsAdmin\\`, and the\n// \\`rebase\\` a function or a cron receives are typed from it. Every later\n// \\`rebase generate-sdk\\` (and \\`rebase dev\\`) refreshes this directory; delete\n// it to go back to untyped server-side data.\nimport type { Database } from \"./database.types\";\n\ndeclare module \"@rebasepro/types\" {\n interface Register {\n database: Database;\n }\n}\n`;\n\n/**\n * Where `--register` writes: `generated/` beside the collections directory,\n * which is `config/generated/` in a scaffolded project.\n *\n * Inside `config/` because that is the one directory both compiles of a\n * collection file include: the backend's program (it includes\n * `../config/**`) and the `config` package's own `tsc`. A registration\n * there that imported `../generated/sdk/database.types` pulled a file from\n * outside `config/` into that package's program, which TypeScript refuses\n * (the file is not under its `rootDir`) — so the types are copied in beside\n * the registration rather than imported from the SDK.\n */\nexport function registrationDir(collectionsDir: string): string {\n return path.join(path.dirname(path.resolve(collectionsDir)), \"generated\");\n}\n\n/** Whether this project opted in: the registration is there, and it is ours. */\nfunction hasRegistration(dir: string): boolean {\n try {\n return fs.readFileSync(path.join(dir, REGISTER_FILE), \"utf-8\").startsWith(REGISTER_MARKER);\n } catch {\n return false;\n }\n}\n\n/** Write a file only when its content changed, so a watcher on the directory does not restart for nothing. */\nfunction writeIfChanged(filePath: string, content: string): void {\n try {\n if (fs.readFileSync(filePath, \"utf-8\") === content) return;\n } catch {\n // Not there yet.\n }\n fs.writeFileSync(filePath, content, \"utf-8\");\n}\n\n/**\n * Write the generated `Database` and its `Register` augmentation into\n * {@link registrationDir}. Refuses to overwrite a `register.ts` it did not\n * write.\n */\nfunction writeRegistration(dir: string, databaseTypes: string): void {\n const registerPath = path.join(dir, REGISTER_FILE);\n if (fs.existsSync(registerPath) && !hasRegistration(dir)) {\n throw new Error(\n `${registerPath} exists and was not written by \"rebase generate-sdk --register\". ` +\n \"Move it, or register the Database there yourself.\"\n );\n }\n fs.mkdirSync(dir, { recursive: true });\n writeIfChanged(path.join(dir, \"database.types.ts\"), databaseTypes);\n writeIfChanged(registerPath, REGISTER_SOURCE);\n}\n\n/**\n * Whether `rebase.json` asks for the registration (`registerDatabase: true` on\n * the backend app). That is what survives a clone: `generated/` is gitignored,\n * so a `register.ts` from an earlier run is not there to say it.\n *\n * An unreadable manifest answers no; `rebase build` is where it is reported.\n */\nfunction manifestRegisters(projectRoot: string | undefined): boolean {\n if (!projectRoot || !manifestExists(projectRoot)) return false;\n try {\n return findBackendApp(loadManifest(projectRoot).manifest)?.app.registerDatabase === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Remember `--register` in `rebase.json`, so later runs, `rebase dev` and a\n * fresh clone keep registering. Returns where it was written, or why not.\n *\n * Never creates the file: a project without one is synthesized from its\n * layout, and writing one is `rebase apps init`'s decision, not this flag's.\n */\nfunction rememberRegistration(projectRoot: string | undefined): { written: string } | { skipped: string } {\n if (!projectRoot || !manifestExists(projectRoot)) {\n return { skipped: \"No rebase.json here, so the choice lasts as long as the generated files.\" };\n }\n let loaded: ReturnType<typeof loadManifest>;\n try {\n loaded = loadManifest(projectRoot);\n } catch (error) {\n return { skipped: `rebase.json could not be read (${error instanceof Error ? error.message : String(error)}).` };\n }\n const backend = findBackendApp(loaded.manifest);\n if (!backend) return { skipped: \"rebase.json declares no backend app to remember it on.\" };\n if (backend.app.registerDatabase === true) return { written: loaded.filePath ?? projectRoot };\n const manifest = {\n ...loaded.manifest,\n apps: { ...loaded.manifest.apps, [backend.name]: { ...backend.app, registerDatabase: true } }\n };\n return { written: writeManifest(projectRoot, manifest) };\n}\n\n/**\n * Load the collections the backend serves, the way it finds them.\n *\n * A directory is read as `loadCollectionsFromDirectory` in @rebasepro/server\n * reads it: every top-level collection file, each default-exporting one\n * collection. The barrel (`index.ts`) is not a registry. The runtime, the admin\n * panel, `rebase build` and `rebase schema generate` all scan the directory, and\n * the barrel only orders the panel's navigation and declares\n * `defaultSecurityRules`. This command used to read the barrel instead, so a\n * collection file left out of it was created, served at `/api/data/<slug>` and\n * listed in the panel, and missing from the typed SDK alone.\n *\n * A file that does not load is fatal, as it is at boot: `rebase dev` runs this\n * on every save, and skipping the file would overwrite good types with a\n * `Database` that is silently short a collection.\n *\n * A path to a single module is read as the runtime reads one: its\n * `backendCollections`, or its `collections`.\n *\n * A missing directory, a missing jiti and a module that exports no collections\n * are `Refusal`s: the message says all there is. A collection file that throws\n * on import is not: that is the project's own code failing, and the stack\n * `--debug` prints points at the line, so `bin/rebase.js` keeps its hint.\n */\nasync function loadCollections(collectionsDir: string): Promise<CollectionConfig[]> {\n const absDir = path.resolve(collectionsDir);\n\n if (!fs.existsSync(absDir)) {\n throw new Refusal(`Collections directory not found: ${absDir} (${COLLECTIONS_PATH_RULE})`);\n }\n\n let jiti: (id: string, userOptions?: Record<string, unknown>) => (modulePath: string) => Record<string, unknown>;\n try {\n const jitiModule = await import(\"jiti\");\n jiti = (jitiModule.default || jitiModule) as typeof jiti;\n } catch {\n const installCmd = [...getPMCommands(detectPackageManager()).install, \"-D\", \"jiti\"].join(\" \");\n throw new Refusal(\n `Could not load 'jiti'. Install it with: ${installCmd}\\n` +\n \"jiti is required to dynamically import TypeScript collection definitions.\"\n );\n }\n\n if (!fs.statSync(absDir).isDirectory()) {\n const mod = jiti(path.dirname(absDir), { interopDefault: true, esmResolve: true })(absDir);\n const listed = mod.backendCollections ?? mod.collections ?? mod.default;\n if (Array.isArray(listed)) return listed as CollectionConfig[];\n throw new Refusal(\n `Could not extract collections from ${absDir}.\\n` +\n \"A single collections module exports `backendCollections` or `collections`: an array of collections.\"\n );\n }\n\n const jitiInstance = jiti(absDir, {\n interopDefault: true,\n esmResolve: true\n });\n\n const collections: CollectionConfig[] = [];\n const failures: string[] = [];\n const files = fs.readdirSync(absDir).filter(isLoadedCollectionFile).sort();\n\n for (const file of files) {\n try {\n const mod = jitiInstance(path.join(absDir, file));\n const exported = mod.default ?? mod;\n if (exported && typeof exported === \"object\" && \"slug\" in exported) {\n collections.push(exported as CollectionConfig);\n } else {\n failures.push(`${file}: no default export of a collection`);\n }\n } catch (err) {\n failures.push(`${file}: ${(err as Error).message}`);\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `Could not load ${failures.length} collection file(s) from ${absDir}:\\n` +\n failures.map(failure => ` • ${failure}`).join(\"\\n\") +\n \"\\n\\nEvery collection file must import cleanly and default-export a collection — \" +\n \"the backend refuses to boot on the same file.\"\n );\n }\n\n return collections;\n}\n\n/**\n * Write generated files to the output directory.\n */\nfunction writeFiles(outputDir: string, files: GeneratedFile[]): void {\n const absOutput = path.resolve(outputDir);\n\n // Create output directory\n fs.mkdirSync(absOutput, { recursive: true });\n\n for (const file of files) {\n const filePath = path.join(absOutput, file.path);\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, file.content, \"utf-8\");\n }\n}\n\nfunction printSdkHelp(): void {\n console.log(`\n${chalk.bold(\"rebase generate-sdk\")} — generate a typed client from a project's schema\n\n${chalk.bold(\"Usage\")}\n rebase generate-sdk [options]\n\n${chalk.bold(\"Options\")}\n -c, --collections <dir> ${COLLECTIONS_FLAG_HELP}\n (--collections-dir is accepted too)\n -o, --output <dir> Where to write the SDK (default: ./generated/sdk)\n (--out is accepted too, as on 'rebase build')\n --from <link|url> Fetch the schema from a running project instead of\n local source. \"link\" uses this checkout's linked project.\n --token <token> Bearer token for the contract endpoint\n (default: $REBASE_SERVICE_KEY)\n --register Also type server-side data: write the types and the\n Register declaration to config/generated/, and\n remember it in rebase.json so later runs keep it.\n -h, --help Show this help\n\n${chalk.bold(\"Examples\")}\n rebase generate-sdk From local collections\n rebase generate-sdk --from link From the linked project\n rebase generate-sdk --from https://api.acme.com From any Rebase backend\n rebase generate-sdk --register Type context.data and rebase.dataAsAdmin too\n`.trim());\n}\n\n/**\n * Fetch collections from a running project's contract endpoint.\n *\n * The payload replaces relation `target` functions with slug references, so it\n * has to be rehydrated before the generator sees it — the generator *calls*\n * `target()` to decide whether a foreign key is a string or a number, and a\n * missing target silently degrades that to a union rather than failing.\n */\n/** What `--from` sent to the contract endpoint, and which keys it left behind. */\ninterface ContractCredential {\n /** The bearer token sent: `--token`, the shell's key, or none. */\n sent: \"token\" | \"ambient\" | null;\n /** `REBASE_SERVICE_KEY` is in the shell environment. */\n shellKey: boolean;\n /** `REBASE_SERVICE_KEY` is in the project's `.env`. */\n envFileKey: boolean;\n}\n\n/**\n * What to say when the contract endpoint refuses, by what was and was not sent.\n *\n * \"Set REBASE_SERVICE_KEY\" is only right when no key exists. The shell's key is\n * withheld from every host but the linked project, and `.env`'s is never read\n * here — it is the local backend's key, and the linked project is usually a\n * deployed one — so telling a reader whose key is in `.env` to set it sends them\n * to fix something that is not broken.\n */\nfunction contractRefusalHint(credential: ContractCredential): string[] {\n if (credential.sent === \"token\") {\n return [\"The token passed with --token was refused: pass a service key, or an admin's token.\"];\n }\n if (credential.sent === \"ambient\") {\n return [\"REBASE_SERVICE_KEY was sent and refused: it is not this project's service key. Pass the right one with --token.\"];\n }\n if (credential.shellKey) {\n return [\n \"REBASE_SERVICE_KEY is set, but it is only sent to this checkout's linked project, and this host is not it.\",\n \"Pass the key with --token to send it here.\"\n ];\n }\n if (credential.envFileKey) {\n return [\n \"REBASE_SERVICE_KEY in .env is not sent: --from sends the shell's REBASE_SERVICE_KEY, and only to this checkout's linked project.\",\n \"Pass the key with --token.\"\n ];\n }\n return [\"Pass --token <key>, a service key or an admin's token. The shell's REBASE_SERVICE_KEY is sent only to this checkout's linked project.\"];\n}\n\nasync function fetchRemoteCollections(\n baseUrl: string,\n token: string | undefined,\n credential: ContractCredential\n): Promise<{ collections: CollectionConfig[]; schemaVersion: string }> {\n const url = `${baseUrl.replace(/\\/+$/, \"\")}/api/meta/contract`;\n\n const headers: Record<string, string> = { accept: \"application/json\" };\n if (token) headers.authorization = `Bearer ${token}`;\n\n let response: Response;\n try {\n response = await fetch(url, { headers });\n } catch (err) {\n console.log(chalk.red(` ✗ Could not reach ${url}`));\n console.log(chalk.gray(` ${err instanceof Error ? err.message : String(err)}`));\n process.exit(1);\n }\n\n if (response.status === 401 || response.status === 403) {\n console.log(chalk.red(` ✗ Not authorized to read the project contract (${response.status}).`));\n console.log(chalk.gray(\" The contract describes every table and relation, so it is admin-only.\"));\n for (const line of contractRefusalHint(credential)) console.log(chalk.gray(` ${line}`));\n process.exit(1);\n }\n\n if (response.status === 404) {\n console.log(chalk.red(\" ✗ This server has no contract endpoint.\"));\n console.log(chalk.gray(\" It needs to be running Rebase 0.11 or newer.\"));\n process.exit(1);\n }\n\n if (!response.ok) {\n console.log(chalk.red(` ✗ Contract request failed with ${response.status}.`));\n process.exit(1);\n }\n\n const contract = await response.json() as {\n collections?: unknown[];\n schemaVersion?: string;\n };\n\n if (!Array.isArray(contract.collections)) {\n console.log(chalk.red(\" ✗ The contract response did not contain collections.\"));\n process.exit(1);\n }\n\n return {\n collections: deserializeCollections(contract.collections),\n schemaVersion: contract.schemaVersion ?? \"unknown\"\n };\n}\n\n/**\n * Decide whether the ambient service key may be sent to this host.\n *\n * `REBASE_SERVICE_KEY` grants full admin bypass. Attaching it to whatever URL\n * happened to be passed — or, worse, to whatever a committed `.rebase/cloud.json`\n * points at — would hand the project's most powerful credential to a host nobody\n * vetted. An explicit `--token` is a decision the caller made; the ambient\n * variable is not, so it only travels to the project this checkout is linked to.\n */\nfunction mayUseAmbientKey(target: string, cwd: string): boolean {\n const link = readLink(findProjectRoot(cwd) ?? cwd);\n if (!link?.apiUrl) return false;\n try {\n // Origin, not host: with a link recorded as https, an `http://` target\n // for the same host would otherwise pass and send the key in cleartext.\n return new URL(link.apiUrl).origin === new URL(target).origin;\n } catch {\n return false;\n }\n}\n\n/**\n * The base URL to show in the printed usage example.\n *\n * `rebase dev` binds a port derived from the project path, not 3001, and writes\n * the one it actually got to `.rebase/state.json`. Printing a hardcoded\n * `localhost:3001` sent people to a port nothing was listening on — or, with\n * several projects on one machine, to a different project's backend. Prefer the\n * port `rebase dev` says it is starting the backend on (`DEV_BACKEND_URL_ENV`:\n * it regenerates the SDK before the backend binds), then the port this project\n * last ran on; fall back to the literal only when the project has never been\n * started.\n */\nexport function resolveExampleBaseUrl(cwd: string): string {\n const fromDev = process.env[DEV_BACKEND_URL_ENV]?.trim();\n if (fromDev) return fromDev;\n const projectRoot = findProjectRoot(cwd) ?? cwd;\n try {\n const state = JSON.parse(fs.readFileSync(path.join(projectRoot, \".rebase\", \"state.json\"), \"utf-8\"));\n if (typeof state.baseUrl === \"string\" && state.baseUrl) return state.baseUrl;\n if (typeof state.port === \"number\") return `http://localhost:${state.port}`;\n } catch {\n // Never started, or the file is unreadable — fall through.\n }\n return \"http://localhost:3001\";\n}\n\n/** Whether a slug can be written as `rebase.data.<slug>` rather than a lookup. */\nexport function isIdentifierLike(slug: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(slug);\n}\n\n/** Resolve `--from` into a base URL, following the link file when asked. */\nfunction resolveSchemaSource(from: string, cwd: string): string {\n if (from !== \"link\") {\n // A bare hostname or a typo would otherwise be handed to `fetch` and fail\n // with something unhelpful; a non-http scheme has no business here at all.\n let parsed: URL;\n try {\n parsed = new URL(from);\n } catch {\n console.log(chalk.red(` ✗ \"${from}\" is not a valid URL.`));\n console.log(chalk.gray(\" Pass a full URL, e.g. https://api.example.com, or \\\"link\\\".\"));\n process.exit(1);\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n console.log(chalk.red(\" ✗ The project URL must be http or https.\"));\n process.exit(1);\n }\n return from;\n }\n\n const projectRoot = findProjectRoot(cwd) ?? cwd;\n const link = readLink(projectRoot);\n\n if (!link) {\n console.log(chalk.red(\" ✗ This checkout is not linked to a project.\"));\n console.log(chalk.gray(\" Run `rebase cloud link <url>`, or pass --from <url>.\"));\n process.exit(1);\n }\n\n const apiUrl = link.apiUrl;\n if (!apiUrl) {\n console.log(chalk.red(\" ✗ The project link has no API URL.\"));\n console.log(chalk.gray(\" Re-link with `rebase cloud link <url>` to record one.\"));\n process.exit(1);\n }\n\n return apiUrl;\n}\n\n/**\n * Main entry point for the generate-sdk command.\n */\nexport async function generateSdkCommand(args: GenerateSDKArgs): Promise<void> {\n const { collectionsDir, output, cwd } = args;\n\n if (args.help) {\n printSdkHelp();\n return;\n }\n\n const resolvedCollectionsDir = path.isAbsolute(collectionsDir)\n ? collectionsDir\n : path.join(cwd, collectionsDir);\n\n const resolvedOutput = path.isAbsolute(output)\n ? output\n : path.join(cwd, output);\n\n console.log(\"\");\n console.log(chalk.bold(\" 🔧 Rebase SDK Generator\"));\n console.log(\"\");\n\n let collections: CollectionConfig[];\n let remoteSchemaVersion: string | undefined;\n\n if (args.from) {\n const baseUrl = resolveSchemaSource(args.from, cwd);\n console.log(` ${chalk.gray(\"Project:\")} ${baseUrl}`);\n console.log(` ${chalk.gray(\"Output:\")} ${resolvedOutput}`);\n console.log(\"\");\n console.log(chalk.cyan(\" → Fetching the project contract...\"));\n\n const ambient = mayUseAmbientKey(baseUrl, cwd)\n ? process.env.REBASE_SERVICE_KEY\n : undefined;\n\n if (!args.token && !ambient && process.env.REBASE_SERVICE_KEY) {\n console.log(chalk.dim(\n \" (not sending REBASE_SERVICE_KEY — this host is not the linked project; pass --token to override)\"\n ));\n }\n\n const remote = await fetchRemoteCollections(baseUrl, args.token || ambient, {\n sent: args.token ? \"token\" : ambient ? \"ambient\" : null,\n shellKey: Boolean(process.env.REBASE_SERVICE_KEY),\n envFileKey: Boolean(readEnvFile(findProjectRoot(cwd) ?? cwd).REBASE_SERVICE_KEY)\n });\n collections = remote.collections;\n remoteSchemaVersion = remote.schemaVersion;\n } else {\n // A headless project has no collections directory by design: its API is\n // introspected from the live database at boot, and there is nothing here\n // to generate a client from. The scaffold ships `pnpm generate:sdk`\n // anyway, so the documented headless path had a script that could only\n // ever fail — and it failed with a path, which reads as a broken install\n // rather than a question with an answer.\n if (!fs.existsSync(resolvedCollectionsDir)) {\n console.log(chalk.gray(\n \" ○ This project derives its API from the database — \"\n + \"run `rebase schema introspect` first.\"\n ));\n console.log(chalk.gray(\n ` Nothing to generate from: ${resolvedCollectionsDir} does not exist.`\n ));\n console.log(\"\");\n return;\n }\n console.log(` ${chalk.gray(\"Collections:\")} ${resolvedCollectionsDir}`);\n console.log(` ${chalk.gray(\"Output:\")} ${resolvedOutput}`);\n console.log(\"\");\n console.log(chalk.cyan(\" → Loading collection definitions...\"));\n collections = await loadCollections(resolvedCollectionsDir);\n }\n\n // Sort collections alphabetically by slug to ensure deterministic SDK generation\n collections.sort((a, b) => a.slug.localeCompare(b.slug));\n\n if (collections.length === 0) {\n console.log(chalk.red(\" ✗ No collections found. Nothing to generate.\"));\n process.exit(1);\n }\n\n console.log(chalk.green(` ✓ Found ${collections.length} collection(s): ${collections.map(c => c.slug).join(\", \")}`));\n console.log(\"\");\n\n // 2. Generate SDK files\n console.log(chalk.cyan(\" → Generating SDK files...\"));\n let files: GeneratedFile[];\n try {\n files = generateSDK(collections, { baseUrl: resolveExampleBaseUrl(cwd) });\n } catch (err) {\n // A schema that cannot be expressed as valid TypeScript — two slugs\n // that collide on one accessor, a slug with no usable name. The\n // generator refuses rather than emitting a file that does not compile,\n // or one that silently routes a collection's reads to another's table.\n if (err instanceof CodegenError) {\n console.log(\"\");\n console.log(chalk.red(` ✗ ${err.message}`));\n process.exit(1);\n }\n throw err;\n }\n\n // Stamp the schema this SDK was built from.\n //\n // Without it, an app in a separate repository has no way to know its client\n // is stale: the backend moves on, the frontend keeps compiling against types\n // captured weeks ago, and the mismatch only surfaces as a runtime error. With\n // it, CI can compare against `/api/meta/schema-version` and say so.\n //\n // No generation timestamp. Collections are sorted above precisely so that\n // the same schema produces the same bytes; a timestamp put that back,\n // turning every regeneration into a diff and making the obvious staleness\n // gate — `rebase generate-sdk && git diff --exit-code` — impossible to pass.\n // `SCHEMA_VERSION` already identifies what this was built from, and does it\n // in a way that can be compared against a running project.\n const schemaVersion = remoteSchemaVersion ?? computeSchemaVersion(collections);\n files.push({\n path: \"schema.meta.ts\",\n content: `// Auto-generated by \\`rebase generate-sdk\\`. Do not edit.\n//\n// The schema version this SDK was generated from. Compare it against the\n// project's current version to detect drift:\n//\n// curl -s <api-url>/api/meta/schema-version\n//\n// Pass it to the client as \\`schemaVersion\\` and every request carries it in\n// the \\`x-rebase-schema\\` header, so the server can name the drift instead of\n// answering a renamed field with a bare 400.\nexport const SCHEMA_VERSION = ${JSON.stringify(schemaVersion)};\n`\n });\n\n console.log(chalk.green(` ✓ Generated ${files.length} file(s)`));\n console.log(chalk.gray(` schema ${schemaVersion}`));\n\n // 3. Write to disk\n console.log(chalk.cyan(` → Writing to ${resolvedOutput}...`));\n writeFiles(resolvedOutput, files);\n\n // 4. The server-side registration: on request, and kept current once a\n // project has it, so `rebase dev` regenerating the SDK never leaves the\n // server typed against an older schema than the client.\n const registerDir = registrationDir(resolvedCollectionsDir);\n const projectRoot = args.projectRoot ?? findProjectRoot(cwd) ?? undefined;\n if (args.register || hasRegistration(registerDir) || manifestRegisters(projectRoot)) {\n if (!fs.existsSync(path.dirname(registerDir))) {\n console.log(chalk.red(` ✗ No ${path.dirname(registerDir)} to register the Database in.`));\n console.log(chalk.gray(\" --register writes beside the collections directory; pass --collections.\"));\n process.exit(1);\n return;\n }\n const databaseTypes = files.find((file) => file.path === \"database.types.ts\")?.content;\n if (databaseTypes !== undefined) {\n try {\n writeRegistration(registerDir, databaseTypes);\n } catch (error) {\n console.log(chalk.red(` ✗ ${error instanceof Error ? error.message : String(error)}`));\n process.exit(1);\n return;\n }\n console.log(chalk.green(` ✓ Registered the Database for server-side code in ${registerDir}`));\n if (args.register) {\n const remembered = rememberRegistration(projectRoot);\n if (\"written\" in remembered) {\n console.log(chalk.gray(` Remembered in ${path.relative(cwd, remembered.written) || \"rebase.json\"} (registerDatabase).`));\n } else {\n console.log(chalk.yellow(` ${remembered.skipped}`));\n }\n }\n }\n }\n\n console.log(\"\");\n console.log(chalk.green.bold(\" ✓ SDK generated successfully!\"));\n console.log(\"\");\n const typesImport = `./${path.relative(cwd, path.join(resolvedOutput, \"database.types\"))}`;\n const metaImport = `./${path.relative(cwd, path.join(resolvedOutput, \"schema.meta\"))}`;\n const exampleSlug = collections[0]?.slug || \"my_collection\";\n\n console.log(chalk.gray(\" Usage:\"));\n console.log(chalk.gray(\" import { createRebaseClient } from '@rebasepro/client';\"));\n console.log(chalk.gray(` import { collectionsDictionary, type Database } from '${typesImport}';`));\n console.log(chalk.gray(` import { SCHEMA_VERSION } from '${metaImport}';`));\n console.log(\"\");\n console.log(chalk.gray(\" const rebase = createRebaseClient<Database>({\"));\n console.log(chalk.gray(` baseUrl: '${resolveExampleBaseUrl(cwd)}',`));\n // Sent as `x-rebase-schema` on every request. Costs one line here and is\n // the difference between a server that can say \"this client is three\n // deploys behind\" and one that can only reject a field it does not know.\n console.log(chalk.gray(\" schemaVersion: SCHEMA_VERSION,\"));\n // Without the dictionary a hyphenated slug is not resolvable from the\n // property name alone, and the request 404s at runtime.\n console.log(chalk.gray(\" collections: collectionsDictionary,\"));\n console.log(chalk.gray(\" // token: 'your-jwt-token',\"));\n console.log(chalk.gray(\" });\"));\n console.log(\"\");\n // `rebase.data.<accessor>` is the typed surface, so it is what gets printed.\n // `rebase.data.collection(slug)` exists too, but it is generic over\n // `Record<string, unknown>` and has no link to `Database` — it was the\n // headline example here for a while, which advertised the one call shape\n // that throws away the types this command just generated.\n const exampleAccessor = toCollectionAccessor(exampleSlug);\n const exampleAccess = isIdentifierLike(exampleAccessor)\n ? `rebase.data.${exampleAccessor}`\n : `rebase.data[${JSON.stringify(exampleAccessor)}]`;\n console.log(chalk.gray(` const { data } = await ${exampleAccess}.find();`));\n console.log(\"\");\n}\n"],"mappings":"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"}
|
package/dist/index.es.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { i as recordEvent, n as isEnabled, u as errorClass } from "./telemetry-
|
|
2
|
-
import { p as requireProjectRoot } from "./project-
|
|
3
|
-
import { a as unknownCommand, n as parseCommandArgs } from "./args-BX0YD14a.js";
|
|
1
|
+
import { i as recordEvent, n as isEnabled, u as errorClass } from "./telemetry-HfU5uAh1.js";
|
|
2
|
+
import { T as unknownCommand, b as parseCommandArgs, p as requireProjectRoot } from "./project-g4K6kV1t.js";
|
|
4
3
|
import { n as cliVersion } from "./version-Buyyo1ut.js";
|
|
5
|
-
import { _ as selectDeployApp, a as DEFAULT_SCHEMA_FILE, b as validateManifest, c as buildableApps, d as findBackendApp, f as formatAppAddress, g as resolveBackendPaths, h as manifestPath, i as DEFAULT_FUNCTIONS_DIR, l as cmsMountOf, m as manifestExists, n as DEFAULT_CONFIG_DIR, o as ManifestError, p as loadManifest, r as DEFAULT_CRONS_DIR, s as assessManagedCompatibility, t as CURRENT_RUNTIME_RANGE, u as compareMountOrder, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-
|
|
6
|
-
import { _ as foldStaticIntoBundle, a as VENDOR_TARGET_OS, c as collectDeclaredDependencies, d as describeDepConflicts, f as detectDeclaredDepConflicts, g as findUnusedServerEntry, h as detectStorageAuthorize, i as VENDOR_TARGET_CPU, l as commentSpans, m as detectNativeDependencies, n as VENDOR_SIZE_MAX_BYTES, o as buildBundle, p as detectFrameworkDepDrift, r as VENDOR_SIZE_WARN_BYTES, s as buildStaticBundle, t as DEFAULT_BUNDLE_DIR, u as composeBundleManifest, v as normalizeEsmSpecifiers, y as vendorDependencies } from "./bundle-
|
|
4
|
+
import { _ as selectDeployApp, a as DEFAULT_SCHEMA_FILE, b as validateManifest, c as buildableApps, d as findBackendApp, f as formatAppAddress, g as resolveBackendPaths, h as manifestPath, i as DEFAULT_FUNCTIONS_DIR, l as cmsMountOf, m as manifestExists, n as DEFAULT_CONFIG_DIR, o as ManifestError, p as loadManifest, r as DEFAULT_CRONS_DIR, s as assessManagedCompatibility, t as CURRENT_RUNTIME_RANGE, u as compareMountOrder, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-nvPdLlJY.js";
|
|
5
|
+
import { _ as foldStaticIntoBundle, a as VENDOR_TARGET_OS, c as collectDeclaredDependencies, d as describeDepConflicts, f as detectDeclaredDepConflicts, g as findUnusedServerEntry, h as detectStorageAuthorize, i as VENDOR_TARGET_CPU, l as commentSpans, m as detectNativeDependencies, n as VENDOR_SIZE_MAX_BYTES, o as buildBundle, p as detectFrameworkDepDrift, r as VENDOR_SIZE_WARN_BYTES, s as buildStaticBundle, t as DEFAULT_BUNDLE_DIR, u as composeBundleManifest, v as normalizeEsmSpecifiers, y as vendorDependencies } from "./bundle-DlqkDYSe.js";
|
|
7
6
|
import chalk from "chalk";
|
|
8
7
|
import arg from "arg";
|
|
9
8
|
import path from "path";
|
|
@@ -89,39 +88,39 @@ var NO_VOCABULARY = {
|
|
|
89
88
|
async function commandVocabulary(command) {
|
|
90
89
|
switch (command) {
|
|
91
90
|
case "schema": return {
|
|
92
|
-
subcommands: (await import("./schema-
|
|
91
|
+
subcommands: (await import("./schema-nuxvvc50.js")).SCHEMA_SUBCOMMANDS,
|
|
93
92
|
aliases: {}
|
|
94
93
|
};
|
|
95
94
|
case "db": return {
|
|
96
|
-
subcommands: (await import("./db-
|
|
95
|
+
subcommands: (await import("./db-9P6MnmdC.js")).DB_SUBCOMMANDS,
|
|
97
96
|
aliases: {}
|
|
98
97
|
};
|
|
99
98
|
case "auth": return {
|
|
100
|
-
subcommands: (await import("./auth-
|
|
99
|
+
subcommands: (await import("./auth-DRsTWPky.js")).AUTH_SUBCOMMANDS,
|
|
101
100
|
aliases: {}
|
|
102
101
|
};
|
|
103
102
|
case "skills": return {
|
|
104
|
-
subcommands: (await import("./skills-
|
|
103
|
+
subcommands: (await import("./skills-DeUIsZcT.js")).SKILLS_SUBCOMMANDS,
|
|
105
104
|
aliases: {}
|
|
106
105
|
};
|
|
107
106
|
case "api-keys": return {
|
|
108
|
-
subcommands: (await import("./api-keys-
|
|
107
|
+
subcommands: (await import("./api-keys-CSMbsmAn.js")).API_KEYS_SUBCOMMANDS,
|
|
109
108
|
aliases: {}
|
|
110
109
|
};
|
|
111
110
|
case "storage": return {
|
|
112
|
-
subcommands: (await import("./storage-
|
|
111
|
+
subcommands: (await import("./storage-BB3umRfw.js")).STORAGE_SUBCOMMANDS,
|
|
113
112
|
aliases: {}
|
|
114
113
|
};
|
|
115
114
|
case "apps": return {
|
|
116
|
-
subcommands: (await import("./apps-
|
|
115
|
+
subcommands: (await import("./apps-iBXNZhVN.js")).APPS_SUBCOMMANDS,
|
|
117
116
|
aliases: {}
|
|
118
117
|
};
|
|
119
118
|
case "telemetry": return {
|
|
120
|
-
subcommands: (await import("./telemetry-
|
|
119
|
+
subcommands: (await import("./telemetry-TseNLk6X.js")).TELEMETRY_SUBCOMMANDS,
|
|
121
120
|
aliases: {}
|
|
122
121
|
};
|
|
123
122
|
case "cloud": {
|
|
124
|
-
const cloud = await import("./cloud-
|
|
123
|
+
const cloud = await import("./cloud-B-ZIjHrA.js");
|
|
125
124
|
return {
|
|
126
125
|
subcommands: cloud.CLOUD_GROUP_NAMES,
|
|
127
126
|
aliases: cloud.GROUP_ALIASES
|
|
@@ -243,12 +242,12 @@ async function entry(args) {
|
|
|
243
242
|
async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespacedCommands) {
|
|
244
243
|
switch (command) {
|
|
245
244
|
case "__dev-db-daemon": {
|
|
246
|
-
const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-
|
|
245
|
+
const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-zOC1revO.js");
|
|
247
246
|
await runDaemon(parseDaemonArgs(args));
|
|
248
247
|
return;
|
|
249
248
|
}
|
|
250
249
|
case "init": {
|
|
251
|
-
const { createRebaseApp } = await import("./init-
|
|
250
|
+
const { createRebaseApp } = await import("./init-DYaeppEN.js");
|
|
252
251
|
await createRebaseApp(args);
|
|
253
252
|
break;
|
|
254
253
|
}
|
|
@@ -271,7 +270,7 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
|
|
|
271
270
|
maxPositionals: 0
|
|
272
271
|
});
|
|
273
272
|
const sdkRoot = sdkHelp ? process.cwd() : requireProjectRoot();
|
|
274
|
-
const { generateSdkCommand } = await import("./generate_sdk-
|
|
273
|
+
const { generateSdkCommand } = await import("./generate_sdk-B4R65oUV.js");
|
|
275
274
|
await generateSdkCommand({
|
|
276
275
|
collectionsDir: sdkArgs["--collections"] || path.join(sdkRoot, "config/collections"),
|
|
277
276
|
output: sdkArgs["--output"] || path.join(sdkRoot, "generated/sdk"),
|
|
@@ -285,101 +284,101 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
|
|
|
285
284
|
break;
|
|
286
285
|
}
|
|
287
286
|
case "schema": {
|
|
288
|
-
const { schemaCommand } = await import("./schema-
|
|
287
|
+
const { schemaCommand } = await import("./schema-nuxvvc50.js");
|
|
289
288
|
await schemaCommand(effectiveSubcommand, args);
|
|
290
289
|
break;
|
|
291
290
|
}
|
|
292
291
|
case "db": {
|
|
293
|
-
const { dbCommand } = await import("./db-
|
|
292
|
+
const { dbCommand } = await import("./db-9P6MnmdC.js");
|
|
294
293
|
await dbCommand(effectiveSubcommand, args);
|
|
295
294
|
break;
|
|
296
295
|
}
|
|
297
296
|
case "console": {
|
|
298
|
-
const { consoleCommand } = await import("./console-
|
|
297
|
+
const { consoleCommand } = await import("./console-BlD9kjFW.js");
|
|
299
298
|
await consoleCommand(args);
|
|
300
299
|
break;
|
|
301
300
|
}
|
|
302
301
|
case "dev": {
|
|
303
|
-
const { devCommand } = await import("./dev-
|
|
302
|
+
const { devCommand } = await import("./dev-BDN_OKXA.js");
|
|
304
303
|
await devCommand(args);
|
|
305
304
|
break;
|
|
306
305
|
}
|
|
307
306
|
case "normalize-imports": {
|
|
308
|
-
const { normalizeImportsCommand } = await import("./normalize-imports-
|
|
307
|
+
const { normalizeImportsCommand } = await import("./normalize-imports-BYw8ad87.js");
|
|
309
308
|
await normalizeImportsCommand(args);
|
|
310
309
|
break;
|
|
311
310
|
}
|
|
312
311
|
case "build": {
|
|
313
|
-
const { buildCommand } = await import("./build-
|
|
312
|
+
const { buildCommand } = await import("./build-et7Rccxi.js").then((n) => n.n);
|
|
314
313
|
await buildCommand(args);
|
|
315
314
|
break;
|
|
316
315
|
}
|
|
317
316
|
case "start": {
|
|
318
|
-
const { startCommand } = await import("./start-
|
|
317
|
+
const { startCommand } = await import("./start-RzZqDroW.js");
|
|
319
318
|
await startCommand(args);
|
|
320
319
|
break;
|
|
321
320
|
}
|
|
322
321
|
case "upgrade": {
|
|
323
|
-
const { upgradeCommand } = await import("./upgrade-
|
|
322
|
+
const { upgradeCommand } = await import("./upgrade-apiPKKE_.js");
|
|
324
323
|
await upgradeCommand(args);
|
|
325
324
|
break;
|
|
326
325
|
}
|
|
327
326
|
case "apps": {
|
|
328
|
-
const { appsCommand } = await import("./apps-
|
|
327
|
+
const { appsCommand } = await import("./apps-iBXNZhVN.js");
|
|
329
328
|
await appsCommand(effectiveSubcommand, args);
|
|
330
329
|
break;
|
|
331
330
|
}
|
|
332
331
|
case "eject": {
|
|
333
|
-
const { ejectCommand } = await import("./eject-
|
|
332
|
+
const { ejectCommand } = await import("./eject-izG2KjMo.js");
|
|
334
333
|
await ejectCommand(args);
|
|
335
334
|
break;
|
|
336
335
|
}
|
|
337
336
|
case "auth": {
|
|
338
|
-
const { authCommand } = await import("./auth-
|
|
337
|
+
const { authCommand } = await import("./auth-DRsTWPky.js");
|
|
339
338
|
await authCommand(effectiveSubcommand, args);
|
|
340
339
|
break;
|
|
341
340
|
}
|
|
342
341
|
case "status": {
|
|
343
|
-
const { statusCommand } = await import("./status-
|
|
342
|
+
const { statusCommand } = await import("./status-D9Zm88NZ.js");
|
|
344
343
|
await statusCommand(args);
|
|
345
344
|
break;
|
|
346
345
|
}
|
|
347
346
|
case "resources": {
|
|
348
|
-
const { resourcesCommand } = await import("./resources-
|
|
347
|
+
const { resourcesCommand } = await import("./resources-CovP8AZ-.js");
|
|
349
348
|
await resourcesCommand(args);
|
|
350
349
|
break;
|
|
351
350
|
}
|
|
352
351
|
case "doctor": {
|
|
353
|
-
const { doctorCommand } = await import("./doctor-
|
|
352
|
+
const { doctorCommand } = await import("./doctor-D8YXz7df.js");
|
|
354
353
|
await doctorCommand(args);
|
|
355
354
|
break;
|
|
356
355
|
}
|
|
357
356
|
case "skills": {
|
|
358
|
-
const { skillsCommand } = await import("./skills-
|
|
357
|
+
const { skillsCommand } = await import("./skills-DeUIsZcT.js");
|
|
359
358
|
await skillsCommand(effectiveSubcommand, args);
|
|
360
359
|
break;
|
|
361
360
|
}
|
|
362
361
|
case "api-keys": {
|
|
363
|
-
const { apiKeysCommand } = await import("./api-keys-
|
|
362
|
+
const { apiKeysCommand } = await import("./api-keys-CSMbsmAn.js");
|
|
364
363
|
await apiKeysCommand(effectiveSubcommand, args);
|
|
365
364
|
break;
|
|
366
365
|
}
|
|
367
366
|
case "storage": {
|
|
368
|
-
const { storageCommand } = await import("./storage-
|
|
367
|
+
const { storageCommand } = await import("./storage-BB3umRfw.js");
|
|
369
368
|
await storageCommand(effectiveSubcommand, args);
|
|
370
369
|
break;
|
|
371
370
|
}
|
|
372
371
|
case "cloud": {
|
|
373
|
-
const { cloudCommand } = await import("./cloud-
|
|
372
|
+
const { cloudCommand } = await import("./cloud-B-ZIjHrA.js");
|
|
374
373
|
await cloudCommand(effectiveSubcommand, args);
|
|
375
374
|
break;
|
|
376
375
|
}
|
|
377
376
|
case "telemetry": {
|
|
378
|
-
const { telemetryCommand } = await import("./telemetry-
|
|
377
|
+
const { telemetryCommand } = await import("./telemetry-TseNLk6X.js");
|
|
379
378
|
await telemetryCommand(args);
|
|
380
379
|
break;
|
|
381
380
|
}
|
|
382
|
-
default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-
|
|
381
|
+
default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-B-ZIjHrA.js")).CLOUD_GROUP_NAMES });
|
|
383
382
|
}
|
|
384
383
|
}
|
|
385
384
|
/** The global help. Exported so its Options block can be held against {@link ROOT_FLAGS}. */
|