@rebasepro/cli 0.23.0 → 0.24.1-canary.g19596ef
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/README.md +19 -3
- package/bin/rebase.js +4 -1
- package/dist/agent-setup-B31F00DC.js +324 -0
- package/dist/agent-setup-B31F00DC.js.map +1 -0
- package/dist/api-keys-Bl1I9q7M.js +525 -0
- package/dist/api-keys-Bl1I9q7M.js.map +1 -0
- package/dist/apps-CNgQJjg5.js +340 -0
- package/dist/apps-CNgQJjg5.js.map +1 -0
- package/dist/args-BnmsEXvu.js +109 -0
- package/dist/args-BnmsEXvu.js.map +1 -0
- package/dist/atlas-dev-database-D_LP_Woq.js +62 -0
- package/dist/atlas-dev-database-D_LP_Woq.js.map +1 -0
- package/dist/auth-aySHEF45.js +414 -0
- package/dist/auth-aySHEF45.js.map +1 -0
- package/dist/branch-pointer-DvSHBjjz.js +2 -0
- package/dist/build-DIHWIqO4.js +336 -0
- package/dist/build-DIHWIqO4.js.map +1 -0
- package/dist/bundle-CqURVN-K.js +1621 -0
- package/dist/bundle-CqURVN-K.js.map +1 -0
- package/dist/bundle.d.ts +12 -3
- package/dist/cli.d.ts +23 -2
- package/dist/cloud-DjByQlkW.js +9667 -0
- package/dist/cloud-DjByQlkW.js.map +1 -0
- package/dist/collection-drift-BKj_BoMq.js +106 -0
- package/dist/collection-drift-BKj_BoMq.js.map +1 -0
- package/dist/commands/__test_support__/parser-specs.d.ts +13 -0
- package/dist/commands/agent-setup.d.ts +116 -0
- package/dist/commands/api-keys.d.ts +86 -23
- package/dist/commands/apps.d.ts +17 -0
- package/dist/commands/auth.d.ts +7 -0
- package/dist/commands/build.d.ts +5 -1
- package/dist/commands/cloud/auth.d.ts +4 -3
- package/dist/commands/cloud/bundle-deploy.d.ts +45 -0
- package/dist/commands/cloud/context.d.ts +44 -5
- package/dist/commands/cloud/cron.d.ts +53 -0
- package/dist/commands/cloud/debug.d.ts +134 -0
- package/dist/commands/cloud/index.d.ts +89 -12
- package/dist/commands/cloud/token-capabilities.d.ts +76 -0
- package/dist/commands/cloud/tokens.d.ts +23 -0
- package/dist/commands/console.d.ts +12 -0
- package/dist/commands/db.d.ts +79 -25
- package/dist/commands/dev.d.ts +181 -13
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/generate_sdk.d.ts +29 -2
- package/dist/commands/init.d.ts +115 -14
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/skills.d.ts +126 -7
- package/dist/commands/start.d.ts +44 -0
- package/dist/commands/storage.d.ts +46 -0
- package/dist/commands/upgrade.d.ts +1 -0
- package/dist/consent-ClRHmcxf.js +76 -0
- package/dist/consent-ClRHmcxf.js.map +1 -0
- package/dist/console-D6SJf8k_.js +102 -0
- package/dist/console-D6SJf8k_.js.map +1 -0
- package/dist/context-BqhRydBg.js +1234 -0
- package/dist/context-BqhRydBg.js.map +1 -0
- package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
- package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
- package/dist/daemon-pzsQwDHa.js +2 -0
- package/dist/db-B7RuNuaQ.js +1312 -0
- package/dist/db-B7RuNuaQ.js.map +1 -0
- package/dist/derive-Dl0z2OWi.js +484 -0
- package/dist/derive-Dl0z2OWi.js.map +1 -0
- package/dist/dev-CYr_WXan.js +1599 -0
- package/dist/dev-CYr_WXan.js.map +1 -0
- package/dist/dev-db/atlas-dev-database.d.ts +32 -0
- package/dist/dev-db/daemon-entry.d.ts +13 -0
- package/dist/dev-db/daemon.d.ts +10 -0
- package/dist/dev-db/last-dev-database.d.ts +41 -0
- package/dist/dev-db/prepare.d.ts +29 -3
- package/dist/dev-db/pull.d.ts +90 -5
- package/dist/dev-db/resolve.d.ts +26 -2
- package/dist/dev-preflight-B-LYyBf1.js +2 -0
- package/dist/dev-server-DG8Tt-uf.js +96 -0
- package/dist/dev-server-DG8Tt-uf.js.map +1 -0
- package/dist/doctor-BP8cZ-7F.js +771 -0
- package/dist/doctor-BP8cZ-7F.js.map +1 -0
- package/dist/eject-DizdoecV.js +335 -0
- package/dist/eject-DizdoecV.js.map +1 -0
- package/dist/fold-static-BC9CYicw.js +201 -0
- package/dist/fold-static-BC9CYicw.js.map +1 -0
- package/dist/fold-static.d.ts +26 -3
- package/dist/function-portability-BIvlvR9q.js +265 -0
- package/dist/function-portability-BIvlvR9q.js.map +1 -0
- package/dist/generate_sdk-BPqdJc3Q.js +489 -0
- package/dist/generate_sdk-BPqdJc3Q.js.map +1 -0
- package/dist/index.es.js +199 -22095
- package/dist/index.es.js.map +1 -1
- package/dist/init-Utstvh2Q.js +1149 -0
- package/dist/init-Utstvh2Q.js.map +1 -0
- package/dist/last-dev-database-B58g89uA.js +2 -0
- package/dist/manifest-DRp0UVTj.js +880 -0
- package/dist/manifest-DRp0UVTj.js.map +1 -0
- package/dist/manifest.d.ts +56 -4
- package/dist/normalize-imports-X0Tgze9y.js +107 -0
- package/dist/normalize-imports-X0Tgze9y.js.map +1 -0
- package/dist/package-manager-DSEOwTqM.js +193 -0
- package/dist/package-manager-DSEOwTqM.js.map +1 -0
- package/dist/path-flags-BFgG9V6y.js +91 -0
- package/dist/path-flags-BFgG9V6y.js.map +1 -0
- package/dist/precompress.d.ts +17 -0
- package/dist/prepare-CDN6lSpz.js +1236 -0
- package/dist/prepare-CDN6lSpz.js.map +1 -0
- package/dist/{project-3WCbrrfW.js → project-Wp2zoyeN.js} +34 -184
- package/dist/project-Wp2zoyeN.js.map +1 -0
- package/dist/pull-CrGYMEsy.js +458 -0
- package/dist/pull-CrGYMEsy.js.map +1 -0
- package/dist/resolve-B2O-wKKk.js +2 -0
- package/dist/resources-FD7AfZx8.js +183 -0
- package/dist/resources-FD7AfZx8.js.map +1 -0
- package/dist/schema-DMdr431S.js +125 -0
- package/dist/schema-DMdr431S.js.map +1 -0
- package/dist/skills-DTFibT1m.js +642 -0
- package/dist/skills-DTFibT1m.js.map +1 -0
- package/dist/start-DEa-hOBh.js +267 -0
- package/dist/start-DEa-hOBh.js.map +1 -0
- package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
- package/dist/state-Do7ZJYkF.js.map +1 -0
- package/dist/status-DxnJTekv.js +352 -0
- package/dist/status-DxnJTekv.js.map +1 -0
- package/dist/storage-DyVq-f_F.js +303 -0
- package/dist/storage-DyVq-f_F.js.map +1 -0
- package/dist/telemetry/identity.d.ts +10 -1
- package/dist/telemetry-C8Uq8phb.js +129 -0
- package/dist/telemetry-C8Uq8phb.js.map +1 -0
- package/dist/telemetry-EMFRVRQi.js +351 -0
- package/dist/telemetry-EMFRVRQi.js.map +1 -0
- package/dist/unknown-command-DNwDcX3w.js +98 -0
- package/dist/unknown-command-DNwDcX3w.js.map +1 -0
- package/dist/upgrade-CtZtRkTE.js +1332 -0
- package/dist/upgrade-CtZtRkTE.js.map +1 -0
- package/dist/upgrade.d.ts +38 -5
- package/dist/utils/dev-preflight.d.ts +47 -5
- package/dist/utils/dev-server.d.ts +30 -0
- package/dist/utils/path-flags.d.ts +31 -0
- package/dist/utils/project.d.ts +16 -0
- package/dist/utils/temp-archive.d.ts +9 -0
- package/dist/version-Buyyo1ut.js +58 -0
- package/dist/version-Buyyo1ut.js.map +1 -0
- package/package.json +7 -7
- package/templates/eject/Dockerfile +4 -2
- package/templates/eject/backend/src/env.ts +1 -1
- package/templates/eject/backend/src/index.ts +42 -4
- package/templates/eject/docker-compose.custom.yml +8 -4
- package/templates/generated-schemas/blank.ts +40 -0
- package/templates/generated-schemas/blog.ts +127 -0
- package/templates/generated-schemas/ecommerce.ts +93 -0
- package/templates/overlays/baas/ai-instructions.md +1 -1
- package/templates/overlays/baas/config/package.json +1 -0
- package/templates/overlays/baas/config/storage.ts +5 -3
- package/templates/overlays/baas/package.json +1 -0
- package/templates/template/.cursorrules +1 -1
- package/templates/template/.env.example +20 -10
- package/templates/template/.github/copilot-instructions.md +1 -1
- package/templates/template/.mcp.json +2 -2
- package/templates/template/.windsurfrules +1 -1
- package/templates/template/AGENTS.md +1 -1
- package/templates/template/CLAUDE.md +1 -1
- package/templates/template/README.md +21 -15
- package/templates/template/ai-instructions.md +5 -4
- package/templates/template/backend/functions/hello.ts +8 -0
- package/templates/template/backend/package.json +1 -1
- package/templates/template/config/resources.ts +7 -6
- package/templates/template/config/storage.ts +5 -3
- package/templates/template/docker-compose.yml +15 -9
- package/templates/template/frontend/vite.config.ts +13 -3
- package/templates/template/gitignore +6 -1
- package/templates/template/package.json +5 -3
- package/templates/template/scripts/example.ts +6 -4
- package/templates/template/tsconfig.json +25 -0
- package/dist/branch-pointer-dBiClJ0p.js +0 -111
- package/dist/branch-pointer-dBiClJ0p.js.map +0 -1
- package/dist/constraints-DKGbNfUW.js +0 -48
- package/dist/constraints-DKGbNfUW.js.map +0 -1
- package/dist/daemon-DR9Tk0La.js +0 -355
- package/dist/daemon-DR9Tk0La.js.map +0 -1
- package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
- package/dist/dev-preflight-CNLl4rdo.js +0 -367
- package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
- package/dist/project-3WCbrrfW.js.map +0 -1
- package/dist/pull-Dywm5FWP.js +0 -232
- package/dist/pull-Dywm5FWP.js.map +0 -1
- package/dist/resolve-BAeRUBhg.js +0 -74
- package/dist/resolve-BAeRUBhg.js.map +0 -1
- package/dist/state-C59Elrnt.js.map +0 -1
- package/templates/template/backend/src/schema.generated.ts +0 -13
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-Utstvh2Q.js","names":[],"sources":["../src/commands/init.ts"],"sourcesContent":["import inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport net from \"net\";\nimport { promisify } from \"util\";\nimport { execa } from \"execa\";\nimport { cp } from \"fs/promises\";\nimport { fileURLToPath } from \"url\";\nimport crypto from \"crypto\";\nimport { detectPackageManager, getPMCommands } from \"../utils/package-manager\";\nimport { cliVersion } from \"../utils/version\";\nimport type arg from \"arg\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport { resolveCloudUrl, writeLink } from \"./cloud/context\";\nimport type { PackageManager, PMCommands } from \"../utils/package-manager\";\nimport { promptForConsent } from \"../telemetry/consent\";\nimport { durationBucket, recordEvent } from \"../telemetry\";\nimport { parseEnvBoolean } from \"@rebasepro/types\";\nimport { AGENT_KEYS, AGENTS, type AgentKey, resolveAgentNames } from \"./skills\";\nimport { configureAgents, printAgentSetup, promptForAgents, retargetScaffoldMcpConfig } from \"./agent-setup\";\n\nconst access = promisify(fs.access);\n\n\n// Resolve template path relative to this file\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nfunction findParentDir(currentDir: string, targetName: string): string | null {\n const root = path.parse(currentDir).root;\n while (currentDir && currentDir !== root) {\n if (path.basename(currentDir) === targetName) {\n return currentDir;\n }\n currentDir = path.dirname(currentDir);\n }\n return null;\n}\n\nconst cliRoot = findParentDir(__dirname, \"cli\");\n\nconst PROJECT_NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;\n\n/**\n * Every scaffolded file that carries a `{{PLACEHOLDER}}`.\n *\n * Exported because it is the single source of truth: `init.test.ts` reads it and\n * asserts that every template file containing `{{` appears here. It used to be a\n * local, with the test harness keeping a *second* copy — so the two drifted, and\n * a test built on the copy could not observe the production list at all.\n *\n * The drift shipped: `docker-compose.yml` arrived with the self-host work\n * (26fd5259c) and was added to neither, so every scaffolded project got a literal\n * `name: {{PROJECT_NAME}}`. In YAML `{{...}}` is a map, not a string, so the\n * documented `docker compose up` path failed on the file before doing anything:\n *\n * yaml: unmarshal errors: line 28: cannot unmarshal !!map into string\n */\nexport const TEMPLATE_PLACEHOLDER_FILES = [\n \"package.json\",\n \"frontend/package.json\",\n \"backend/package.json\",\n \"config/package.json\",\n \"frontend/index.html\",\n \"pnpm-workspace.yaml\",\n \"docker-compose.yml\",\n \"README.md\"\n];\n\n/** Returns an error message, or null when the name is a valid package name. */\nexport function validateProjectName(name: string): string | null {\n if (!name.trim()) return \"Project name is required\";\n if (!PROJECT_NAME_RE.test(name)) {\n return \"Project name must start with a lowercase letter or number and contain only lowercase letters, numbers, hyphens, dots, or underscores\";\n }\n return null;\n}\n\nexport type TemplatePreset = \"blog\" | \"ecommerce\" | \"blank\";\n\n/**\n * Whether to scaffold the admin panel alongside the backend.\n *\n * A boolean, not a named pair. It was `--flavor cms|baas`, and neither word\n * survived what they described: \"cms\" is a product category rather than a thing\n * this tool builds, and \"baas\" was the same value that used to appear as\n * `backend.mode` — which is now derived from whether collections are declared.\n * What is left is one question: does this project get an admin UI?\n */\nconst HEADLESS_CHOICES: Array<{ name: string; value: boolean; short: string }> = [\n { name: \"Backend + admin — API plus an admin UI, driven by collections you define (like Payload/Directus)\",\nvalue: false,\nshort: \"Backend + admin\" },\n { name: \"Backend only — headless API over your database. No collections, no UI (like Supabase)\",\nvalue: true,\nshort: \"Backend only\" }\n];\n\nconst PRESET_CHOICES: Array<{ name: string; value: TemplatePreset; short: string }> = [\n { name: \"Blog — Posts, Authors, Tags (with markdown editor)\",\nvalue: \"blog\",\nshort: \"Blog\" },\n { name: \"E-commerce — Products, Categories, Orders\",\nvalue: \"ecommerce\",\nshort: \"E-commerce\" },\n { name: \"Blank — Empty project, just authentication\",\nvalue: \"blank\",\nshort: \"Blank\" }\n];\n\nexport interface InitOptions {\n projectName: string;\n git: boolean;\n installDeps: boolean;\n targetDirectory: string;\n templateDirectory: string;\n databaseUrl?: string;\n introspect?: boolean;\n /** Starter template preset. */\n preset: TemplatePreset;\n /** Whether `preset` came from an explicit --template rather than the default. */\n explicitPreset?: boolean;\n /** Scaffold the backend alone, with no admin panel and no collections. */\n headless: boolean;\n /** Detected package manager (pnpm or npm). */\n pm: PackageManager;\n /** Command helpers for the detected PM. */\n pmCommands: PMCommands;\n /** Cloud project slug (its subdomain) to link the scaffold to. */\n cloudProject?: string;\n /** One-time setup key that authenticates the cloud link. */\n setupKey?: string;\n /** Control-plane URL the setup key is redeemed against. */\n cloudUrl?: string;\n /** AI coding agents to install skills and the MCP server for. */\n agents: AgentKey[];\n /** Whoever reads the closing steps can answer a prompt (a TTY, not --yes). */\n interactive?: boolean;\n}\n\nexport interface BuildQuestionsParams {\n nameArg?: string;\n templateArg?: TemplatePreset;\n headlessArg?: boolean;\n hasGitFlag: boolean;\n hasInstallFlag: boolean;\n pm: PackageManager;\n}\n\n/**\n * Builds the interactive prompt questions for `rebase init`.\n * Exported for testability — all prompt `type` values must match\n * types registered by the installed version of inquirer.\n */\n/**\n * The questions this command asks, as inquirer types them.\n *\n * Declared, rather than left as `Record<string, unknown>` and asserted into\n * `Parameters<typeof inquirer.prompt>[0]` at the call. Inquirer infers the\n * answer shape from the array it is handed, so an array of open records matches\n * none of its overloads — which is the refusal that assertion was there to get\n * past, at the cost of every question in this file being unchecked: a\n * misspelled `mesage`, a `choices` on a `confirm`, a `default` of the wrong\n * type for its question kind all compiled.\n */\nexport type InitQuestion =\n | { type: \"input\"; name: string; message: string; default: string; validate?: (input: string) => string | true }\n | { type: \"confirm\"; name: string; message: string; default: boolean; when?: (answers: Record<string, unknown>) => boolean }\n | { type: \"select\"; name: string; message: string; choices: ReadonlyArray<{ name: string; value: unknown; short: string }>; default: unknown; when?: (answers: Record<string, unknown>) => boolean };\n\n/**\n * Why `input` cannot be this project's `DATABASE_URL`, or null when it can.\n *\n * The runtime refuses anything that is not a URL, and only a Postgres one can\n * work, so `init` refuses the same — before the scaffold is written around it.\n * The value itself is never repeated back: it may hold a password.\n */\nexport function databaseUrlProblem(input: string): string | null {\n const expected = \"(expected postgresql://user:password@host:5432/database)\";\n let parsed: URL;\n try {\n parsed = new URL(input.trim());\n } catch {\n return `not a PostgreSQL connection string ${expected}`;\n }\n if (parsed.protocol !== \"postgresql:\" && parsed.protocol !== \"postgres:\") {\n return `not a PostgreSQL connection string: it starts with ${parsed.protocol}// ${expected}`;\n }\n return null;\n}\n\n/** One line saying `dir` already holds files, or null when it may be scaffolded into. */\nfunction scaffoldConflictLine(dir: string): string | null {\n const conflicts = scaffoldDirectoryConflicts(dir);\n if (conflicts.length === 0) return null;\n const shown = conflicts.slice(0, 4).join(\", \") + (conflicts.length > 4 ? `, and ${conflicts.length - 4} more` : \"\");\n return `\"${path.basename(dir)}\" already holds files a new project would overwrite or mix with (${shown}). Choose another name.`;\n}\n\nexport function buildInitQuestions(params: BuildQuestionsParams): InitQuestion[] {\n const { nameArg, templateArg, headlessArg, hasGitFlag, hasInstallFlag, pm } = params;\n const questions: InitQuestion[] = [];\n\n if (!nameArg) {\n questions.push({\n type: \"input\",\n name: \"projectName\",\n message: \"Project name:\",\n default: \"my-app\",\n // The directory is checked here, while the name can still be\n // changed, rather than after every other question is answered.\n validate: (input: string) => validateProjectName(input)\n ?? scaffoldConflictLine(path.resolve(process.cwd(), input))\n ?? true\n });\n }\n\n if (headlessArg === undefined) {\n questions.push({\n type: \"select\",\n name: \"headless\",\n message: \"What do you want to build?\",\n choices: HEADLESS_CHOICES,\n default: false\n });\n }\n\n if (!templateArg) {\n questions.push({\n type: \"select\",\n name: \"preset\",\n message: \"Choose a starter template:\",\n choices: PRESET_CHOICES,\n default: \"blog\",\n // A headless project has no collection files, so a preset is moot.\n when: (answers: Record<string, unknown>) => !(headlessArg ?? answers.headless)\n });\n }\n\n if (!hasGitFlag) {\n questions.push({\n type: \"confirm\",\n name: \"git\",\n message: \"Initialize a git repository?\",\n default: true\n });\n }\n\n if (!hasInstallFlag) {\n questions.push({\n type: \"confirm\",\n name: \"installDeps\",\n message: `Install dependencies with ${pm}?`,\n default: true\n });\n }\n\n questions.push({\n type: \"input\",\n name: \"databaseUrl\",\n message: \"PostgreSQL connection string (blank = a managed database for this project, no setup):\",\n default: \"\",\n validate: (input: string) => {\n if (!input.trim()) return true;\n if (/[\\r\\n]/.test(input)) {\n return \"Database URL cannot contain newline characters.\";\n }\n // `n` here was an answer to the yes/no question the reader thought\n // this was, and it became DATABASE_URL=n.\n const problem = databaseUrlProblem(input);\n return problem ? `That is ${problem}. Leave it blank for the managed database.` : true;\n }\n });\n\n questions.push({\n type: \"confirm\",\n name: \"introspect\",\n message: \"Would you like to introspect this database to automatically generate collections?\",\n default: true,\n when: (answers: Record<string, unknown>) => !!(answers.databaseUrl as string)?.trim()\n });\n\n return questions;\n}\n\n/**\n * The `cd` a user must type to enter the new project.\n *\n * Not the project's basename: `init apps/my-app` has to say `cd apps/my-app`,\n * and `init .` returns \"\" because they are already in the project.\n */\nexport function formatCdTarget(cwd: string, targetDirectory: string): string {\n return path.relative(cwd, targetDirectory);\n}\n\n/** Help for `rebase init` — the flags were previously only discoverable by\n * triggering the non-TTY error. */\nexport function printInitHelp(): void {\n console.log(`\n${chalk.bold(\"rebase init\")} — Create a new Rebase project\n\n${chalk.bold(\"Usage\")}\n rebase init ${chalk.blue(\"[name]\")} [options]\n\n ${chalk.gray(\"The name may be a nested path (apps/my-app) or \\\".\\\" for the current directory.\")}\n ${chalk.gray(\"Asks when omitted; defaults to \\\"my-app\\\", and takes it without asking under --yes.\")}\n\n${chalk.bold(\"Options\")}\n ${chalk.blue(\"-t, --template\")} ${chalk.gray(\"<preset>\")} blog | ecommerce | blank ${chalk.gray(\"(default: blog)\")}\n ${chalk.blue(\"--headless\")} Backend only — no admin panel, no collections\n ${chalk.blue(\"-y, --yes\")} Never prompt ${chalk.gray(\"(required for CI / non-TTY)\")}\n ${chalk.gray(\"Skips git init and dependency install — the interactive\")}\n ${chalk.gray(\"defaults say yes to both. Pass --git / --install for those.\")}\n ${chalk.blue(\"-i, --install\")} Install dependencies after scaffolding\n ${chalk.blue(\"--no-install\")} Scaffold only, install nothing ${chalk.gray(\"(the default)\")}\n ${chalk.blue(\"-g, --git\")} Initialize a git repository and make an initial commit\n ${chalk.blue(\"--database-url\")} ${chalk.gray(\"<url>\")} Use an existing database instead of the generated one\n ${chalk.blue(\"--introspect\")} Generate collections from that database ${chalk.gray(\"(implies --template blank; needs --install)\")}\n ${chalk.blue(\"--project\")} ${chalk.gray(\"<slug>\")} Link the scaffold to a Rebase Cloud project\n ${chalk.blue(\"--setup-key\")} ${chalk.gray(\"<key>\")} One-time key authenticating the cloud link ${chalk.gray(\"(use with --project)\")}\n ${chalk.blue(\"-a, --agent\")} ${chalk.gray(\"<name>\")} Set up an AI coding agent: Rebase skills + the MCP server.\n ${chalk.gray(`Repeatable or comma-separated: ${AGENT_KEYS.join(\" | \")} | all`)}\n ${chalk.gray(\"Asks when omitted, pre-ticking the agents installed on this\")}\n ${chalk.gray(\"machine; under --yes, none unless named.\")}\n\n${chalk.bold(\"What gets scaffolded\")}\n ${chalk.gray(\"default\")} Backend + an admin UI, driven by collections you define ${chalk.gray(\"(like Payload/Directus)\")}\n ${chalk.blue(\"--headless\")} Backend only, over your existing database ${chalk.gray(\"(like Supabase)\")}\n ${chalk.gray(\"--template has no effect: there are no collections to seed.\")}\n\n${chalk.bold(\"Examples\")}\n ${chalk.gray(\"$\")} rebase init my-shop --template ecommerce --install\n ${chalk.gray(\"$\")} rebase init my-api --headless --yes\n ${chalk.gray(\"$\")} rebase init . --yes --git\n ${chalk.gray(\"$\")} rebase init my-app --yes --agent claude,cursor\n`);\n}\n\nexport async function createRebaseApp(rawArgs: string[]) {\n if (wantsHelp(rawArgs)) {\n printInitHelp();\n return;\n }\n\n console.log(`\n${chalk.bold(\"Rebase\")} — Create a new project 🚀\n`);\n\n const pm = detectPackageManager();\n const options = await promptForOptions(rawArgs, pm);\n await createProject(options);\n}\n\n/** The flags `rebase init` takes. */\nexport const INIT_FLAGS = {\n \"--git\": Boolean,\n \"--install\": Boolean,\n // The default, spelled out. `arg` has no negation, so without this entry a\n // CI script that writes what reads naturally — `rebase init app --yes\n // --no-install` — died on \"Unknown or unexpected option\", and both the\n // README and the Quickstart documented a flag the parser rejected. When\n // both are passed, the explicit \"no\" wins.\n \"--no-install\": Boolean,\n \"--database-url\": String,\n \"--introspect\": Boolean,\n \"--template\": String,\n \"--headless\": Boolean,\n \"--project\": String,\n \"--setup-key\": String,\n \"--agent\": [String],\n \"--yes\": Boolean,\n \"-a\": \"--agent\",\n \"-g\": \"--git\",\n \"-i\": \"--install\",\n \"-t\": \"--template\",\n \"-y\": \"--yes\"\n} satisfies arg.Spec;\n\nasync function promptForOptions(rawArgs: string[], pm: PackageManager): Promise<InitOptions> {\n const { flags: args, positionals } = parseCommandArgs({\n spec: INIT_FLAGS,\n rawArgs,\n commandWords: 1,\n command: \"init\",\n maxPositionals: 1\n });\n\n // The first positional arg after \"init\" is the project name. Under the old\n // permissive parse a mistyped flag took that slot — `rebase init --headles\n // shop` scaffolded a directory called `--headles` — and the misspelling that\n // caused it was accepted in silence.\n const nameArg = positionals[0];\n const isNonInteractive = args[\"--yes\"] || false;\n\n // The interactive prompt validates typed names; a name passed as an\n // argument must pass the same check or it becomes an invalid package.json\n // \"name\" that only fails later, at install time. Validate the basename so\n // nested paths (\"apps/my-app\") and \".\" still work.\n if (nameArg) {\n const resolvedName = path.basename(path.resolve(process.cwd(), nameArg));\n const nameError = validateProjectName(resolvedName);\n if (nameError) {\n console.error(chalk.red(`Invalid project name \"${resolvedName}\": ${nameError}`));\n process.exit(1);\n }\n // Before any question: the answer cannot change, so asking first only\n // wastes every answer the reader gives.\n const targetDirectory = path.resolve(process.cwd(), nameArg);\n const conflicts = scaffoldDirectoryConflicts(targetDirectory);\n if (conflicts.length > 0) {\n for (const line of scaffoldConflictMessage(resolvedName, formatCdTarget(process.cwd(), targetDirectory), conflicts)) {\n console.error(line);\n }\n process.exit(1);\n }\n }\n\n const databaseUrlArg = args[\"--database-url\"]?.trim();\n if (databaseUrlArg) {\n const problem = databaseUrlProblem(databaseUrlArg);\n if (problem) {\n console.error(chalk.red(`✗ --database-url is ${problem}.`));\n console.error(chalk.gray(\" Leave the flag out to use a managed database for this project, with no setup.\"));\n process.exit(1);\n }\n }\n\n const templateArg = args[\"--template\"] as TemplatePreset | undefined;\n if (templateArg && !PRESET_CHOICES.some(p => p.value === templateArg)) {\n console.error(chalk.red(`Unknown template \"${templateArg}\". Available: ${PRESET_CHOICES.map(p => p.value).join(\", \")}`));\n process.exit(1);\n }\n\n const headlessArg = args[\"--headless\"] === true ? true : undefined;\n\n // Resolved before any question, so a misspelt agent costs nothing.\n const namedAgents = resolveAgentNames(args[\"--agent\"] ?? []);\n\n // `--no-install` is an explicit \"no\", not merely the absence of a \"yes\": it\n // suppresses the interactive question too, so `rebase init app --no-install`\n // asks one fewer thing rather than asking and ignoring the answer.\n const noInstall = args[\"--no-install\"] === true;\n const installFlag = noInstall ? false : (args[\"--install\"] ?? false);\n const hasInstallFlag = noInstall || args[\"--install\"] === true;\n\n if (isNonInteractive) {\n // Non-interactive: nothing to ask, so the prompt's default stands in.\n const projectName = nameArg || \"my-app\";\n const targetDirectory = path.resolve(process.cwd(), projectName);\n const templateDirectory = path.resolve(cliRoot!, \"templates\", \"template\");\n const pmCommands = getPMCommands(pm);\n\n return {\n projectName: path.basename(targetDirectory),\n git: args[\"--git\"] ?? false,\n installDeps: installFlag,\n targetDirectory,\n templateDirectory,\n databaseUrl: args[\"--database-url\"] || undefined,\n introspect: args[\"--introspect\"] || false,\n preset: templateArg || \"blog\",\n explicitPreset: !!templateArg,\n headless: headlessArg ?? false,\n pm,\n pmCommands,\n cloudProject: args[\"--project\"] || undefined,\n setupKey: args[\"--setup-key\"] || undefined,\n cloudUrl: resolveCloudUrl(rawArgs),\n // Nothing is guessed without a person to confirm it: the machine's\n // agents are only ever a pre-ticked default in the prompt.\n agents: namedAgents ?? [],\n interactive: false\n };\n }\n\n // A non-interactive stdin (CI, a pipe, no TTY) can't answer prompts:\n // inquirer either blocks forever waiting for input or aborts with a raw\n // ExitPromptError stack trace. Fail fast with actionable guidance instead.\n if (!process.stdin.isTTY) {\n console.error(chalk.red(\"Cannot prompt: this is a non-interactive terminal (no TTY).\"));\n console.error(chalk.yellow(\" Re-run with --yes to accept defaults, passing any choices as flags, e.g.:\"));\n console.error(chalk.yellow(` rebase init ${nameArg || \"my-app\"} --yes --template blog`));\n console.error(chalk.gray(\" Options: --template <blog|ecommerce|blank> --headless --database-url <url> --install --git --agent <name>\"));\n process.exit(1);\n }\n\n const questions = buildInitQuestions({\n nameArg,\n templateArg,\n headlessArg,\n hasGitFlag: !!args[\"--git\"],\n hasInstallFlag,\n pm\n });\n\n\n const answers = await inquirer.prompt(questions);\n const agents = namedAgents ?? await promptForAgents();\n\n const targetDirectory = path.resolve(process.cwd(), nameArg || answers.projectName);\n const projectName = path.basename(targetDirectory);\n const templateDirectory = path.resolve(cliRoot!, \"templates\", \"template\");\n const pmCommands = getPMCommands(pm);\n\n return {\n projectName,\n git: args[\"--git\"] || answers.git || false,\n installDeps: noInstall ? false : (args[\"--install\"] || answers.installDeps || false),\n targetDirectory,\n templateDirectory,\n databaseUrl: (answers.databaseUrl as string)?.trim() || undefined,\n introspect: answers.introspect || false,\n preset: templateArg || (answers.preset as TemplatePreset) || \"blog\",\n // Only a flag is \"explicit\" here: the interactive path never asks for a\n // preset once baas is chosen, so it can't produce a conflicting answer.\n explicitPreset: !!templateArg,\n headless: headlessArg ?? Boolean(answers.headless),\n pm,\n pmCommands,\n cloudProject: args[\"--project\"] || undefined,\n setupKey: args[\"--setup-key\"] || undefined,\n cloudUrl: resolveCloudUrl(rawArgs),\n agents,\n interactive: true\n };\n}\n\n/**\n * Redeem the one-time setup key from the console's setup page and write the\n * `.rebase/cloud.json` link into the scaffold, so `rebase cloud deploy` etc.\n * work in the new directory with no further flags. `--project` carries the\n * project's slug (its subdomain, as shown in console URLs); the control plane\n * also accepts a raw id for old copies of the command.\n *\n * Best-effort by design: a failed link must never fail the scaffold, so every\n * exit path other than success is a warning plus instructions to link later.\n */\nasync function linkScaffoldToCloud(options: InitOptions): Promise<void> {\n if (!options.cloudProject && !options.setupKey) return;\n\n const linkLater = `Link it later with ${chalk.bold(\"rebase cloud login\")} then ${chalk.bold(\"rebase cloud link\")}.`;\n if (!options.cloudProject || !options.setupKey) {\n console.warn(chalk.yellow(\" --project and --setup-key go together; skipping the cloud link.\"));\n console.warn(chalk.yellow(` ${linkLater}`));\n return;\n }\n\n try {\n const res = await fetch(`${options.cloudUrl}/api/functions/setup-key/validate`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ projectId: options.cloudProject,\nsetupKey: options.setupKey })\n });\n const body = (await res.json().catch(() => ({}))) as {\n error?: { message?: string };\n project?: { id?: string | number; subdomain?: string; name?: string };\n };\n if (!res.ok || body.project?.id === undefined) {\n console.warn(chalk.yellow(` Could not verify the setup key: ${body.error?.message || res.statusText}`));\n console.warn(chalk.yellow(` ${linkLater}`));\n return;\n }\n writeLink(\n {\n url: String(options.cloudUrl),\n projectId: String(body.project.id),\n slug: body.project.subdomain,\n projectName: body.project.name\n },\n options.targetDirectory\n );\n console.log(\"\");\n console.log(` ${chalk.green(\"✓\")} Linked to cloud project ${chalk.bold(body.project.subdomain ?? options.cloudProject)}`);\n } catch (e) {\n console.warn(chalk.yellow(` Could not reach the control plane: ${e instanceof Error ? e.message : String(e)}`));\n console.warn(chalk.yellow(` ${linkLater}`));\n }\n}\n\n/**\n * Make the initial commit, after everything that writes into the project has run.\n *\n * It used to happen immediately after `git init`, which is before dependency\n * installation and before introspection — so `init --git --install` ended on a\n * dirty tree whose only untracked file was `pnpm-lock.yaml`. A lockfile is\n * precisely the thing that should be in a project's first commit, and a brand\n * new scaffold whose first `git status` is dirty invites the reader to conclude\n * the lockfile is deliberately ignored and never commit it at all.\n *\n * Introspection has the same shape: it generates `config/collections` and\n * `schema.generated.ts`, which belong in the commit describing the scaffold that\n * produced them.\n *\n * `git init` stays where it was. Creating the repository early costs nothing and\n * means a failed install still leaves the user a repository to commit into.\n */\nasync function commitScaffold(targetDirectory: string): Promise<void> {\n try {\n // Leaving the tree uncommitted makes the very first `git diff`\n // useless and hides the scaffold in a wall of untracked files.\n // .gitignore is already in place, so .env is never committed.\n await execa(\"git\", [\"add\", \"-A\"], { cwd: targetDirectory });\n // A machine with no user.email configured cannot commit at all.\n // Supply an identity only in that case, so a configured user still\n // authors their own initial commit.\n let identity: Record<string, string> = {};\n try {\n await execa(\"git\", [\"config\", \"user.email\"], { cwd: targetDirectory });\n } catch {\n identity = {\n GIT_AUTHOR_NAME: \"Rebase\",\n GIT_AUTHOR_EMAIL: \"noreply@rebase.pro\",\n GIT_COMMITTER_NAME: \"Rebase\",\n GIT_COMMITTER_EMAIL: \"noreply@rebase.pro\"\n };\n }\n await execa(\"git\", [\"commit\", \"-m\", \"Initial commit from Rebase\"], {\n cwd: targetDirectory,\n env: identity\n });\n } catch {\n console.warn(chalk.yellow(\" Warning: Failed to create the initial commit\"));\n }\n}\n\n/** What the closing \"Next steps\" depend on: the project's shape, and what `init` managed to do. */\nexport interface InitNextStepsInput {\n headless: boolean;\n /** `--database-url` was given, so `.env` names the user's own database. */\n ownDatabase: boolean;\n /** Introspection was asked for. */\n introspect: boolean;\n /** Introspection ran and produced collections. */\n introspected: boolean;\n /** Dependencies were installed. */\n installed: boolean;\n /** What the reader types to enter the project; \"\" when they are in it. */\n cdTarget: string;\n pm: PMCommands;\n}\n\n/**\n * The \"Next steps\" `init` closes on, every command one that works as printed.\n *\n * Each flavour has its own steps, and the branch for one flavour must not run\n * for another. The `--database-url` branch was checked before the headless one,\n * so `init --headless --database-url` — the documented BaaS path — opened on\n * `pnpm run db:push`: a script the headless scaffold does not have, for a\n * schema it does not declare (its tables are the developer's own), with an\n * Atlas it does not install. `init-next-steps.test.ts` holds every script\n * named here to the scaffold it is printed for.\n */\nexport function initNextSteps(input: InitNextStepsInput): string[] {\n const { headless, ownDatabase, introspect, introspected, installed, cdTarget, pm } = input;\n const cmd = (parts: string[]): string => ` ${chalk.cyan(parts.join(\" \"))}`;\n const note = (text: string): string => chalk.gray(` # ${text}`);\n const runDev = cmd(pm.run(\"dev\"));\n const lines: string[] = [];\n\n if (cdTarget) lines.push(` ${chalk.cyan(\"cd\")} ${cdTarget}`);\n if (!installed) lines.push(cmd(pm.install));\n lines.push(\"\");\n\n if (introspected) {\n lines.push(note(\"Database has been introspected & collections generated!\"));\n lines.push(note(headless\n ? \"Start the API over it:\"\n : \"Start the development server (frontend + backend):\"));\n lines.push(runDev);\n } else if (introspect) {\n // Introspection was requested but did not run. Point at the steps that\n // finish the job rather than claiming collections exist.\n lines.push(note(\"Introspection did not run — finish it with:\"));\n lines.push(cmd(pm.exec(\"rebase\", [\"schema\", \"introspect\", \"--force\"])));\n lines.push(cmd(pm.exec(\"rebase\", [\"schema\", \"generate\"])));\n lines.push(\"\");\n lines.push(note(\"Then start the development server:\"));\n lines.push(runDev);\n } else if (headless) {\n // One step, then the thing that is actually this mode's job. `dev`\n // starts the database itself when none is named; a headless project has\n // no collections, so there is no schema to push and the tables are the\n // developer's to create — on their own database or the managed one.\n lines.push(note(ownDatabase\n ? \"Your database is configured in .env (DATABASE_URL).\"\n : \"A local database configuration has been generated in .env.\"));\n lines.push(note(ownDatabase\n ? \"1. Start the API over it:\"\n : \"1. Start everything — the database comes up with it:\"));\n lines.push(runDev);\n lines.push(\"\");\n lines.push(note(ownDatabase\n ? \"2. Serve your tables.\"\n : \"2. Create your tables (migrations, SQL, any tool you like).\"));\n lines.push(note(\" A table is served once row-level security is enabled on it, and a\"));\n lines.push(note(\" policy is what opens its rows:\"));\n lines.push(cmd([\"ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;\"]));\n lines.push(cmd([\"CREATE POLICY your_table_owner ON your_table FOR ALL USING (user_id = rebase.uid());\"]));\n lines.push(note(\" The API logs any table it skips, and why.\"));\n } else if (ownDatabase) {\n lines.push(note(\"Your custom database is configured in .env.\"));\n lines.push(note(\"If the database is empty, push the Rebase schema to initialize it:\"));\n lines.push(cmd(pm.run(\"db:push\")));\n lines.push(\"\");\n lines.push(note(\"Then start the development server:\"));\n lines.push(runDev);\n } else {\n // The whole first run, in one command.\n //\n // Deliberately does NOT say \"container\". This branch is the one a new\n // project takes, and it is precisely the branch with no container in it:\n // `.env` ships DATABASE_URL commented out, so `dev` starts the managed\n // PGlite database rather than Docker. Saying otherwise sent a reader who\n // had no Docker installed off to install it, to satisfy a step that was\n // never going to run — and made the whole quickstart look like it\n // required a daemon it does not.\n //\n // \"schema\" covers two things `dev` does before serving: generating the\n // Drizzle schema from the collections, and applying the collections to\n // the database. The push-and-Docker steps are documented under\n // `rebase dev --help`.\n lines.push(note(\"A local database configuration has been generated in .env.\"));\n lines.push(note(\"Start everything — the database and schema are set up for you,\"));\n lines.push(note(\"with no Docker and nothing else to install:\"));\n lines.push(runDev);\n lines.push(\"\");\n lines.push(note(\"To use a Postgres of your own instead, uncomment DATABASE_URL in .env.\"));\n }\n\n lines.push(\"\");\n // Both halves of the first-admin rule, once, here.\n //\n // `init` has just written REBASE_ADMIN_EMAIL and a generated password into\n // `.env`, and they belong to the *production* boot — the compose stack, where\n // the first-registration window is shut. `rebase dev` reads the same file, so\n // without this line the honest reading of that `.env` is \"these are my\n // credentials\", and the first documented step (register, become the admin)\n // reads as broken.\n lines.push(note(\"Sign in: the first account you register becomes the admin.\"));\n lines.push(note(\"In production (docker compose) that window is shut and the account named by\"));\n lines.push(note(\"REBASE_ADMIN_EMAIL in .env is created at boot instead.\"));\n\n lines.push(\"\");\n // `--headless --introspect` had these two claims fighting: the step above\n // announced \"collections generated!\" and this line then said there are none.\n // Both were reachable at once, and the reader has to believe one of them.\n lines.push(headless\n ? introspected\n ? chalk.gray(\"This starts a headless API (Hono + PostgreSQL) over the collections just \")\n + chalk.gray(\"generated from your database in config/collections. Edit them to change what the \")\n + chalk.gray(\"API exposes; docs are at /api/swagger.\")\n : chalk.gray(\"This starts a headless API (Hono + PostgreSQL). There are no collection files: \")\n + chalk.gray(\"the API is derived from your database schema. Once it serves a table, docs are at /api/swagger.\")\n : chalk.gray(\"This starts both the backend (Hono + PostgreSQL)\")\n + chalk.gray(\" and the frontend (Vite + React) concurrently.\"));\n return lines;\n}\n\n/**\n * The closing \"AI Agent Skills\" lines, each command one its reader can run.\n *\n * `rebase skills install` with no `--agent` prompts, and refuses without a\n * TTY — so printing it bare at the end of `rebase init --yes`, the agent and\n * CI path, told that reader to run a command that answers \"Cannot prompt\".\n * Named agents are spelled out (a refresh must not depend on detection, which\n * never finds Copilot); otherwise a TTY reader gets the prompt, anyone else\n * the `--agent` form.\n */\nexport function agentNextSteps(agents: readonly AgentKey[], interactive: boolean, pm: PMCommands): string[] {\n const both = (args: string[]): string =>\n ` ${chalk.cyan([\"rebase\", ...args].join(\" \"))} ${chalk.gray(\"or\")} ${chalk.cyan(pm.exec(\"rebase\", args).join(\" \"))}`;\n if (agents.length > 0) {\n return [\n chalk.gray(` Set up for ${agents.map(a => AGENTS[a].label).join(\", \")}. Commit the files to share them;`),\n chalk.gray(\" after a Rebase upgrade, refresh the skills with:\"),\n \"\",\n both([\"skills\", \"install\", \"--agent\", agents.join(\",\")])\n ];\n }\n if (interactive) {\n return [\n chalk.gray(\" Install Rebase agent skills, and the Rebase MCP server, for your AI coding assistant:\"),\n \"\",\n both([\"skills\", \"install\", \"--mcp\"])\n ];\n }\n return [\n chalk.gray(\" Install Rebase agent skills, and the Rebase MCP server, for your AI coding assistant —\"),\n chalk.gray(` name it: ${AGENT_KEYS.join(\", \")}, or all.`),\n \"\",\n both([\"skills\", \"install\", \"--agent\", \"<agent>\", \"--mcp\"])\n ];\n}\n\n/**\n * What a directory may already hold for `rebase init` to scaffold into it.\n *\n * `git clone` of an empty repository, or `git init`, leaves exactly `.git` —\n * and `rebase init . --yes --git` is the help's own example. Counting every\n * entry as \"not empty\" refused the one directory that example is most likely\n * to be typed in. The entries here are a repository's metadata, the files\n * operating systems drop into any folder, and a licence: none of them is\n * something the scaffold writes (`init.test.ts` holds the template to that),\n * so tolerating them can never overwrite anything. Everything else is a\n * conflict and is named, never merged into.\n */\nexport const SCAFFOLD_TOLERATED_ENTRIES: ReadonlySet<string> = new Set([\n \".git\", \".hg\", \".svn\", \".gitattributes\",\n \".DS_Store\", \"Thumbs.db\", \"desktop.ini\",\n \"LICENSE\", \"LICENSE.md\", \"LICENSE.txt\"\n]);\n\n/** Entries in `dir` the scaffold would overwrite or mix with — `[]` when it may proceed. */\nexport function scaffoldDirectoryConflicts(dir: string): string[] {\n if (!fs.existsSync(dir)) return [];\n return fs.readdirSync(dir, { withFileTypes: true })\n .filter(entry => !SCAFFOLD_TOLERATED_ENTRIES.has(entry.name))\n .map(entry => entry.isDirectory() ? `${entry.name}/` : entry.name)\n .sort();\n}\n\n/** The refusal for a directory that already holds files, with the two ways forward. */\nexport function scaffoldConflictMessage(projectName: string, displayPath: string, conflicts: string[]): string[] {\n const shown = conflicts.slice(0, 8).join(\", \") + (conflicts.length > 8 ? `, and ${conflicts.length - 8} more` : \"\");\n return [\n `${chalk.red.bold(\"ERROR\")} Directory \"${projectName}\" already holds files a new project would overwrite or mix with: ${shown}`,\n chalk.yellow(` Scaffold somewhere new — ${chalk.cyan(\"rebase init <new-directory>\")} — or move those out of ${displayPath || \"this directory\"} and run this again.`),\n chalk.gray(` A repository's own metadata (.git) and a LICENSE are fine to leave in place.`)\n ];\n}\n\n/**\n * `git init`, or nothing when the directory is already a repository.\n *\n * A cloned repository keeps its branch, its remote and its history: the\n * scaffold is committed on top of what is there. Only a repository this\n * function created is pointed at `main`.\n */\nexport async function initGitRepository(targetDirectory: string): Promise<boolean> {\n if (fs.existsSync(path.join(targetDirectory, \".git\"))) {\n console.log(chalk.gray(\" Using the existing git repository...\"));\n return true;\n }\n console.log(chalk.gray(\" Initializing git repository...\"));\n try {\n await execa(\"git\", [\"init\"], { cwd: targetDirectory });\n // Name the branch `main` rather than inheriting whatever\n // `init.defaultBranch` is (often still `master`). `git init -b` would\n // be the obvious way, but it needs git >= 2.28; rewriting HEAD works\n // on every version and is safe before the first commit.\n try {\n await execa(\"git\", [\"symbolic-ref\", \"HEAD\", \"refs/heads/main\"], { cwd: targetDirectory });\n } catch {\n // Leave the default branch name; not worth failing the scaffold.\n }\n return true;\n } catch {\n console.warn(chalk.yellow(\" Warning: Failed to initialize git repository\"));\n return false;\n }\n}\n\nasync function createProject(options: InitOptions) {\n const startedAt = Date.now();\n const conflicts = scaffoldDirectoryConflicts(options.targetDirectory);\n if (conflicts.length > 0) {\n for (const line of scaffoldConflictMessage(options.projectName, formatCdTarget(process.cwd(), options.targetDirectory), conflicts)) {\n console.error(line);\n }\n process.exit(1);\n }\n fs.mkdirSync(options.targetDirectory, { recursive: true });\n\n // Verify template exists\n try {\n await access(options.templateDirectory, fs.constants.R_OK);\n } catch {\n console.error(`${chalk.red.bold(\"ERROR\")} Template not found at ${options.templateDirectory}`);\n process.exit(1);\n }\n\n // Copy template files\n console.log(chalk.gray(\" Copying project files...\"));\n try {\n await cp(options.templateDirectory, options.targetDirectory, {\n recursive: true,\n filter: (source: string) => {\n const basename = path.basename(source);\n // Skip node_modules and .DS_Store\n return basename !== \"node_modules\" && basename !== \".DS_Store\";\n }\n });\n } catch (err: unknown) {\n console.error(`${chalk.red.bold(\"ERROR\")} Failed to copy template files: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n\n // npm/pnpm always strip files named .gitignore and .npmrc from published\n // tarballs, so the template ships them un-dotted and we restore the real\n // names here.\n for (const [from, to] of [[\"gitignore\", \".gitignore\"], [\"npmrc\", \".npmrc\"]] as const) {\n const shipped = path.join(options.targetDirectory, from);\n if (fs.existsSync(shipped)) {\n fs.renameSync(shipped, path.join(options.targetDirectory, to));\n }\n }\n\n // Apply the selected template preset (swap collection files)\n if (options.headless && options.explicitPreset) {\n // baas has no collections, so there is nothing for a preset to swap.\n // Say so rather than accepting the flag and silently dropping it.\n console.log(chalk.yellow(` Ignoring --template ${options.preset}: a headless project declares no collections.`));\n }\n if (!options.headless) {\n // When introspecting, the database is the source of truth: start from\n // the blank preset so example collections never register on top of\n // tables the database doesn't have.\n if (options.introspect && options.preset !== \"blank\") {\n console.log(chalk.gray(\" Using the blank template: collections will come from your database.\"));\n }\n const applied = await applyPreset(options.targetDirectory, options.introspect ? \"blank\" : options.preset);\n writeShippedSchema(options.targetDirectory, applied);\n }\n\n // Reduce the project to the selected shape\n await applyHeadless(options.targetDirectory, options.headless);\n\n // Replace placeholder project name in package.json files\n await replacePlaceholders(options);\n\n // Rename .env.example to .env if it exists and randomize secrets\n await configureEnvFile(options.targetDirectory, options.databaseUrl);\n\n // The manifest's build command is the project's package manager, not npm.\n // The template has to spell one of them, and `npm run build --workspace\n // frontend` in a pnpm project is a second package manager reading a\n // lockfile it did not write.\n await writeProjectPackageManagerIntoManifest(options.targetDirectory, options.pmCommands);\n // The scaffold's `.mcp.json` runs the project's own `@rebasepro/mcp`\n // through the package manager, and it ships spelled for pnpm.\n retargetScaffoldMcpConfig(options.targetDirectory, options.pm);\n\n // Before git, so the skills and MCP configs are in the initial commit.\n if (options.agents.length > 0) {\n console.log(chalk.gray(\" Setting up AI coding agents...\"));\n printAgentSetup(configureAgents(options.agents, options.targetDirectory, undefined, options.pm), options.pm);\n }\n\n // Create the repository now, but commit at the very end — see\n // commitScaffold below for why the two halves are separated.\n const gitInitialized = options.git ? await initGitRepository(options.targetDirectory) : false;\n\n const { pm, pmCommands } = options;\n const installCmd = pmCommands.install;\n const execCmd = pmCommands.exec(\"rebase\", [\"schema\", \"introspect\", \"--force\"]);\n // No --collections: config/collections is the default, and a path written\n // here is resolved from where the reader runs it — the project root.\n const generateCmd = pmCommands.exec(\"rebase\", [\"schema\", \"generate\"]);\n\n // Whether the install succeeded, so a failed one is printed as a step still to take.\n let installed = false;\n if (options.installDeps) {\n console.log(\"\");\n console.log(chalk.gray(` Installing dependencies with ${pm}...`));\n console.log(\"\");\n try {\n await execa(installCmd[0], installCmd.slice(1), {\n cwd: options.targetDirectory,\n stdio: \"inherit\"\n });\n installed = true;\n } catch {\n console.warn(chalk.yellow(` Warning: Failed to install dependencies. You may need to run \\`${installCmd.join(\" \")}\\` manually.`));\n }\n }\n\n // Whether introspection actually ran and produced collections. The next\n // steps below report what really happened, so a skipped or failed\n // introspection is never announced as a success.\n let introspected = false;\n\n if (options.introspect) {\n console.log(\"\");\n if (options.installDeps) {\n console.log(chalk.gray(\" Introspecting database and generating collections...\"));\n console.log(\"\");\n try {\n // --force overwrites template example collections with real ones\n await execa(execCmd[0], execCmd.slice(1), {\n cwd: options.targetDirectory,\n stdio: \"inherit\"\n });\n // The scaffold holds the blank preset's schema.generated.ts;\n // regenerate it from the introspected collections or the\n // backend serves a schema that doesn't match the database.\n await execa(generateCmd[0], generateCmd.slice(1), {\n cwd: options.targetDirectory,\n stdio: \"inherit\"\n });\n console.log(chalk.green(\" Database successfully introspected!\"));\n introspected = true;\n } catch {\n console.warn(chalk.yellow(\" Warning: Failed to introspect database automatically.\"));\n console.warn(chalk.yellow(` You can run \\`${execCmd.join(\" \")}\\` then \\`${generateCmd.join(\" \")}\\` manually after setup.`));\n }\n } else {\n console.warn(chalk.yellow(\" Skipping introspection because dependencies were not installed.\"));\n console.warn(chalk.yellow(` Run \\`${installCmd.join(\" \")}\\` then \\`${execCmd.join(\" \")}\\` manually.`));\n }\n }\n\n if (gitInitialized) await commitScaffold(options.targetDirectory);\n\n await linkScaffoldToCloud(options);\n\n // Success message\n console.log(\"\");\n console.log(`${chalk.green.bold(\"✓\")} Project ${chalk.bold(options.projectName)} created successfully!`);\n console.log(\"\");\n console.log(chalk.bold(\"Next steps:\"));\n console.log(\"\");\n const nextSteps = initNextSteps({\n headless: options.headless,\n ownDatabase: Boolean(options.databaseUrl),\n introspect: Boolean(options.introspect),\n introspected,\n installed,\n // The path the user has to type, not the project's basename: `init\n // apps/my-app` must say `cd apps/my-app`, and `init .` needs no cd at all\n // because they are already standing in the project.\n cdTarget: formatCdTarget(process.cwd(), options.targetDirectory),\n pm: pmCommands\n });\n for (const line of nextSteps) console.log(line);\n console.log(\"\");\n console.log(chalk.gray(\"Docs: https://rebase.pro/docs\"));\n console.log(chalk.gray(\"GitHub: https://github.com/rebasepro/rebase\"));\n console.log(\"\");\n console.log(chalk.bold(\"🤖 AI Agent Skills\"));\n console.log(\"\");\n for (const line of agentNextSteps(options.agents, options.interactive === true, pmCommands)) console.log(line);\n console.log(\"\");\n\n // Asked here, at the very end, and never before: the project exists, it\n // worked, and the user has something to judge us on. Nothing has been\n // written or transmitted up to this line — declining leaves no id and no\n // file. See telemetry/consent.ts for why the order matters.\n //\n // `--yes` and non-TTY runs never reach the prompt, so CI behaviour is\n // unchanged.\n const initProperties = {\n preset: options.headless ? \"none\" : options.preset,\n headless: Boolean(options.headless),\n package_manager: options.pm,\n installed_deps: Boolean(options.installDeps),\n introspected,\n own_database: Boolean(options.databaseUrl),\n cloud_linked: Boolean(options.cloudProject),\n git: Boolean(options.git),\n duration: durationBucket(Date.now() - startedAt)\n };\n // `reAskDeclined`: scaffolding is the one moment where asking again is an\n // offer rather than nagging. See PromptOptions.\n if (await promptForConsent({ reAskDeclined: true })) {\n await recordEvent(\"cli.init\", initProperties, { projectRoot: options.targetDirectory });\n }\n}\n\n/**\n * Apply a template preset by replacing the default collection files.\n *\n * The template ships with blog collections at the top level and\n * preset alternatives under `config/collections/presets/<name>/`.\n * This function swaps the active collection files and removes the\n * presets directory so the final project is clean.\n */\n/**\n * Reduce the scaffolded project to the chosen shape.\n *\n * The base template is the full triad. `--headless` drops the frontend and the\n * declared collections — there is nothing to define, since the server derives\n * its API from the database — and overlays the files that differ.\n *\n * The config *package* stays, holding only `storageAuthorize`. Storage is not\n * under row-level security, so a deployment with file storage enabled and no\n * access model serves every user's files to every signed-in user; the server\n * refuses to boot in that state. Deleting the package outright would leave a\n * headless project with nowhere to put the hook, and the scaffold's own\n * docker-compose.yml enables storage — so the first `docker compose up` would\n * crash-loop.\n */\nasync function applyHeadless(targetDirectory: string, headless: boolean): Promise<void> {\n if (!headless) return;\n\n fs.rmSync(path.join(targetDirectory, \"frontend\"), { recursive: true,\nforce: true });\n // Collections only. `rebase build` reads the absence of this directory as\n // \"introspect from the database\", and the overlay replaces config/index.ts\n // with one that exports the storage hook alone.\n fs.rmSync(path.join(targetDirectory, \"config\", \"collections\"), { recursive: true,\nforce: true });\n for (const stray of [\"cms.d.ts\", \"frontend-assets.d.ts\"]) {\n fs.rmSync(path.join(targetDirectory, \"config\", stray), { force: true });\n }\n // Generated from collection files; a headless project reads the live schema.\n fs.rmSync(path.join(targetDirectory, \"backend\", \"src\", \"schema.generated.ts\"), { force: true });\n\n const overlayDir = path.resolve(cliRoot!, \"templates\", \"overlays\", \"baas\");\n if (!fs.existsSync(overlayDir)) {\n console.error(`${chalk.red.bold(\"ERROR\")} BaaS template overlay not found at ${overlayDir}`);\n process.exit(1);\n }\n\n await cp(overlayDir, targetDirectory, {\n recursive: true,\n force: true,\n filter: (source: string) => {\n const basename = path.basename(source);\n return basename !== \"node_modules\" && basename !== \".DS_Store\";\n }\n });\n}\n\n/**\n * Rewrite `rebase.json`'s static-app build command for this project's package manager.\n *\n * The template must spell one of them, and it spells npm. In a pnpm project\n * that is a second package manager invoked against a lockfile it did not\n * write — `rebase build` then either installs a second tree or fails on a\n * workspace flag npm and pnpm spell differently.\n */\nasync function writeProjectPackageManagerIntoManifest(\n targetDirectory: string,\n pmCommands: PMCommands\n): Promise<void> {\n const manifestPath = path.join(targetDirectory, \"rebase.json\");\n if (!fs.existsSync(manifestPath)) return;\n\n try {\n const manifest = JSON.parse(fs.readFileSync(manifestPath, \"utf8\")) as {\n apps?: Record<string, { type?: string; root?: string; build?: string }>;\n };\n let changed = false;\n for (const app of Object.values(manifest.apps ?? {})) {\n if (app.type !== \"static\" || !app.root || !app.build) continue;\n const rewritten = pmCommands.runWorkspace(app.root, \"build\").join(\" \");\n if (rewritten !== app.build) {\n app.build = rewritten;\n changed = true;\n }\n }\n if (changed) {\n fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 4)}\\n`, \"utf8\");\n }\n } catch {\n // A manifest that will not parse is `rebase build`'s problem to report,\n // and scaffolding must not fail on a cosmetic rewrite.\n }\n}\n\n/** Swap in the preset's collection files. Returns the preset actually applied. */\nasync function applyPreset(targetDirectory: string, preset: TemplatePreset): Promise<TemplatePreset> {\n const collectionsDir = path.join(targetDirectory, \"config\", \"collections\");\n const presetsDir = path.join(collectionsDir, \"presets\");\n\n if (preset !== \"blog\") {\n const presetDir = path.join(presetsDir, preset);\n if (!fs.existsSync(presetDir)) {\n console.warn(chalk.yellow(` Warning: Preset \"${preset}\" not found, falling back to blog template.`));\n cleanupPresets(presetsDir);\n return \"blog\";\n }\n\n // Remove the default blog collection files (keep users.ts — it's shared)\n const blogFiles = [\"posts.ts\", \"authors.ts\", \"tags.ts\", \"index.ts\"];\n for (const file of blogFiles) {\n const filePath = path.join(collectionsDir, file);\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n }\n\n // Copy preset files into the collections directory\n const presetFiles = fs.readdirSync(presetDir).filter(f => f.endsWith(\".ts\"));\n for (const file of presetFiles) {\n fs.copyFileSync(\n path.join(presetDir, file),\n path.join(collectionsDir, file)\n );\n }\n }\n\n // Always clean up the presets directory — it shouldn't ship with the final project\n cleanupPresets(presetsDir);\n return preset;\n}\n\n/**\n * Where the generated Drizzle schema for each preset ships, beside the template.\n *\n * `rebase dev` regenerates `backend/src/schema.generated.ts` on every start, and\n * the Studio's schema editor refuses to commit over a dirty copy of it — a\n * schema change must not sweep up somebody's work in progress. So whatever\n * `init` writes there, and commits under `--git`, has to be byte-for-byte what\n * that first regeneration produces. A stub (`export const tables = {}`) was\n * rewritten on the first `rebase dev`, and every new project's first Studio\n * edit was refused with `SCHEMA_EDIT_DIRTY_TREE` before its owner had changed\n * a thing.\n *\n * The file cannot be generated here: generation loads the collection files,\n * and they import `@rebasepro/cms-types`, which the project does not have\n * until it is installed — `init --git` without `--install` commits first. So\n * each preset's output is generated in this repository and shipped, and\n * `init-generated-schema.test.ts` fails the moment one of them differs from\n * what the generator writes for that preset's collections.\n *\n * Outside `templates/template` on purpose: a preset's schema must not be\n * copied into a project that chose another preset.\n */\nexport function shippedSchemaPath(preset: TemplatePreset): string {\n return path.resolve(cliRoot!, \"templates\", \"generated-schemas\", `${preset}.ts`);\n}\n\n/** Write the preset's generated schema to `backend/src/schema.generated.ts`. */\nfunction writeShippedSchema(targetDirectory: string, preset: TemplatePreset): void {\n const destination = path.join(targetDirectory, \"backend\", \"src\", \"schema.generated.ts\");\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.copyFileSync(shippedSchemaPath(preset), destination);\n}\n\nfunction cleanupPresets(presetsDir: string): void {\n if (fs.existsSync(presetsDir)) {\n fs.rmSync(presetsDir, { recursive: true,\nforce: true });\n }\n}\n\n/**\n * The one registry call `init` makes, and what it is for.\n *\n * Every `@rebasepro/*` package in this repository carries the same version —\n * `check:publishable-set` fails the build on the first PR after a bump if any\n * of them drifts — so the version to pin is known before the network is\n * touched: it is this CLI's own. Asking npm eleven times, once per package,\n * bought nothing but eleven chances to hang. On a slow connection that was the\n * slowest part of `init`; on no connection it was eleven timeouts before a\n * fallback to `\"latest\"`, which is the one answer that produces a project\n * mixing framework eras.\n *\n * One call remains, and it asks a different question. Lockstep is enforced in\n * the repository, not on the registry: a release can still ship the CLI and\n * leave a package behind, which is exactly what happened to\n * `@rebasepro/agent-skills` across three releases. So this probes a single\n * package — `@rebasepro/server`, the one a project cannot run without — to see\n * whether this version really made it out. A gap is a refusal, because the\n * alternative is scaffolding a project that cannot install.\n *\n * Unreachable is NOT a refusal. `init` offline is a legitimate thing to do,\n * and the pin it would write is the same pin the probe would have confirmed.\n * It says so and carries on.\n */\ntype ReleaseProbe =\n | { kind: \"published\" }\n | { kind: \"gap\"; found: string }\n | { kind: \"unreachable\"; reason: string };\n\n/** The package the probe asks about. Not the CLI: the CLI is what is running. */\nconst RELEASE_PROBE_PACKAGE = \"@rebasepro/server\";\n\nasync function probeRelease(version: string): Promise<ReleaseProbe> {\n try {\n const { stdout } = await execa(\"npm\", [\"view\", `${RELEASE_PROBE_PACKAGE}@${version}`, \"version\"]);\n if (stdout.trim() === version) return { kind: \"published\" };\n // npm answers an unpublished version with empty output rather than an\n // error on some registries. Empty is a gap, not a success.\n return { kind: \"gap\", found: stdout.trim() || \"nothing\" };\n } catch (error) {\n const text = `${(error as { stderr?: string }).stderr ?? \"\"}${(error as Error).message ?? \"\"}`;\n if (/E404|404 Not Found|No match(ing)? version/i.test(text)) {\n return { kind: \"gap\", found: \"nothing\" };\n }\n return { kind: \"unreachable\", reason: firstLine(text) || \"the registry could not be reached\" };\n }\n}\n\nfunction firstLine(text: string): string {\n return text.split(\"\\n\").map(l => l.trim()).filter(Boolean)[0] ?? \"\";\n}\n\nasync function replacePlaceholders(options: InitOptions) {\n const filesToProcess = TEMPLATE_PLACEHOLDER_FILES;\n\n // `unknown` only when the manifest could not be read at all, which is the\n // same \"nothing to pin, nothing to confirm\" case `latest` used to stand for.\n const version = cliVersion();\n\n const fileContents = new Map<string, string>();\n const allPackages = new Set<string>();\n\n for (const file of filesToProcess) {\n const fullPath = path.resolve(options.targetDirectory, file);\n if (!fs.existsSync(fullPath)) continue;\n const content = fs.readFileSync(fullPath, \"utf-8\");\n fileContents.set(fullPath, content);\n\n const matches = [...content.matchAll(/\"(@rebasepro\\/[^\"]+)\":\\s*\"workspace:\\*\"/g)];\n for (const match of matches) allPackages.add(match[1]);\n }\n\n // `latest` means this CLI could not read its own manifest — there is no\n // version to confirm, and nothing to gain from asking.\n const skipProbe = parseEnvBoolean(process.env.REBASE_E2E) === true || version === \"unknown\";\n const probe: ReleaseProbe = skipProbe ? { kind: \"published\" } : await probeRelease(version);\n\n if (probe.kind === \"gap\") {\n throw new Error(\n `Rebase ${version} is not fully published to npm.\\n\\n` +\n `${RELEASE_PROBE_PACKAGE} has no ${version} release — the registry has ${probe.found}.\\n` +\n `Every @rebasepro package ships at one version, so scaffolding would pin ${allPackages.size}\\n` +\n `dependencies at a version that is not there, and the install would fail.\\n\\n` +\n \"That is a release gap in Rebase itself — not a problem with your machine,\\n\" +\n \"your network, or your package manager.\\n\\n\" +\n \"Stopped before writing dependency versions or installing anything. The\\n\" +\n `project directory ${path.basename(options.targetDirectory)}/ was created and is safe to delete.\\n` +\n \"Please report this.\"\n );\n }\n\n if (probe.kind === \"published\") {\n console.log(chalk.gray(` Pinning ${allPackages.size} @rebasepro package(s) to ${version}...`));\n }\n\n if (probe.kind === \"unreachable\") {\n console.log(chalk.gray(` Pinning @rebasepro packages to ${version} (this CLI's version).`));\n console.log(chalk.yellow(` Could not reach npm to confirm the release: ${probe.reason}`));\n console.log(chalk.gray(\" The pin is right either way — install will say so if the version is missing.\"));\n }\n\n for (const [fullPath, originalContent] of fileContents.entries()) {\n let content = originalContent.replace(/\\{\\{PROJECT_NAME\\}\\}/g, options.projectName);\n for (const pkgName of allPackages) {\n content = content.replace(\n new RegExp(`\"${pkgName}\":\\\\s*\"workspace:\\\\*\"`, \"g\"),\n `\"${pkgName}\": \"${version}\"`\n );\n }\n fs.writeFileSync(fullPath, content, \"utf-8\");\n }\n}\n\n\n/** `undefined` binds the wildcard address, which is a different question — see isPortAvailable. */\nfunction canBind(port: number, host?: string): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once(\"error\", (err: NodeJS.ErrnoException) => {\n // The host has no such address family at all — a v4-only machine\n // asked about `::1`. Nothing can be listening on an address that\n // cannot exist, so this is free rather than taken.\n resolve(err.code === \"EAFNOSUPPORT\" || err.code === \"EADDRNOTAVAIL\");\n });\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n if (host === undefined) server.listen(port);\n else server.listen(port, host);\n });\n}\n\n/**\n * Whether `port` is free — on the wildcard address *and* on both loopback addresses.\n *\n * All three, because on macOS/BSD a successful bind does not mean the port is\n * unused. Sockets carry `SO_REUSEADDR` (Node sets it), under which a wildcard\n * bind and a specific-address bind on the same port do not conflict — in either\n * direction. So each probe alone has a blind spot, and they are different ones:\n *\n * - **Wildcard only** (what this used to do) misses a server bound to\n * `127.0.0.1` and `[::1]` — a Homebrew or Postgres.app install, i.e. most\n * developer machines. 5432 was reported free while it was already serving\n * another project's database. Docker then published `*:5432` for the same\n * reason and the container started cleanly, with no \"port already allocated\"\n * error anywhere to hint at the collision. `DATABASE_URL` pointed at\n * `localhost:5432`, `localhost` resolves to `::1` first, and every command\n * reported success while reading and writing the *pre-existing* database — a\n * `db push` would have created tables, roles and RLS policies inside it.\n *\n * - **Loopback only** misses the opposite case: Docker Desktop publishes a\n * container's port on `*`, and a specific-address bind succeeds right past it.\n * That port is free to probe and unusable to publish, so `docker compose up -d\n * db` fails on \"Bind for 0.0.0.0:PORT failed: port is already allocated\" —\n * loudly, but only after the project has been generated around the bad port.\n *\n * Requiring all three costs three sockets and leaves neither gap. The wildcard\n * bind is the one the container itself has to make; the loopback binds are the\n * addresses `DATABASE_URL` will actually name.\n */\nexport async function isPortAvailable(port: number): Promise<boolean> {\n return (await canBind(port)) && (await canBind(port, \"127.0.0.1\")) && (await canBind(port, \"::1\"));\n}\n\nasync function findAvailablePort(startPort: number): Promise<number> {\n let port = startPort;\n while (!(await isPortAvailable(port))) {\n port++;\n }\n return port;\n}\n\n/**\n * The CLI's own version, which is the runtime image tag a scaffolded project\n * pins. They move together: the CLI, the packages and the runtime image are cut\n * from one release, so the version that installed the project is the version\n * whose runtime can boot its bundle.\n *\n * Falls back to `latest` only when the CLI cannot read its own manifest — a\n * floating tag is worse than a pinned one, but better than a compose file that\n * names a version that was never published.\n */\nfunction readCliVersion(): string {\n const version = cliVersion();\n return version === \"unknown\" ? \"latest\" : version;\n}\n\n/**\n * The runtime image tag to pin, given the version of the CLI doing the scaffolding.\n *\n * Only a stable release publishes `rebasepro/server` — a multi-arch build on\n * every push to main would cost minutes per commit for an image nobody pulls.\n * So pinning a prerelease CLI's own version writes a tag that cannot exist, and\n * `docker compose up` fails on `manifest unknown`, which is the same dead end\n * as the missing-repository bug this pinning was added to prevent.\n *\n * A prerelease therefore falls back to `latest`, which is correct rather than\n * merely available: a bundle's manifest declares the runtime range it needs\n * (`^1`), the image supplies only `@rebasepro/server`, and the framework a\n * bundle runs is installed from its own `deps.declared` at boot. The current\n * stable runtime boots a canary bundle by design.\n *\n * A floating tag is a real cost — it is what pinning exists to avoid — so say\n * so in the file rather than leaving a reader to discover it.\n */\nexport function resolveRuntimeImageTag(cliVersion: string): { tag: string; note?: string } {\n // Semver prerelease: everything after the first `-`. `0.13.1-canary.gcd6689e`.\n if (/^\\d+\\.\\d+\\.\\d+-/.test(cliVersion)) {\n return {\n tag: \"latest\",\n note: `# Scaffolded by a prerelease CLI (${cliVersion}), which publishes no runtime image,\\n` +\n \"# so this floats to the newest stable runtime. Pin an exact version once you\\n\" +\n \"# deploy: a moving tag changes what you are running with no version changing.\"\n };\n }\n return { tag: cliVersion };\n}\n\n/**\n * Set `KEY=value` in a .env body, whether the key ships set, commented out or\n * missing entirely.\n *\n * The missing case is not hypothetical: `configureEnvFile` runs against\n * whatever `.env.example` is in the target directory, which for a project\n * scaffolded from an older template — or from one somebody edited — may not\n * carry a key this version of `init` is expected to write. Silently skipping it\n * produces a `.env` that satisfies no `${VAR:?…}` in the compose file, which\n * surfaces as a stack that refuses to interpolate rather than as anything\n * pointing back here.\n */\nfunction setEnvValue(content: string, key: string, value: string, header?: string): string {\n const line = new RegExp(`^#?\\\\s*${key}=.*$`, \"m\");\n if (line.test(content)) return content.replace(line, `${key}=${value}`);\n return `${content.trimEnd()}\\n\\n${header ? `${header}\\n` : \"\"}${key}=${value}\\n`;\n}\n\nexport async function configureEnvFile(targetDirectory: string, databaseUrl?: string) {\n const envExamplePath = path.join(targetDirectory, \".env.example\");\n const envPath = path.join(targetDirectory, \".env\");\n if (fs.existsSync(envExamplePath) && !fs.existsSync(envPath)) {\n // Copy .env.example → .env (keep .env.example as a reference in the repo)\n fs.copyFileSync(envExamplePath, envPath);\n // Owner-only from the first byte. `copyFileSync` copies the *source's*\n // permissions and the packaged `.env.example` is 0644, so the file that\n // is about to receive a generated JWT_SECRET, the database password and\n // REBASE_SERVICE_KEY was world-readable for the whole of `init` — on a\n // shared build box or a multi-user machine, any local account could read\n // another project's service key, which the API treats as a full admin\n // credential. `.rebase/state.json` (dev-port.ts) and `telemetry.json`\n // are both 0600 for the same reason; this file holds strictly more.\n fs.chmodSync(envPath, 0o600);\n\n // Generate secure random strings\n const jwtSecret = crypto.randomBytes(32).toString(\"hex\");\n const dbPassword = crypto.randomBytes(16).toString(\"hex\");\n const serviceKey = crypto.randomBytes(48).toString(\"base64\");\n // base64url rather than base64 or hex: 24 characters, comfortably past\n // the runtime's 12-character floor, and every character it can produce\n // is one dotenv and Compose interpolation read back unchanged. `+`, `/`\n // and `=` are fine in a .env value but not obviously so to a reader\n // about to paste one into a shell, and `#` — which hex cannot produce\n // but a passphrase generator might — would truncate the line.\n const adminPassword = crypto.randomBytes(18).toString(\"base64url\");\n\n let envContent = fs.readFileSync(envPath, \"utf-8\");\n\n // The banner is written for the file being read as a template. This\n // copy *is* the filled-in one — it already carries a generated\n // JWT_SECRET, service key and database password — and telling its\n // reader to \"copy this file to .env and fill in the values\" invites\n // exactly the overwrite the README warns against two paragraphs later.\n envContent = envContent.replace(\n /^(# ║ {2})(Copy this file to \\.env and fill in the values)( +║)$/m,\n (_match, open: string, old: string, close: string) => {\n const replacement = \"Generated by `rebase init` — the secrets below are already set\";\n // Keep the box drawn: pad or clip to the width the line had.\n const width = old.length + close.length - 1;\n return open + replacement.slice(0, width).padEnd(width, \" \") + \"║\";\n }\n );\n\n envContent = envContent.replace(\n /^JWT_SECRET=.*$/m,\n `JWT_SECRET=${jwtSecret}`\n );\n\n // Ships commented out in .env.example. Left unset, the server generates\n // one on every boot and silently invalidates the previous run's tokens,\n // so write a stable one now rather than making each restart a logout.\n envContent = envContent.replace(\n /^#\\s*REBASE_SERVICE_KEY=.*$/m,\n `REBASE_SERVICE_KEY=${serviceKey}`\n );\n\n // Read back rather than hardcoded, so this tracks whatever PORT the\n // generated .env ends up carrying. `docker-compose.yml` publishes the\n // api as `${PORT:-3001}:3001`.\n const composeApiPort = /^PORT=(\\d+)/m.exec(envContent)?.[1] ?? \"3001\";\n\n // Also ships commented out, and left that way the very first command\n // this project tells you to run does not work.\n //\n // `docker-compose.yml` declares `CORS_ORIGINS: ${CORS_ORIGINS:?…}` on\n // the `api` service — deliberately required, because an API that\n // guesses its allowed origins eventually allows the wrong one. But\n // Compose interpolates the WHOLE file before selecting services, so\n // `docker compose up -d db` — step 1 of the \"Next steps\" printed at the\n // end of `rebase init` — failed on a variable the `db` service does not\n // use. So did `docker compose config`: the file could not be read at all.\n //\n // The guard is right; a generated project should satisfy it. The compose\n // stack serves the bundled admin from the `api` container on ${PORT},\n // so that is the origin a browser loads it from. A deployment still has\n // to set its own, and gets a visible CORS failure rather than a silent\n // one if it forgets.\n envContent = envContent.replace(\n /^#\\s*CORS_ORIGINS=.*$/m,\n `CORS_ORIGINS=http://localhost:${composeApiPort}`\n );\n\n // The first admin, named rather than raced for.\n //\n // `docker-compose.yml` runs the api service with NODE_ENV=production,\n // and in production the first-registration-becomes-admin window is\n // shut — deliberately, because the compose stack is serving before its\n // operator has typed anything and whoever found the sign-up form first\n // would own it. A closed window needs a way in that is not a race, and\n // this is it: the account is named in the same file that already holds\n // the JWT secret and the database password.\n //\n // Written by `init` rather than left for the reader, because the\n // compose file declares both with `${VAR:?…}`: unset, `docker compose\n // up` does not produce a deployment without an admin, it produces a\n // file that refuses to interpolate — and it refuses for `docker compose\n // up -d db` too, which is step 1 of the \"Next steps\" printed below.\n //\n // The address is a placeholder the login route accepts. Not\n // `admin@localhost`: `POST /auth/login` parses its body with\n // `z.string().email()`, which rejects a domain with no dot, so that\n // address seeds an account and then 400s on every attempt to use it.\n // The runtime now refuses it at boot; this default is one it accepts.\n envContent = setEnvValue(\n envContent,\n \"REBASE_ADMIN_EMAIL\",\n \"admin@example.com\",\n \"# ── The first admin account, in production only ──────────────────────\\n\" +\n \"# `rebase dev` ignores both of these: on a laptop the first account to\\n\" +\n \"# register becomes the admin, and it says so at boot. In production —\\n\" +\n \"# `docker compose up`, or anything with NODE_ENV=production — that\\n\" +\n \"# window is shut, because the server answers on a hostname before you\\n\" +\n \"# have typed anything. So the operator names the account here instead.\\n\" +\n \"# Created once, while the user table is empty. Change the email to\\n\" +\n \"# yours, sign in, and change the password below.\"\n );\n envContent = setEnvValue(envContent, \"REBASE_ADMIN_PASSWORD\", adminPassword);\n\n // Blank the build-time API URL rather than shipping `http://localhost:3001`.\n //\n // This is the one environment-specific value `init` used to leave alone,\n // and the chain that made it dangerous is fully closed: `.env.example`\n // ships the literal, `frontend/vite.config.ts` sets `envDir: \"..\"` so\n // `vite build` reads *this* file, and the managed bundle is built on the\n // developer's own machine — so `.env` being gitignored does not save\n // anyone. A stock scaffold deployed with `rebase cloud deploy` served\n // HTML that passed every health check while every XHR from the live site\n // went to the developer's laptop. `rebase cloud env set VITE_API_URL=…`\n // refuses build-time variables, so there was no recovery from the\n // platform side either.\n //\n // Empty is not a missing value, it is the correct one: the client falls\n // back to `window.location.origin`, which is the right shape for a\n // single-origin bundle and the only one that keeps working when a custom\n // domain is added. `rebase dev` injects the port it actually bound, so\n // local development is unaffected.\n // The template ships it blank, so this is belt-and-braces for a project\n // whose .env.example was edited or predates that change.\n envContent = envContent.replace(/^#?\\s*VITE_API_URL=.*$/m, \"VITE_API_URL=\");\n\n // Pin the runtime image `docker-compose.yml` pulls.\n //\n // The compose file reads `rebasepro/server:${REBASE_VERSION:-latest}`,\n // and unset it resolves to `latest` — a tag that moves under a running\n // deployment. That is precisely the hazard `cloudbuild-runtime.yaml`\n // designed away for the managed fleet, which pins releases by digest\n // because \"re-pushing a tag silently changes what the fleet is running\n // with no version anywhere changing\". A self-hoster deserves the same\n // guarantee, and it costs one line here.\n //\n // It also makes the compose header's upgrade instruction true: \"To\n // upgrade Rebase, change REBASE_VERSION and restart\" is a no-op while\n // the value is unset and the tag floats.\n const { tag: runtimeVersion, note } = resolveRuntimeImageTag(readCliVersion());\n const pinned = `${note ? `${note}\\n` : \"\"}REBASE_VERSION=${runtimeVersion}`;\n envContent = /^#?\\s*REBASE_VERSION=.*$/m.test(envContent)\n ? envContent.replace(/^#?\\s*REBASE_VERSION=.*$/m, pinned)\n : `${envContent.trimEnd()}\\n\\n# The Rebase runtime image tag docker-compose.yml pulls.\\n# Change this and restart to upgrade; your project bundle is untouched.\\n${pinned}\\n`;\n\n if (databaseUrl) {\n if (/[\\r\\n]/.test(databaseUrl)) {\n throw new Error(\"Invalid DATABASE_URL: multiline values are not allowed.\");\n }\n // A supplied URL used to be written through verbatim, which quietly\n // dropped the `search_path=public` pin the generated URL below has\n // always carried. Postgres defaults `search_path` to `\"$user\",\n // public`, and this project creates a `rebase` schema — so on any\n // database whose role happens to be named `rebase` (the name every\n // template, compose file and deployment doc uses), unqualified SQL\n // resolves to `$user` and the project's tables get created in\n // `rebase` instead of `public`. Pinning here makes the two branches\n // agree; a URL that already pins something keeps it.\n // Imported lazily: this is the only line in `init` that needs the\n // Postgres package, and a static import would load pg + drizzle on\n // every CLI invocation.\n const { pinSearchPath } = await import(\"@rebasepro/server-postgres\");\n const pinnedUrl = pinSearchPath(databaseUrl);\n // DATABASE_PASSWORD is still written even though the URL points\n // elsewhere: docker-compose.yml interpolates it into both\n // POSTGRES_PASSWORD and the backend's own DATABASE_URL, defaulting\n // to `${DATABASE_PASSWORD:-changeme}`. Omitting it here shipped a\n // compose stack whose database password was literally \"changeme\",\n // on a service that publishes a host port by default.\n //\n // A replacer function, not a replacement string: in a string, `$$`,\n // `$&` and `$'` are patterns, and a password is free to contain\n // them — `pa$$w0rd` reached .env as `pa$w0rd`.\n envContent = envContent.replace(\n /^DATABASE_URL=.*$/m,\n () => `DATABASE_URL=${pinnedUrl}\\nDATABASE_PASSWORD=${dbPassword}`\n );\n } else {\n const dbPort = await findAvailablePort(5432);\n envContent = envContent.replace(\n /^DATABASE_URL=.*$/m,\n // sslmode=disable: the paired docker-compose Postgres has no TLS,\n // and Go-based tooling (atlas, via `rebase db push`) defaults to\n // requiring SSL when the URL doesn't say otherwise.\n //\n // 127.0.0.1 rather than `localhost`: the name resolves to `::1`\n // first on macOS, so on a machine that already runs Postgres on\n // loopback the two addresses can reach two different servers.\n // An address cannot be ambiguous the way a name can.\n //\n // `%3D`, not a literal `=`, inside the `options` value. libpq\n // splits a URI query parameter on the FIRST `=` and rejects any\n // further one outright:\n // extra key/value separator \"=\" in URI query parameter: \"options\"\n // That is every libpq caller — `pg_dump`/`pg_restore` behind\n // `rebase db backup|restore`, and a plain `psql \"$DATABASE_URL\"`\n // copied out of this very file. It is not a version quirk; 15\n // through 18 all refuse it. node-postgres parses URLs itself and\n // accepts the literal form, which is why `rebase dev` and\n // `rebase db push` worked and this shipped broken for so long.\n // `pinSearchPath` (the --database-url branch above) has always\n // emitted the encoded form; this line is what disagreed.\n // Commented out, not omitted. `rebase dev` starts a managed\n // PostgreSQL when nothing names a database, which is what makes\n // a fresh project one command rather than four. The compose URL\n // stays here, one `#` away, because the alternative — a project\n // that mentions Docker nowhere — makes switching to it a\n // documentation lookup instead of an edit.\n // Deliberately short: the header copied from `.env.example`\n // sits directly above and already says what unset means. Saying\n // it twice, in the first section of the first file a new\n // developer opens, is how a generated file starts reading like\n // boilerplate nobody wrote on purpose.\n [\n \"# Commented out on purpose — that is what selects the managed database.\",\n \"# To use the docker-compose Postgres this project ships instead:\",\n \"# docker compose up -d db, then uncomment the line below.\",\n `# DATABASE_URL=postgresql://rebase_app:${dbPassword}@127.0.0.1:${dbPort}/rebase?options=-c%20search_path%3Dpublic&sslmode=disable`,\n `DATABASE_PASSWORD=${dbPassword}`\n ].join(\"\\n\")\n );\n\n // `.env.example` is copied to `.env` and then kept, as the reference\n // that gets committed — so it is the one file in the project that\n // still carries the template's defaults after everything else has\n // been rewritten. Two of them are actively dangerous once the port\n // is derived per project:\n //\n // - its `DATABASE_URL` is UNCOMMENTED, contradicting the rule the\n // rest of the scaffold now states (\"unset means the managed\n // database\"), and\n // - it names `localhost:5432`, while this project's compose\n // publishes ${dbPort}.\n //\n // Copying `.env.example` to `.env` is a near-universal habit, and on\n // a machine that already runs Postgres on 5432 — most developer\n // machines — the result is not a connection failure. It is a\n // successful connection to somebody else's database, which boot will\n // then provision. Comment it out and give it this project's port.\n const envExampleReference = path.join(targetDirectory, \".env.example\");\n if (fs.existsSync(envExampleReference)) {\n let exampleContent = fs.readFileSync(envExampleReference, \"utf-8\");\n exampleContent = exampleContent.replace(\n /^DATABASE_URL=postgresql:\\/\\/[^\\n]*$/m,\n [\n \"# Commented out on purpose — that is what selects the managed database.\",\n \"# To use the docker-compose Postgres this project ships instead:\",\n \"# docker compose up -d db, then uncomment the line below in .env\",\n \"# (with DATABASE_PASSWORD from that file, not the placeholder here).\",\n `# DATABASE_URL=postgresql://rebase_app:changeme@127.0.0.1:${dbPort}/rebase?options=-c%20search_path%3Dpublic&sslmode=disable`\n ].join(\"\\n\")\n );\n // The prose further down illustrates `sslmode=disable` with a\n // full DSN. It is commented and not meant to be copied whole,\n // but a file that names two different ports for one database\n // teaches the reader to distrust both.\n exampleContent = exampleContent.replaceAll(\n \"@localhost:5432/rebase\",\n `@127.0.0.1:${dbPort}/rebase`\n );\n fs.writeFileSync(envExampleReference, exampleContent, \"utf-8\");\n }\n\n // Also update docker-compose.yml with the dynamic host port if it has the default 5432 port mapping\n const dockerComposePath = path.join(targetDirectory, \"docker-compose.yml\");\n if (fs.existsSync(dockerComposePath)) {\n let dockerComposeContent = fs.readFileSync(dockerComposePath, \"utf-8\");\n dockerComposeContent = dockerComposeContent.replace(\n /-\\s*\"5432:5432\"/g,\n `- \"${dbPort}:5432\"`\n );\n fs.writeFileSync(dockerComposePath, dockerComposeContent, \"utf-8\");\n }\n }\n\n // `mode` only applies when the file is created, and this one exists\n // already — so chmod as well, exactly as `writeStateFile` does.\n fs.writeFileSync(envPath, envContent, {\n encoding: \"utf-8\",\n mode: 0o600\n });\n fs.chmodSync(envPath, 0o600);\n }\n}\n"],"mappings":"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"}
|