@rebasepro/cli 0.25.0-canary.ge06257e → 0.25.0
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/bin/rebase.js +9 -5
- package/dist/{agent-setup-C83DXnlx.js → agent-setup-B5AKHOgt.js} +2 -2
- package/dist/{agent-setup-C83DXnlx.js.map → agent-setup-B5AKHOgt.js.map} +1 -1
- package/dist/{api-keys-Bc4FJKYp.js → api-keys-Tm7zvAPe.js} +27 -20
- package/dist/api-keys-Tm7zvAPe.js.map +1 -0
- package/dist/{apps-wG-ZTryA.js → apps-BsU_ILbP.js} +4 -4
- package/dist/{apps-wG-ZTryA.js.map → apps-BsU_ILbP.js.map} +1 -1
- package/dist/{args-CcBphFdj.js → args-BX0YD14a.js} +45 -16
- package/dist/args-BX0YD14a.js.map +1 -0
- package/dist/{atlas-dev-database-DeK3Sa4h.js → atlas-dev-database-OWtqnG7W.js} +2 -2
- package/dist/{atlas-dev-database-DeK3Sa4h.js.map → atlas-dev-database-OWtqnG7W.js.map} +1 -1
- package/dist/{auth-BL7bNQVu.js → auth-Vl2hFKXP.js} +77 -10
- package/dist/auth-Vl2hFKXP.js.map +1 -0
- package/dist/{branch-pointer-DTQNLFtb.js → branch-pointer-9DnwkFJJ.js} +1 -1
- package/dist/{build-h_7Re-67.js → build-BBgT8EJZ.js} +5 -5
- package/dist/{build-h_7Re-67.js.map → build-BBgT8EJZ.js.map} +1 -1
- package/dist/{bundle-CqURVN-K.js → bundle-DtCCCr4w.js} +4 -19
- package/dist/bundle-DtCCCr4w.js.map +1 -0
- package/dist/{cloud-DVV_5GPG.js → cloud-BpH0_bmV.js} +7 -7
- package/dist/{cloud-DVV_5GPG.js.map → cloud-BpH0_bmV.js.map} +1 -1
- package/dist/commands/api-keys.d.ts +4 -1
- package/dist/commands/auth.d.ts +3 -2
- package/dist/connection-banner-DbLJzWf4.js +128 -0
- package/dist/connection-banner-DbLJzWf4.js.map +1 -0
- package/dist/{console-Dw3HLdUs.js → console-CEGm0XNc.js} +4 -4
- package/dist/{console-Dw3HLdUs.js.map → console-CEGm0XNc.js.map} +1 -1
- package/dist/{context-BM-oOMNX.js → context-CyflUrKg.js} +2 -2
- package/dist/{context-BM-oOMNX.js.map → context-CyflUrKg.js.map} +1 -1
- package/dist/{daemon-entry-C6pxdily.js → daemon-entry-CbLRrgzy.js} +199 -3
- package/dist/daemon-entry-CbLRrgzy.js.map +1 -0
- package/dist/{db-Dkn9XhT-.js → db-CRNpA5mH.js} +171 -60
- package/dist/db-CRNpA5mH.js.map +1 -0
- package/dist/{derive-Dl0z2OWi.js → derive-CsoFGAnK.js} +28 -13
- package/dist/{derive-Dl0z2OWi.js.map → derive-CsoFGAnK.js.map} +1 -1
- package/dist/{dev-DAcZR4Pp.js → dev-C0pbMmhS.js} +6 -6
- package/dist/{dev-DAcZR4Pp.js.map → dev-C0pbMmhS.js.map} +1 -1
- package/dist/dev-db/connection-banner.d.ts +47 -0
- package/dist/dev-db/notification-proxy.d.ts +82 -1
- package/dist/{dev-preflight-CorMg7Ub.js → dev-preflight-unHpiYO1.js} +26 -3
- package/dist/dev-preflight-unHpiYO1.js.map +1 -0
- package/dist/{doctor-Ds_lzc9p.js → doctor-CATRdWm6.js} +4 -4
- package/dist/{doctor-Ds_lzc9p.js.map → doctor-CATRdWm6.js.map} +1 -1
- package/dist/{eject-CJHkfnat.js → eject-DuasTr-F.js} +2 -2
- package/dist/{eject-CJHkfnat.js.map → eject-DuasTr-F.js.map} +1 -1
- package/dist/{fold-static-BC9CYicw.js → fold-static-hDHtDfTq.js} +2 -2
- package/dist/{fold-static-BC9CYicw.js.map → fold-static-hDHtDfTq.js.map} +1 -1
- package/dist/{generate_sdk-kfkZmG-d.js → generate_sdk-Cvg5jjJF.js} +3 -3
- package/dist/{generate_sdk-kfkZmG-d.js.map → generate_sdk-Cvg5jjJF.js.map} +1 -1
- package/dist/index.es.js +34 -34
- package/dist/{init-CjoJoThg.js → init-BWAwHPtz.js} +8 -7
- package/dist/init-BWAwHPtz.js.map +1 -0
- package/dist/last-dev-database-c_dKz1S3.js +2 -0
- package/dist/{normalize-imports-BHxL2d05.js → normalize-imports-BoBVh5tU.js} +3 -3
- package/dist/{normalize-imports-BHxL2d05.js.map → normalize-imports-BoBVh5tU.js.map} +1 -1
- package/dist/precompress.d.ts +0 -7
- package/dist/{prepare-C1iaiTC4.js → prepare-DdnU70z8.js} +4 -4
- package/dist/prepare-DdnU70z8.js.map +1 -0
- package/dist/{pull-COpNJFzY.js → pull-C3PXduzl.js} +13 -40
- package/dist/pull-C3PXduzl.js.map +1 -0
- package/dist/resolve-CNQjsatH.js +2 -0
- package/dist/resources/derive.d.ts +9 -0
- package/dist/{resources-CLm6g0br.js → resources-BdNRDEAy.js} +3 -3
- package/dist/{resources-CLm6g0br.js.map → resources-BdNRDEAy.js.map} +1 -1
- package/dist/{schema-BKdh6UoE.js → schema-B0-p6T1O.js} +4 -4
- package/dist/{schema-BKdh6UoE.js.map → schema-B0-p6T1O.js.map} +1 -1
- package/dist/{skills-DEhYiPeO.js → skills-DfnTeyRz.js} +3 -3
- package/dist/{skills-DEhYiPeO.js.map → skills-DfnTeyRz.js.map} +1 -1
- package/dist/{start-BsPJedPQ.js → start-BmEZkS0n.js} +4 -4
- package/dist/{start-BsPJedPQ.js.map → start-BmEZkS0n.js.map} +1 -1
- package/dist/{status-D_B3tlDy.js → status-BJ26yZOo.js} +9 -9
- package/dist/{status-D_B3tlDy.js.map → status-BJ26yZOo.js.map} +1 -1
- package/dist/{storage-CtB8polS.js → storage-DKPUBTWG.js} +3 -3
- package/dist/{storage-CtB8polS.js.map → storage-DKPUBTWG.js.map} +1 -1
- package/dist/{telemetry-BYmPU-Ji.js → telemetry-m9czTNGR.js} +2 -2
- package/dist/{telemetry-BYmPU-Ji.js.map → telemetry-m9czTNGR.js.map} +1 -1
- package/dist/{upgrade-DbuKX9lv.js → upgrade-DjihWuZL.js} +5 -4
- package/dist/{upgrade-DbuKX9lv.js.map → upgrade-DjihWuZL.js.map} +1 -1
- package/dist/utils/args.d.ts +13 -0
- package/dist/utils/redact.d.ts +10 -0
- package/dist/utils/refusal.d.ts +18 -0
- package/package.json +7 -7
- package/templates/overlays/baas/README.md +2 -1
- package/templates/template/.env.example +6 -0
- package/templates/template/frontend/vite.config.ts +7 -73
- package/dist/api-keys-Bc4FJKYp.js.map +0 -1
- package/dist/args-CcBphFdj.js.map +0 -1
- package/dist/auth-BL7bNQVu.js.map +0 -1
- package/dist/bundle-CqURVN-K.js.map +0 -1
- package/dist/daemon-entry-C6pxdily.js.map +0 -1
- package/dist/db-Dkn9XhT-.js.map +0 -1
- package/dist/dev-preflight-CorMg7Ub.js.map +0 -1
- package/dist/init-CjoJoThg.js.map +0 -1
- package/dist/last-dev-database-BEBPfAMY.js +0 -2
- package/dist/prepare-C1iaiTC4.js.map +0 -1
- package/dist/pull-COpNJFzY.js.map +0 -1
- package/dist/resolve-b_p9bmdH.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate_sdk-kfkZmG-d.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 { 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 */\nasync function loadCollections(collectionsDir: string): Promise<CollectionConfig[]> {\n const absDir = path.resolve(collectionsDir);\n\n if (!fs.existsSync(absDir)) {\n throw new Error(`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 Error(\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 Error(\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 this project last ran on; fall back to the literal only when the project\n * has never been started.\n */\nexport function resolveExampleBaseUrl(cwd: string): string {\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);\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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"}
|
|
1
|
+
{"version":3,"file":"generate_sdk-Cvg5jjJF.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 { 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 */\nasync function loadCollections(collectionsDir: string): Promise<CollectionConfig[]> {\n const absDir = path.resolve(collectionsDir);\n\n if (!fs.existsSync(absDir)) {\n throw new Error(`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 Error(\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 Error(\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 this project last ran on; fall back to the literal only when the project\n * has never been started.\n */\nexport function resolveExampleBaseUrl(cwd: string): string {\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":";;;;;;;;;;;;;;;;;;;;;;AAoDA,IAAa,gBAAgB;;AAG7B,IAAM,kBAAkB;AAExB,IAAM,kBAAkB,GAAG,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4B3C,SAAgB,gBAAgB,gBAAgC;CAC5D,OAAO,KAAK,KAAK,KAAK,QAAQ,KAAK,QAAQ,cAAc,CAAC,GAAG,WAAW;AAC5E;;AAGA,SAAS,gBAAgB,KAAsB;CAC3C,IAAI;EACA,OAAO,GAAG,aAAa,KAAK,KAAK,KAAK,aAAa,GAAG,OAAO,CAAC,CAAC,WAAW,eAAe;CAC7F,QAAQ;EACJ,OAAO;CACX;AACJ;;AAGA,SAAS,eAAe,UAAkB,SAAuB;CAC7D,IAAI;EACA,IAAI,GAAG,aAAa,UAAU,OAAO,MAAM,SAAS;CACxD,QAAQ,CAER;CACA,GAAG,cAAc,UAAU,SAAS,OAAO;AAC/C;;;;;;AAOA,SAAS,kBAAkB,KAAa,eAA6B;CACjE,MAAM,eAAe,KAAK,KAAK,KAAK,aAAa;CACjD,IAAI,GAAG,WAAW,YAAY,KAAK,CAAC,gBAAgB,GAAG,GACnD,MAAM,IAAI,MACN,GAAG,aAAa,mHAEpB;CAEJ,GAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CACrC,eAAe,KAAK,KAAK,KAAK,mBAAmB,GAAG,aAAa;CACjE,eAAe,cAAc,eAAe;AAChD;;;;;;;;AASA,SAAS,kBAAkB,aAA0C;CACjE,IAAI,CAAC,eAAe,CAAC,eAAe,WAAW,GAAG,OAAO;CACzD,IAAI;EACA,OAAO,eAAe,aAAa,WAAW,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,qBAAqB;CACxF,QAAQ;EACJ,OAAO;CACX;AACJ;;;;;;;;AASA,SAAS,qBAAqB,aAA4E;CACtG,IAAI,CAAC,eAAe,CAAC,eAAe,WAAW,GAC3C,OAAO,EAAE,SAAS,2EAA2E;CAEjG,IAAI;CACJ,IAAI;EACA,SAAS,aAAa,WAAW;CACrC,SAAS,OAAO;EACZ,OAAO,EAAE,SAAS,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,IAAI;CACnH;CACA,MAAM,UAAU,eAAe,OAAO,QAAQ;CAC9C,IAAI,CAAC,SAAS,OAAO,EAAE,SAAS,yDAAyD;CACzF,IAAI,QAAQ,IAAI,qBAAqB,MAAM,OAAO,EAAE,SAAS,OAAO,YAAY,YAAY;CAK5F,OAAO,EAAE,SAAS,cAAc,aAAa;EAHzC,GAAG,OAAO;EACV,MAAM;GAAE,GAAG,OAAO,SAAS;IAAO,QAAQ,OAAO;IAAE,GAAG,QAAQ;IAAK,kBAAkB;GAAK;EAAE;CAEnD,CAAQ,EAAE;AAC3D;;;;;;;;;;;;;;;;;;;;AAqBA,eAAe,gBAAgB,gBAAqD;CAChF,MAAM,SAAS,KAAK,QAAQ,cAAc;CAE1C,IAAI,CAAC,GAAG,WAAW,MAAM,GACrB,MAAM,IAAI,MAAM,oCAAoC,OAAO,IAAI,sBAAsB,EAAE;CAG3F,IAAI;CACJ,IAAI;EACA,MAAM,aAAa,MAAM,OAAO;EAChC,OAAQ,WAAW,WAAW;CAClC,QAAQ;EACJ,MAAM,aAAa;GAAC,GAAG,cAAc,qBAAqB,CAAC,CAAC,CAAC;GAAS;GAAM;EAAM,CAAC,CAAC,KAAK,GAAG;EAC5F,MAAM,IAAI,MACN,2CAA2C,WAAW,4EAE1D;CACJ;CAEA,IAAI,CAAC,GAAG,SAAS,MAAM,CAAC,CAAC,YAAY,GAAG;EACpC,MAAM,MAAM,KAAK,KAAK,QAAQ,MAAM,GAAG;GAAE,gBAAgB;GAAM,YAAY;EAAK,CAAC,CAAC,CAAC,MAAM;EACzF,MAAM,SAAS,IAAI,sBAAsB,IAAI,eAAe,IAAI;EAChE,IAAI,MAAM,QAAQ,MAAM,GAAG,OAAO;EAClC,MAAM,IAAI,MACN,sCAAsC,OAAO,2GAEjD;CACJ;CAEA,MAAM,eAAe,KAAK,QAAQ;EAC9B,gBAAgB;EAChB,YAAY;CAChB,CAAC;CAED,MAAM,cAAkC,CAAC;CACzC,MAAM,WAAqB,CAAC;CAC5B,MAAM,QAAQ,GAAG,YAAY,MAAM,CAAC,CAAC,OAAO,sBAAsB,CAAC,CAAC,KAAK;CAEzE,KAAK,MAAM,QAAQ,OACf,IAAI;EACA,MAAM,MAAM,aAAa,KAAK,KAAK,QAAQ,IAAI,CAAC;EAChD,MAAM,WAAW,IAAI,WAAW;EAChC,IAAI,YAAY,OAAO,aAAa,YAAY,UAAU,UACtD,YAAY,KAAK,QAA4B;OAE7C,SAAS,KAAK,GAAG,KAAK,oCAAoC;CAElE,SAAS,KAAK;EACV,SAAS,KAAK,GAAG,KAAK,IAAK,IAAc,SAAS;CACtD;CAGJ,IAAI,SAAS,SAAS,GAClB,MAAM,IAAI,MACN,kBAAkB,SAAS,OAAO,2BAA2B,OAAO,OACpE,SAAS,KAAI,YAAW,OAAO,SAAS,CAAC,CAAC,KAAK,IAAI,IACnD,+HAEJ;CAGJ,OAAO;AACX;;;;AAKA,SAAS,WAAW,WAAmB,OAA8B;CACjE,MAAM,YAAY,KAAK,QAAQ,SAAS;CAGxC,GAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;CAE3C,KAAK,MAAM,QAAQ,OAAO;EACtB,MAAM,WAAW,KAAK,KAAK,WAAW,KAAK,IAAI;EAC/C,MAAM,MAAM,KAAK,QAAQ,QAAQ;EACjC,IAAI,CAAC,GAAG,WAAW,GAAG,GAClB,GAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;EAEzC,GAAG,cAAc,UAAU,KAAK,SAAS,OAAO;CACpD;AACJ;AAEA,SAAS,eAAqB;CAC1B,QAAQ,IAAI;EACd,MAAM,KAAK,qBAAqB,EAAE;;EAElC,MAAM,KAAK,OAAO,EAAE;;;EAGpB,MAAM,KAAK,SAAS,EAAE;iCACS,sBAAsB;;;;;;;;;;;;;EAarD,MAAM,KAAK,UAAU,EAAE;;;;;EAKvB,KAAK,CAAC;AACR;;;;;;;;;;AA6BA,SAAS,oBAAoB,YAA0C;CACnE,IAAI,WAAW,SAAS,SACpB,OAAO,CAAC,qFAAqF;CAEjG,IAAI,WAAW,SAAS,WACpB,OAAO,CAAC,iHAAiH;CAE7H,IAAI,WAAW,UACX,OAAO,CACH,8GACA,4CACJ;CAEJ,IAAI,WAAW,YACX,OAAO,CACH,oIACA,4BACJ;CAEJ,OAAO,CAAC,uIAAuI;AACnJ;AAEA,eAAe,uBACX,SACA,OACA,YACmE;CACnE,MAAM,MAAM,GAAG,QAAQ,QAAQ,QAAQ,EAAE,EAAE;CAE3C,MAAM,UAAkC,EAAE,QAAQ,mBAAmB;CACrE,IAAI,OAAO,QAAQ,gBAAgB,UAAU;CAE7C,IAAI;CACJ,IAAI;EACA,WAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,CAAC;CAC3C,SAAS,KAAK;EACV,QAAQ,IAAI,MAAM,IAAI,uBAAuB,KAAK,CAAC;EACnD,QAAQ,IAAI,MAAM,KAAK,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,GAAG,CAAC;EACjF,QAAQ,KAAK,CAAC;CAClB;CAEA,IAAI,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;EACpD,QAAQ,IAAI,MAAM,IAAI,oDAAoD,SAAS,OAAO,GAAG,CAAC;EAC9F,QAAQ,IAAI,MAAM,KAAK,2EAA2E,CAAC;EACnG,KAAK,MAAM,QAAQ,oBAAoB,UAAU,GAAG,QAAQ,IAAI,MAAM,KAAK,OAAO,MAAM,CAAC;EACzF,QAAQ,KAAK,CAAC;CAClB;CAEA,IAAI,SAAS,WAAW,KAAK;EACzB,QAAQ,IAAI,MAAM,IAAI,2CAA2C,CAAC;EAClE,QAAQ,IAAI,MAAM,KAAK,kDAAkD,CAAC;EAC1E,QAAQ,KAAK,CAAC;CAClB;CAEA,IAAI,CAAC,SAAS,IAAI;EACd,QAAQ,IAAI,MAAM,IAAI,oCAAoC,SAAS,OAAO,EAAE,CAAC;EAC7E,QAAQ,KAAK,CAAC;CAClB;CAEA,MAAM,WAAW,MAAM,SAAS,KAAK;CAKrC,IAAI,CAAC,MAAM,QAAQ,SAAS,WAAW,GAAG;EACtC,QAAQ,IAAI,MAAM,IAAI,wDAAwD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAClB;CAEA,OAAO;EACH,aAAa,uBAAuB,SAAS,WAAW;EACxD,eAAe,SAAS,iBAAiB;CAC7C;AACJ;;;;;;;;;;AAWA,SAAS,iBAAiB,QAAgB,KAAsB;CAC5D,MAAM,OAAO,SAAS,gBAAgB,GAAG,KAAK,GAAG;CACjD,IAAI,CAAC,MAAM,QAAQ,OAAO;CAC1B,IAAI;EAGA,OAAO,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,WAAW,IAAI,IAAI,MAAM,CAAC,CAAC;CAC3D,QAAQ;EACJ,OAAO;CACX;AACJ;;;;;;;;;;;AAYA,SAAgB,sBAAsB,KAAqB;CACvD,MAAM,cAAc,gBAAgB,GAAG,KAAK;CAC5C,IAAI;EACA,MAAM,QAAQ,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,aAAa,WAAW,YAAY,GAAG,OAAO,CAAC;EAClG,IAAI,OAAO,MAAM,YAAY,YAAY,MAAM,SAAS,OAAO,MAAM;EACrE,IAAI,OAAO,MAAM,SAAS,UAAU,OAAO,oBAAoB,MAAM;CACzE,QAAQ,CAER;CACA,OAAO;AACX;;AAGA,SAAgB,iBAAiB,MAAuB;CACpD,OAAO,6BAA6B,KAAK,IAAI;AACjD;;AAGA,SAAS,oBAAoB,MAAc,KAAqB;CAC5D,IAAI,SAAS,QAAQ;EAGjB,IAAI;EACJ,IAAI;GACA,SAAS,IAAI,IAAI,IAAI;EACzB,QAAQ;GACJ,QAAQ,IAAI,MAAM,IAAI,QAAQ,KAAK,sBAAsB,CAAC;GAC1D,QAAQ,IAAI,MAAM,KAAK,iEAAiE,CAAC;GACzF,QAAQ,KAAK,CAAC;EAClB;EACA,IAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;GAC7D,QAAQ,IAAI,MAAM,IAAI,4CAA4C,CAAC;GACnE,QAAQ,KAAK,CAAC;EAClB;EACA,OAAO;CACX;CAGA,MAAM,OAAO,SADO,gBAAgB,GAAG,KAAK,GACX;CAEjC,IAAI,CAAC,MAAM;EACP,QAAQ,IAAI,MAAM,IAAI,+CAA+C,CAAC;EACtE,QAAQ,IAAI,MAAM,KAAK,0DAA0D,CAAC;EAClF,QAAQ,KAAK,CAAC;CAClB;CAEA,MAAM,SAAS,KAAK;CACpB,IAAI,CAAC,QAAQ;EACT,QAAQ,IAAI,MAAM,IAAI,sCAAsC,CAAC;EAC7D,QAAQ,IAAI,MAAM,KAAK,2DAA2D,CAAC;EACnF,QAAQ,KAAK,CAAC;CAClB;CAEA,OAAO;AACX;;;;AAKA,eAAsB,mBAAmB,MAAsC;CAC3E,MAAM,EAAE,gBAAgB,QAAQ,QAAQ;CAExC,IAAI,KAAK,MAAM;EACX,aAAa;EACb;CACJ;CAEA,MAAM,yBAAyB,KAAK,WAAW,cAAc,IACvD,iBACA,KAAK,KAAK,KAAK,cAAc;CAEnC,MAAM,iBAAiB,KAAK,WAAW,MAAM,IACvC,SACA,KAAK,KAAK,KAAK,MAAM;CAE3B,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,KAAK,2BAA2B,CAAC;CACnD,QAAQ,IAAI,EAAE;CAEd,IAAI;CACJ,IAAI;CAEJ,IAAI,KAAK,MAAM;EACX,MAAM,UAAU,oBAAoB,KAAK,MAAM,GAAG;EAClD,QAAQ,IAAI,KAAK,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS;EACxD,QAAQ,IAAI,KAAK,MAAM,KAAK,SAAS,EAAE,QAAQ,gBAAgB;EAC/D,QAAQ,IAAI,EAAE;EACd,QAAQ,IAAI,MAAM,KAAK,sCAAsC,CAAC;EAE9D,MAAM,UAAU,iBAAiB,SAAS,GAAG,IACvC,QAAQ,IAAI,qBACZ,KAAA;EAEN,IAAI,CAAC,KAAK,SAAS,CAAC,WAAW,QAAQ,IAAI,oBACvC,QAAQ,IAAI,MAAM,IACd,oGACJ,CAAC;EAGL,MAAM,SAAS,MAAM,uBAAuB,SAAS,KAAK,SAAS,SAAS;GACxE,MAAM,KAAK,QAAQ,UAAU,UAAU,YAAY;GACnD,UAAU,QAAQ,QAAQ,IAAI,kBAAkB;GAChD,YAAY,QAAQ,YAAY,gBAAgB,GAAG,KAAK,GAAG,CAAC,CAAC,kBAAkB;EACnF,CAAC;EACD,cAAc,OAAO;EACrB,sBAAsB,OAAO;CACjC,OAAO;EAOH,IAAI,CAAC,GAAG,WAAW,sBAAsB,GAAG;GACxC,QAAQ,IAAI,MAAM,KACd,4FAEJ,CAAC;GACD,QAAQ,IAAI,MAAM,KACd,iCAAiC,uBAAuB,iBAC5D,CAAC;GACD,QAAQ,IAAI,EAAE;GACd;EACJ;EACA,QAAQ,IAAI,KAAK,MAAM,KAAK,cAAc,EAAE,GAAG,wBAAwB;EACvE,QAAQ,IAAI,KAAK,MAAM,KAAK,SAAS,EAAE,QAAQ,gBAAgB;EAC/D,QAAQ,IAAI,EAAE;EACd,QAAQ,IAAI,MAAM,KAAK,uCAAuC,CAAC;EAC/D,cAAc,MAAM,gBAAgB,sBAAsB;CAC9D;CAGA,YAAY,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;CAEvD,IAAI,YAAY,WAAW,GAAG;EAC1B,QAAQ,IAAI,MAAM,IAAI,gDAAgD,CAAC;EACvE,QAAQ,KAAK,CAAC;CAClB;CAEA,QAAQ,IAAI,MAAM,MAAM,aAAa,YAAY,OAAO,kBAAkB,YAAY,KAAI,MAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC;CACpH,QAAQ,IAAI,EAAE;CAGd,QAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;CACrD,IAAI;CACJ,IAAI;EACA,QAAQ,YAAY,aAAa,EAAE,SAAS,sBAAsB,GAAG,EAAE,CAAC;CAC5E,SAAS,KAAK;EAKV,IAAI,eAAe,cAAc;GAC7B,QAAQ,IAAI,EAAE;GACd,QAAQ,IAAI,MAAM,IAAI,OAAO,IAAI,SAAS,CAAC;GAC3C,QAAQ,KAAK,CAAC;EAClB;EACA,MAAM;CACV;CAeA,MAAM,gBAAgB,uBAAuB,qBAAqB,WAAW;CAC7E,MAAM,KAAK;EACP,MAAM;EACN,SAAS;;;;;;;;;;gCAUe,KAAK,UAAU,aAAa,EAAE;;CAE1D,CAAC;CAED,QAAQ,IAAI,MAAM,MAAM,iBAAiB,MAAM,OAAO,SAAS,CAAC;CAChE,QAAQ,IAAI,MAAM,KAAK,cAAc,eAAe,CAAC;CAGrD,QAAQ,IAAI,MAAM,KAAK,kBAAkB,eAAe,IAAI,CAAC;CAC7D,WAAW,gBAAgB,KAAK;CAKhC,MAAM,cAAc,gBAAgB,sBAAsB;CAC1D,MAAM,cAAc,KAAK,eAAe,gBAAgB,GAAG,KAAK,KAAA;CAChE,IAAI,KAAK,YAAY,gBAAgB,WAAW,KAAK,kBAAkB,WAAW,GAAG;EACjF,IAAI,CAAC,GAAG,WAAW,KAAK,QAAQ,WAAW,CAAC,GAAG;GAC3C,QAAQ,IAAI,MAAM,IAAI,UAAU,KAAK,QAAQ,WAAW,EAAE,8BAA8B,CAAC;GACzF,QAAQ,IAAI,MAAM,KAAK,6EAA6E,CAAC;GACrG,QAAQ,KAAK,CAAC;GACd;EACJ;EACA,MAAM,gBAAgB,MAAM,MAAM,SAAS,KAAK,SAAS,mBAAmB,CAAC,EAAE;EAC/E,IAAI,kBAAkB,KAAA,GAAW;GAC7B,IAAI;IACA,kBAAkB,aAAa,aAAa;GAChD,SAAS,OAAO;IACZ,QAAQ,IAAI,MAAM,IAAI,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,CAAC;IACtF,QAAQ,KAAK,CAAC;IACd;GACJ;GACA,QAAQ,IAAI,MAAM,MAAM,uDAAuD,aAAa,CAAC;GAC7F,IAAI,KAAK,UAAU;IACf,MAAM,aAAa,qBAAqB,WAAW;IACnD,IAAI,aAAa,YACb,QAAQ,IAAI,MAAM,KAAK,qBAAqB,KAAK,SAAS,KAAK,WAAW,OAAO,KAAK,cAAc,qBAAqB,CAAC;SAE1H,QAAQ,IAAI,MAAM,OAAO,OAAO,WAAW,SAAS,CAAC;GAE7D;EACJ;CACJ;CAEA,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,MAAM,KAAK,iCAAiC,CAAC;CAC/D,QAAQ,IAAI,EAAE;CACd,MAAM,cAAc,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,gBAAgB,gBAAgB,CAAC;CACvF,MAAM,aAAa,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,gBAAgB,aAAa,CAAC;CACnF,MAAM,cAAc,YAAY,EAAE,EAAE,QAAQ;CAE5C,QAAQ,IAAI,MAAM,KAAK,UAAU,CAAC;CAClC,QAAQ,IAAI,MAAM,KAAK,6DAA6D,CAAC;CACrF,QAAQ,IAAI,MAAM,KAAK,6DAA6D,YAAY,GAAG,CAAC;CACpG,QAAQ,IAAI,MAAM,KAAK,uCAAuC,WAAW,GAAG,CAAC;CAC7E,QAAQ,IAAI,EAAE;CACd,QAAQ,IAAI,MAAM,KAAK,mDAAmD,CAAC;CAC3E,QAAQ,IAAI,MAAM,KAAK,qBAAqB,sBAAsB,GAAG,EAAE,GAAG,CAAC;CAI3E,QAAQ,IAAI,MAAM,KAAK,wCAAwC,CAAC;CAGhE,QAAQ,IAAI,MAAM,KAAK,6CAA6C,CAAC;CACrE,QAAQ,IAAI,MAAM,KAAK,qCAAqC,CAAC;CAC7D,QAAQ,IAAI,MAAM,KAAK,SAAS,CAAC;CACjC,QAAQ,IAAI,EAAE;CAMd,MAAM,kBAAkB,qBAAqB,WAAW;CACxD,MAAM,gBAAgB,iBAAiB,eAAe,IAChD,eAAe,oBACf,eAAe,KAAK,UAAU,eAAe,EAAE;CACrD,QAAQ,IAAI,MAAM,KAAK,8BAA8B,cAAc,SAAS,CAAC;CAC7E,QAAQ,IAAI,EAAE;AAClB"}
|
package/dist/index.es.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { i as recordEvent, n as isEnabled, u as errorClass } from "./telemetry-EMFRVRQi.js";
|
|
2
2
|
import { p as requireProjectRoot } from "./project-Wp2zoyeN.js";
|
|
3
|
-
import { a as unknownCommand, n as parseCommandArgs } from "./args-
|
|
3
|
+
import { a as unknownCommand, n as parseCommandArgs } from "./args-BX0YD14a.js";
|
|
4
4
|
import { n as cliVersion } from "./version-Buyyo1ut.js";
|
|
5
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-DRp0UVTj.js";
|
|
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-
|
|
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-DtCCCr4w.js";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import arg from "arg";
|
|
9
9
|
import path from "path";
|
|
@@ -89,39 +89,39 @@ var NO_VOCABULARY = {
|
|
|
89
89
|
async function commandVocabulary(command) {
|
|
90
90
|
switch (command) {
|
|
91
91
|
case "schema": return {
|
|
92
|
-
subcommands: (await import("./schema-
|
|
92
|
+
subcommands: (await import("./schema-B0-p6T1O.js")).SCHEMA_SUBCOMMANDS,
|
|
93
93
|
aliases: {}
|
|
94
94
|
};
|
|
95
95
|
case "db": return {
|
|
96
|
-
subcommands: (await import("./db-
|
|
96
|
+
subcommands: (await import("./db-CRNpA5mH.js")).DB_SUBCOMMANDS,
|
|
97
97
|
aliases: {}
|
|
98
98
|
};
|
|
99
99
|
case "auth": return {
|
|
100
|
-
subcommands: (await import("./auth-
|
|
100
|
+
subcommands: (await import("./auth-Vl2hFKXP.js")).AUTH_SUBCOMMANDS,
|
|
101
101
|
aliases: {}
|
|
102
102
|
};
|
|
103
103
|
case "skills": return {
|
|
104
|
-
subcommands: (await import("./skills-
|
|
104
|
+
subcommands: (await import("./skills-DfnTeyRz.js")).SKILLS_SUBCOMMANDS,
|
|
105
105
|
aliases: {}
|
|
106
106
|
};
|
|
107
107
|
case "api-keys": return {
|
|
108
|
-
subcommands: (await import("./api-keys-
|
|
108
|
+
subcommands: (await import("./api-keys-Tm7zvAPe.js")).API_KEYS_SUBCOMMANDS,
|
|
109
109
|
aliases: {}
|
|
110
110
|
};
|
|
111
111
|
case "storage": return {
|
|
112
|
-
subcommands: (await import("./storage-
|
|
112
|
+
subcommands: (await import("./storage-DKPUBTWG.js")).STORAGE_SUBCOMMANDS,
|
|
113
113
|
aliases: {}
|
|
114
114
|
};
|
|
115
115
|
case "apps": return {
|
|
116
|
-
subcommands: (await import("./apps-
|
|
116
|
+
subcommands: (await import("./apps-BsU_ILbP.js")).APPS_SUBCOMMANDS,
|
|
117
117
|
aliases: {}
|
|
118
118
|
};
|
|
119
119
|
case "telemetry": return {
|
|
120
|
-
subcommands: (await import("./telemetry-
|
|
120
|
+
subcommands: (await import("./telemetry-m9czTNGR.js")).TELEMETRY_SUBCOMMANDS,
|
|
121
121
|
aliases: {}
|
|
122
122
|
};
|
|
123
123
|
case "cloud": {
|
|
124
|
-
const cloud = await import("./cloud-
|
|
124
|
+
const cloud = await import("./cloud-BpH0_bmV.js");
|
|
125
125
|
return {
|
|
126
126
|
subcommands: cloud.CLOUD_GROUP_NAMES,
|
|
127
127
|
aliases: cloud.GROUP_ALIASES
|
|
@@ -243,12 +243,12 @@ async function entry(args) {
|
|
|
243
243
|
async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespacedCommands) {
|
|
244
244
|
switch (command) {
|
|
245
245
|
case "__dev-db-daemon": {
|
|
246
|
-
const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-
|
|
246
|
+
const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-CbLRrgzy.js");
|
|
247
247
|
await runDaemon(parseDaemonArgs(args));
|
|
248
248
|
return;
|
|
249
249
|
}
|
|
250
250
|
case "init": {
|
|
251
|
-
const { createRebaseApp } = await import("./init-
|
|
251
|
+
const { createRebaseApp } = await import("./init-BWAwHPtz.js");
|
|
252
252
|
await createRebaseApp(args);
|
|
253
253
|
break;
|
|
254
254
|
}
|
|
@@ -271,7 +271,7 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
|
|
|
271
271
|
maxPositionals: 0
|
|
272
272
|
});
|
|
273
273
|
const sdkRoot = sdkHelp ? process.cwd() : requireProjectRoot();
|
|
274
|
-
const { generateSdkCommand } = await import("./generate_sdk-
|
|
274
|
+
const { generateSdkCommand } = await import("./generate_sdk-Cvg5jjJF.js");
|
|
275
275
|
await generateSdkCommand({
|
|
276
276
|
collectionsDir: sdkArgs["--collections"] || path.join(sdkRoot, "config/collections"),
|
|
277
277
|
output: sdkArgs["--output"] || path.join(sdkRoot, "generated/sdk"),
|
|
@@ -285,101 +285,101 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
|
|
|
285
285
|
break;
|
|
286
286
|
}
|
|
287
287
|
case "schema": {
|
|
288
|
-
const { schemaCommand } = await import("./schema-
|
|
288
|
+
const { schemaCommand } = await import("./schema-B0-p6T1O.js");
|
|
289
289
|
await schemaCommand(effectiveSubcommand, args);
|
|
290
290
|
break;
|
|
291
291
|
}
|
|
292
292
|
case "db": {
|
|
293
|
-
const { dbCommand } = await import("./db-
|
|
293
|
+
const { dbCommand } = await import("./db-CRNpA5mH.js");
|
|
294
294
|
await dbCommand(effectiveSubcommand, args);
|
|
295
295
|
break;
|
|
296
296
|
}
|
|
297
297
|
case "console": {
|
|
298
|
-
const { consoleCommand } = await import("./console-
|
|
298
|
+
const { consoleCommand } = await import("./console-CEGm0XNc.js");
|
|
299
299
|
await consoleCommand(args);
|
|
300
300
|
break;
|
|
301
301
|
}
|
|
302
302
|
case "dev": {
|
|
303
|
-
const { devCommand } = await import("./dev-
|
|
303
|
+
const { devCommand } = await import("./dev-C0pbMmhS.js");
|
|
304
304
|
await devCommand(args);
|
|
305
305
|
break;
|
|
306
306
|
}
|
|
307
307
|
case "normalize-imports": {
|
|
308
|
-
const { normalizeImportsCommand } = await import("./normalize-imports-
|
|
308
|
+
const { normalizeImportsCommand } = await import("./normalize-imports-BoBVh5tU.js");
|
|
309
309
|
await normalizeImportsCommand(args);
|
|
310
310
|
break;
|
|
311
311
|
}
|
|
312
312
|
case "build": {
|
|
313
|
-
const { buildCommand } = await import("./build-
|
|
313
|
+
const { buildCommand } = await import("./build-BBgT8EJZ.js").then((n) => n.n);
|
|
314
314
|
await buildCommand(args);
|
|
315
315
|
break;
|
|
316
316
|
}
|
|
317
317
|
case "start": {
|
|
318
|
-
const { startCommand } = await import("./start-
|
|
318
|
+
const { startCommand } = await import("./start-BmEZkS0n.js");
|
|
319
319
|
await startCommand(args);
|
|
320
320
|
break;
|
|
321
321
|
}
|
|
322
322
|
case "upgrade": {
|
|
323
|
-
const { upgradeCommand } = await import("./upgrade-
|
|
323
|
+
const { upgradeCommand } = await import("./upgrade-DjihWuZL.js");
|
|
324
324
|
await upgradeCommand(args);
|
|
325
325
|
break;
|
|
326
326
|
}
|
|
327
327
|
case "apps": {
|
|
328
|
-
const { appsCommand } = await import("./apps-
|
|
328
|
+
const { appsCommand } = await import("./apps-BsU_ILbP.js");
|
|
329
329
|
await appsCommand(effectiveSubcommand, args);
|
|
330
330
|
break;
|
|
331
331
|
}
|
|
332
332
|
case "eject": {
|
|
333
|
-
const { ejectCommand } = await import("./eject-
|
|
333
|
+
const { ejectCommand } = await import("./eject-DuasTr-F.js");
|
|
334
334
|
await ejectCommand(args);
|
|
335
335
|
break;
|
|
336
336
|
}
|
|
337
337
|
case "auth": {
|
|
338
|
-
const { authCommand } = await import("./auth-
|
|
338
|
+
const { authCommand } = await import("./auth-Vl2hFKXP.js");
|
|
339
339
|
await authCommand(effectiveSubcommand, args);
|
|
340
340
|
break;
|
|
341
341
|
}
|
|
342
342
|
case "status": {
|
|
343
|
-
const { statusCommand } = await import("./status-
|
|
343
|
+
const { statusCommand } = await import("./status-BJ26yZOo.js");
|
|
344
344
|
await statusCommand(args);
|
|
345
345
|
break;
|
|
346
346
|
}
|
|
347
347
|
case "resources": {
|
|
348
|
-
const { resourcesCommand } = await import("./resources-
|
|
348
|
+
const { resourcesCommand } = await import("./resources-BdNRDEAy.js");
|
|
349
349
|
await resourcesCommand(args);
|
|
350
350
|
break;
|
|
351
351
|
}
|
|
352
352
|
case "doctor": {
|
|
353
|
-
const { doctorCommand } = await import("./doctor-
|
|
353
|
+
const { doctorCommand } = await import("./doctor-CATRdWm6.js");
|
|
354
354
|
await doctorCommand(args);
|
|
355
355
|
break;
|
|
356
356
|
}
|
|
357
357
|
case "skills": {
|
|
358
|
-
const { skillsCommand } = await import("./skills-
|
|
358
|
+
const { skillsCommand } = await import("./skills-DfnTeyRz.js");
|
|
359
359
|
await skillsCommand(effectiveSubcommand, args);
|
|
360
360
|
break;
|
|
361
361
|
}
|
|
362
362
|
case "api-keys": {
|
|
363
|
-
const { apiKeysCommand } = await import("./api-keys-
|
|
363
|
+
const { apiKeysCommand } = await import("./api-keys-Tm7zvAPe.js");
|
|
364
364
|
await apiKeysCommand(effectiveSubcommand, args);
|
|
365
365
|
break;
|
|
366
366
|
}
|
|
367
367
|
case "storage": {
|
|
368
|
-
const { storageCommand } = await import("./storage-
|
|
368
|
+
const { storageCommand } = await import("./storage-DKPUBTWG.js");
|
|
369
369
|
await storageCommand(effectiveSubcommand, args);
|
|
370
370
|
break;
|
|
371
371
|
}
|
|
372
372
|
case "cloud": {
|
|
373
|
-
const { cloudCommand } = await import("./cloud-
|
|
373
|
+
const { cloudCommand } = await import("./cloud-BpH0_bmV.js");
|
|
374
374
|
await cloudCommand(effectiveSubcommand, args);
|
|
375
375
|
break;
|
|
376
376
|
}
|
|
377
377
|
case "telemetry": {
|
|
378
|
-
const { telemetryCommand } = await import("./telemetry-
|
|
378
|
+
const { telemetryCommand } = await import("./telemetry-m9czTNGR.js");
|
|
379
379
|
await telemetryCommand(args);
|
|
380
380
|
break;
|
|
381
381
|
}
|
|
382
|
-
default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-
|
|
382
|
+
default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-BpH0_bmV.js")).CLOUD_GROUP_NAMES });
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
/** The global help. Exported so its Options block can be held against {@link ROOT_FLAGS}. */
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { i as recordEvent, l as durationBucket } from "./telemetry-EMFRVRQi.js";
|
|
2
2
|
import { n as getPMCommands, t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
|
|
3
|
-
import { n as parseCommandArgs, r as wantsHelp } from "./args-
|
|
3
|
+
import { n as parseCommandArgs, r as wantsHelp } from "./args-BX0YD14a.js";
|
|
4
4
|
import { n as cliVersion } from "./version-Buyyo1ut.js";
|
|
5
|
-
import { AGENTS, AGENT_KEYS, resolveAgentNames } from "./skills-
|
|
6
|
-
import { configureAgents, printAgentSetup, promptForAgents, retargetScaffoldMcpConfig } from "./agent-setup-
|
|
7
|
-
import { W as resolveCloudUrl, Z as writeLink } from "./context-
|
|
8
|
-
import { r as dockerClaimedPorts } from "./dev-preflight-
|
|
5
|
+
import { AGENTS, AGENT_KEYS, resolveAgentNames } from "./skills-DfnTeyRz.js";
|
|
6
|
+
import { configureAgents, printAgentSetup, promptForAgents, retargetScaffoldMcpConfig } from "./agent-setup-B5AKHOgt.js";
|
|
7
|
+
import { W as resolveCloudUrl, Z as writeLink } from "./context-CyflUrKg.js";
|
|
8
|
+
import { r as dockerClaimedPorts } from "./dev-preflight-unHpiYO1.js";
|
|
9
9
|
import { n as promptForConsent } from "./consent-ClRHmcxf.js";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import fs from "fs";
|
|
@@ -621,7 +621,8 @@ function initNextSteps(input) {
|
|
|
621
621
|
lines.push(note(" A table is served once row-level security is enabled on it, and a"));
|
|
622
622
|
lines.push(note(" policy is what opens its rows:"));
|
|
623
623
|
lines.push(cmd(["ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;"]));
|
|
624
|
-
lines.push(cmd(["
|
|
624
|
+
lines.push(cmd(["-- rebase.uid() is text: the cast makes this work for a uuid or integer column too."]));
|
|
625
|
+
lines.push(cmd(["CREATE POLICY your_table_owner ON your_table FOR ALL USING (user_id::text = rebase.uid());"]));
|
|
625
626
|
lines.push(note(" The API logs any table it skips, and why."));
|
|
626
627
|
} else if (ownDatabase) {
|
|
627
628
|
lines.push(note("Your custom database is configured in .env."));
|
|
@@ -1341,4 +1342,4 @@ async function configureEnvFile(targetDirectory, databaseUrl) {
|
|
|
1341
1342
|
//#endregion
|
|
1342
1343
|
export { createRebaseApp };
|
|
1343
1344
|
|
|
1344
|
-
//# sourceMappingURL=init-
|
|
1345
|
+
//# sourceMappingURL=init-BWAwHPtz.js.map
|