@rebasepro/cli 0.25.0 → 0.26.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/README.md +2 -1
- package/bin/rebase.js +143 -4
- package/dist/{agent-setup-B5AKHOgt.js → agent-setup-D9mHRZ5R.js} +125 -3
- package/dist/agent-setup-D9mHRZ5R.js.map +1 -0
- package/dist/{api-keys-Tm7zvAPe.js → api-keys-CyJ26KEJ.js} +41 -10
- package/dist/api-keys-CyJ26KEJ.js.map +1 -0
- package/dist/{apps-BsU_ILbP.js → apps-CnLDV5b6.js} +6 -7
- package/dist/{apps-BsU_ILbP.js.map → apps-CnLDV5b6.js.map} +1 -1
- package/dist/{atlas-dev-database-OWtqnG7W.js → atlas-dev-database-BODqdCWt.js} +4 -4
- package/dist/{atlas-dev-database-OWtqnG7W.js.map → atlas-dev-database-BODqdCWt.js.map} +1 -1
- package/dist/{auth-Vl2hFKXP.js → auth-dII2jCO1.js} +10 -8
- package/dist/auth-dII2jCO1.js.map +1 -0
- package/dist/{branch-pointer-9DnwkFJJ.js → branch-pointer-BQUF6lYa.js} +1 -1
- package/dist/{build-BBgT8EJZ.js → build-Cza7ZQrp.js} +6 -7
- package/dist/{build-BBgT8EJZ.js.map → build-Cza7ZQrp.js.map} +1 -1
- package/dist/{bundle-DtCCCr4w.js → bundle-C6yEtMJ-.js} +53 -5
- package/dist/bundle-C6yEtMJ-.js.map +1 -0
- package/dist/bundle.d.ts +14 -0
- package/dist/{cloud-BpH0_bmV.js → cloud-BdnmqQaZ.js} +8528 -4342
- package/dist/cloud-BdnmqQaZ.js.map +1 -0
- package/dist/collections-dir-DlvDhime.js +69 -0
- package/dist/collections-dir-DlvDhime.js.map +1 -0
- package/dist/commands/agent-setup.d.ts +58 -0
- package/dist/commands/api-keys.d.ts +13 -0
- package/dist/commands/cloud/activity.d.ts +25 -0
- package/dist/commands/cloud/app-key.d.ts +18 -0
- package/dist/commands/cloud/auth.d.ts +1 -0
- package/dist/commands/cloud/billing-invoices.d.ts +39 -0
- package/dist/commands/cloud/claim.d.ts +7 -0
- package/dist/commands/cloud/context.d.ts +115 -6
- package/dist/commands/cloud/deploy-summary.d.ts +162 -0
- package/dist/commands/cloud/deploy.d.ts +64 -0
- package/dist/commands/cloud/env.d.ts +24 -0
- package/dist/commands/cloud/index.d.ts +13 -1
- package/dist/commands/cloud/init.d.ts +143 -0
- package/dist/commands/cloud/login-flow.d.ts +51 -0
- package/dist/commands/cloud/notifications.d.ts +28 -0
- package/dist/commands/cloud/orgs.d.ts +13 -0
- package/dist/commands/cloud/previews.d.ts +123 -0
- package/dist/commands/cloud/resources.d.ts +68 -14
- package/dist/commands/cloud/runtime-logs.d.ts +176 -0
- package/dist/commands/cloud/service-key.d.ts +15 -0
- package/dist/commands/cloud/token-capabilities.d.ts +61 -8
- package/dist/commands/cloud/tokens.d.ts +18 -3
- package/dist/commands/cloud/usage.d.ts +63 -0
- package/dist/commands/dev.d.ts +22 -0
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/generate-view.d.ts +94 -0
- package/dist/commands/generate_sdk.d.ts +19 -2
- package/dist/commands/init.d.ts +20 -0
- package/dist/commands/skills.d.ts +4 -3
- package/dist/commands/start.d.ts +10 -0
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/upgrade.d.ts +12 -0
- package/dist/commands/verify.d.ts +96 -0
- package/dist/{consent-ClRHmcxf.js → consent-BD7F29T3.js} +2 -2
- package/dist/{consent-ClRHmcxf.js.map → consent-BD7F29T3.js.map} +1 -1
- package/dist/{console-CEGm0XNc.js → console-BXB6-8GT.js} +12 -6
- package/dist/console-BXB6-8GT.js.map +1 -0
- package/dist/{context-CyflUrKg.js → context-GUxkZm-S.js} +482 -26
- package/dist/context-GUxkZm-S.js.map +1 -0
- package/dist/{daemon-CknkDjd6.js → daemon-Cp7oNXth.js} +160 -5
- package/dist/daemon-Cp7oNXth.js.map +1 -0
- package/dist/{daemon-entry-CbLRrgzy.js → daemon-entry-zOC1revO.js} +6 -3
- package/dist/daemon-entry-zOC1revO.js.map +1 -0
- package/dist/{db-CRNpA5mH.js → db-KzlqddGD.js} +101 -54
- package/dist/db-KzlqddGD.js.map +1 -0
- package/dist/{derive-CsoFGAnK.js → derive-ae9UOoOB.js} +2 -2
- package/dist/{derive-CsoFGAnK.js.map → derive-ae9UOoOB.js.map} +1 -1
- package/dist/{dev-C0pbMmhS.js → dev-DTqVMgB3.js} +231 -44
- package/dist/dev-DTqVMgB3.js.map +1 -0
- package/dist/dev-db/daemon.d.ts +41 -0
- package/dist/dev-db/pull.d.ts +33 -5
- package/dist/dev-db/state.d.ts +9 -0
- package/dist/{dev-preflight-unHpiYO1.js → dev-preflight-Cxv3TiD1.js} +73 -27
- package/dist/dev-preflight-Cxv3TiD1.js.map +1 -0
- package/dist/{dev-server-B1UYifZJ.js → dev-server-OJsUGZEB.js} +14 -3
- package/dist/dev-server-OJsUGZEB.js.map +1 -0
- package/dist/{doctor-CATRdWm6.js → doctor-BRWOlqeG.js} +14 -12
- package/dist/doctor-BRWOlqeG.js.map +1 -0
- package/dist/{eject-DuasTr-F.js → eject-DABcDnPN.js} +3 -4
- package/dist/{eject-DuasTr-F.js.map → eject-DABcDnPN.js.map} +1 -1
- package/dist/{fold-static-hDHtDfTq.js → fold-static-BnAK-anQ.js} +3 -3
- package/dist/{fold-static-hDHtDfTq.js.map → fold-static-BnAK-anQ.js.map} +1 -1
- package/dist/generate-view-IFwCADvb.js +662 -0
- package/dist/generate-view-IFwCADvb.js.map +1 -0
- package/dist/{generate_sdk-Cvg5jjJF.js → generate_sdk-BvcWvoUh.js} +49 -13
- package/dist/generate_sdk-BvcWvoUh.js.map +1 -0
- package/dist/index.es.js +58 -40
- package/dist/index.es.js.map +1 -1
- package/dist/{init-BWAwHPtz.js → init-CaU6GhwI.js} +50 -62
- package/dist/init-CaU6GhwI.js.map +1 -0
- package/dist/invoked-command-CG_rIa_o.js +55 -0
- package/dist/invoked-command-CG_rIa_o.js.map +1 -0
- package/dist/last-dev-database-DpW5dfoX.js +2 -0
- package/dist/{manifest-DRp0UVTj.js → manifest-BtzDy7KQ.js} +36 -3
- package/dist/{manifest-DRp0UVTj.js.map → manifest-BtzDy7KQ.js.map} +1 -1
- package/dist/{normalize-imports-BoBVh5tU.js → normalize-imports-D0zXlM6g.js} +3 -3
- package/dist/{normalize-imports-BoBVh5tU.js.map → normalize-imports-D0zXlM6g.js.map} +1 -1
- package/dist/{path-flags-BFgG9V6y.js → path-flags-DNvtEi2-.js} +5 -4
- package/dist/path-flags-DNvtEi2-.js.map +1 -0
- package/dist/{prepare-DdnU70z8.js → prepare-CTw9NEkh.js} +5 -4
- package/dist/{prepare-DdnU70z8.js.map → prepare-CTw9NEkh.js.map} +1 -1
- package/dist/project-CasK56vN.js +701 -0
- package/dist/project-CasK56vN.js.map +1 -0
- package/dist/{pull-C3PXduzl.js → pull-DDMpsZ5r.js} +131 -24
- package/dist/pull-DDMpsZ5r.js.map +1 -0
- package/dist/refusal-ReeeGP8a.js +26 -0
- package/dist/refusal-ReeeGP8a.js.map +1 -0
- package/dist/resolve-D647F1LA.js +2 -0
- package/dist/{resources-BdNRDEAy.js → resources-CPSC5Kcu.js} +4 -5
- package/dist/{resources-BdNRDEAy.js.map → resources-CPSC5Kcu.js.map} +1 -1
- package/dist/{schema-B0-p6T1O.js → schema-BSXwZSiI.js} +9 -8
- package/dist/schema-BSXwZSiI.js.map +1 -0
- package/dist/{skills-DfnTeyRz.js → skills-BU2flMOy.js} +52 -8
- package/dist/skills-BU2flMOy.js.map +1 -0
- package/dist/{start-BmEZkS0n.js → start-mVb6upwY.js} +20 -7
- package/dist/start-mVb6upwY.js.map +1 -0
- package/dist/{state-CCB-FAQ9.js → state-CYdBvnwA.js} +3 -2
- package/dist/state-CYdBvnwA.js.map +1 -0
- package/dist/static-syntax-check.d.ts +64 -0
- package/dist/{status-BJ26yZOo.js → status-BREvtzJm.js} +8 -9
- package/dist/{status-BJ26yZOo.js.map → status-BREvtzJm.js.map} +1 -1
- package/dist/{storage-DKPUBTWG.js → storage-DtOXGflp.js} +159 -16
- package/dist/storage-DtOXGflp.js.map +1 -0
- package/dist/{telemetry-EMFRVRQi.js → telemetry-CgwJPVMO.js} +2 -2
- package/dist/{telemetry-EMFRVRQi.js.map → telemetry-CgwJPVMO.js.map} +1 -1
- package/dist/{telemetry-m9czTNGR.js → telemetry-DwK5RQJl.js} +4 -4
- package/dist/{telemetry-m9czTNGR.js.map → telemetry-DwK5RQJl.js.map} +1 -1
- package/dist/{upgrade-DjihWuZL.js → upgrade-B7sVwL8S.js} +26 -4
- package/dist/{upgrade-DjihWuZL.js.map → upgrade-B7sVwL8S.js.map} +1 -1
- package/dist/utils/args.d.ts +32 -3
- package/dist/utils/boot-retry.d.ts +41 -0
- package/dist/utils/collections-dir.d.ts +14 -0
- package/dist/utils/dev-preflight.d.ts +34 -1
- package/dist/utils/dev-server.d.ts +11 -0
- package/dist/utils/path-flags.d.ts +2 -1
- package/dist/utils/project.d.ts +5 -1
- package/dist/utils/tool-stdio.d.ts +1 -1
- package/dist/utils/unknown-command.d.ts +4 -0
- package/dist/verify-D7UsV_qe.js +730 -0
- package/dist/verify-D7UsV_qe.js.map +1 -0
- package/package.json +9 -7
- package/templates/eject/backend/src/index.ts +9 -1
- package/templates/generated-schemas/ecommerce.ts +3 -0
- package/templates/overlays/baas/ai-instructions.md +13 -0
- package/templates/resource-graphs/blank.json +25 -0
- package/templates/resource-graphs/blog.json +28 -0
- package/templates/resource-graphs/ecommerce.json +28 -0
- package/templates/resource-graphs/headless.json +22 -0
- package/templates/template/.claude/hooks/post-edit-collection.sh +99 -0
- package/templates/template/.claude/settings.json +17 -0
- package/templates/template/.env.example +15 -5
- package/templates/template/ai-instructions.md +21 -1
- package/templates/template/config/collections/presets/ecommerce/index.ts +23 -0
- package/templates/template/docker-compose.yml +4 -1
- package/templates/template/frontend/package.json +1 -0
- package/templates/template/frontend/src/App.tsx +10 -9
- package/templates/views/AppView.tsx.tmpl +138 -0
- package/templates/views/EntityView.tsx.tmpl +64 -0
- package/templates/views/index.ts.tmpl +8 -0
- package/dist/agent-setup-B5AKHOgt.js.map +0 -1
- package/dist/api-keys-Tm7zvAPe.js.map +0 -1
- package/dist/args-BX0YD14a.js +0 -266
- package/dist/args-BX0YD14a.js.map +0 -1
- package/dist/auth-Vl2hFKXP.js.map +0 -1
- package/dist/bundle-DtCCCr4w.js.map +0 -1
- package/dist/cloud-BpH0_bmV.js.map +0 -1
- package/dist/console-CEGm0XNc.js.map +0 -1
- package/dist/context-CyflUrKg.js.map +0 -1
- package/dist/daemon-CknkDjd6.js.map +0 -1
- package/dist/daemon-entry-CbLRrgzy.js.map +0 -1
- package/dist/db-CRNpA5mH.js.map +0 -1
- package/dist/dev-C0pbMmhS.js.map +0 -1
- package/dist/dev-preflight-unHpiYO1.js.map +0 -1
- package/dist/dev-server-B1UYifZJ.js.map +0 -1
- package/dist/doctor-CATRdWm6.js.map +0 -1
- package/dist/generate_sdk-Cvg5jjJF.js.map +0 -1
- package/dist/init-BWAwHPtz.js.map +0 -1
- package/dist/last-dev-database-c_dKz1S3.js +0 -2
- package/dist/path-flags-BFgG9V6y.js.map +0 -1
- package/dist/project-Wp2zoyeN.js +0 -349
- package/dist/project-Wp2zoyeN.js.map +0 -1
- package/dist/pull-C3PXduzl.js.map +0 -1
- package/dist/resolve-CNQjsatH.js +0 -2
- package/dist/schema-B0-p6T1O.js.map +0 -1
- package/dist/skills-DfnTeyRz.js.map +0 -1
- package/dist/start-BmEZkS0n.js.map +0 -1
- package/dist/state-CCB-FAQ9.js.map +0 -1
- package/dist/storage-DKPUBTWG.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-view-IFwCADvb.js","names":[],"sources":["../src/commands/generate-view.ts"],"sourcesContent":["/**\n * `rebase generate view <slug>` — scaffold a custom admin screen and register it.\n *\n * Most back-office screens are a table, a form or a board, and the admin draws\n * those from the collection. The rest — a dispatch board, a reconciliation\n * screen, a record's audit trail — are a hundred lines of React. Written inside\n * the admin they inherit the sign-in, the security rules, the sidebar, the UI\n * kit and the data layer; written as a separate app they have to rebuild every\n * one of those. This command writes the first version of that file where the\n * admin will find it, so the screen starts native and registered.\n *\n * Two places, one file each:\n *\n * - **A screen** (default): `<frontend>/src/views/<Name>View.tsx`, listed in\n * `<frontend>/src/views/index.ts` as an `AppView`, which `App.tsx` hands to\n * `<RebaseCMS views>`. The first run wires `App.tsx`; later runs only append\n * to the list.\n * - **A record tab** (`--collection <slug>`): the same file location, with a\n * component that takes `EntityCustomViewParams`, added to that collection's\n * `admin.entityViews` *by path*. The collection file is shared with the\n * backend, and a path is the one form of component reference the backend\n * never evaluates — the admin's Vite plugin turns it into a lazy import.\n *\n * The frontend is where `rebase.json` says the CMS is (the static app with a\n * `cms` mount), which is `frontend/` in everything `rebase init` writes. A\n * project with no admin panel (`rebase init --headless`) is refused: there is\n * nowhere for a view to render.\n *\n * Edits to existing files are textual and conservative. When `App.tsx` already\n * passes its own `views`, or a collection's shape is not one this can read, the\n * view file is still written and the command prints the one line to add by\n * hand instead of guessing.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\nimport chalk from \"chalk\";\n\nimport { cmsMountOf, loadManifest } from \"../manifest\";\nimport { resolveCollectionsDir } from \"../utils/collections-dir\";\nimport { requireProjectRoot } from \"../utils/project\";\nimport { parseCommandArgs, UsageError, wantsHelp } from \"../utils/args\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/** What `rebase generate` dispatches. Read by `cli.ts` to name the subcommand. */\nexport const GENERATE_SUBCOMMANDS = [\"view\"] as const;\n\nconst VIEW_FLAGS = {\n \"--collection\": String,\n \"--name\": String,\n \"--icon\": String,\n \"--dry-run\": Boolean,\n \"--force\": Boolean\n} as const;\n\n/** A slug is a URL segment and an entity view key: kebab-case, starting with a letter. */\nconst SLUG_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;\n\n/**\n * Top-level paths the admin's own routes answer (`RebaseRouteDefs` in\n * `@rebasepro/cms`): `/c/*` the collections, `/s` Studio, `/settings`. They are\n * declared before custom views, so a screen at one of them was listed in the\n * sidebar and opened the built-in page instead.\n */\nconst RESERVED_SCREEN_SLUGS: readonly string[] = [\"c\", \"s\", \"settings\"];\n\nexport interface GenerateViewOptions {\n projectRoot: string;\n slug: string;\n /** Register as a tab on this collection's records instead of as a screen. */\n collection?: string;\n /** The label in the sidebar or on the tab. Defaults to the slug in sentence case. */\n name?: string;\n /** A Lucide icon name for the sidebar. Screens only. */\n icon?: string;\n /** Replace an existing view file. Registration is never duplicated. */\n force?: boolean;\n}\n\nexport interface PlannedFile {\n /** Absolute path. */\n path: string;\n contents: string;\n action: \"create\" | \"update\" | \"replace\";\n}\n\nexport interface GenerateViewPlan {\n kind: \"app\" | \"entity\";\n componentName: string;\n viewFile: string;\n files: PlannedFile[];\n /** Steps the command could not take itself, as sentences to print. */\n manualSteps: string[];\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Names\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** `orders-board` → `OrdersBoardView`; `sales-view` → `SalesView`, not `SalesViewView`. */\nexport function viewComponentName(slug: string): string {\n const pascal = slug.split(\"-\").map(part => part.charAt(0).toUpperCase() + part.slice(1)).join(\"\");\n return pascal.endsWith(\"View\") ? pascal : `${pascal}View`;\n}\n\n/** `orders-board` → `Orders board`: labels are sentence case in the admin. */\nexport function viewLabel(slug: string): string {\n const words = slug.split(\"-\").join(\" \");\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Reading source without a parser\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * The source with every string, template literal, regular expression and\n * comment blanked out, character for character, so brackets and keys can be\n * found by position without being fooled by a `{` inside a string. String\n * contents become `_` (they are still \"something\"), comments become spaces.\n *\n * Exported for its tests.\n */\nexport function maskCode(source: string): string {\n const out = source.split(\"\");\n let i = 0;\n const blank = (from: number, to: number, fill: string) => {\n for (let k = from; k < to; k++) if (out[k] !== \"\\n\") out[k] = fill;\n };\n const previousSignificant = (at: number): string => {\n for (let k = at - 1; k >= 0; k--) {\n const ch = out[k];\n if (ch !== \" \" && ch !== \"\\t\" && ch !== \"\\n\" && ch !== \"\\r\") return ch;\n }\n return \"\";\n };\n while (i < source.length) {\n const ch = source[i];\n const next = source[i + 1];\n if (ch === \"/\" && next === \"/\") {\n const end = source.indexOf(\"\\n\", i);\n const stop = end === -1 ? source.length : end;\n blank(i, stop, \" \");\n i = stop;\n } else if (ch === \"/\" && next === \"*\") {\n const end = source.indexOf(\"*/\", i + 2);\n const stop = end === -1 ? source.length : end + 2;\n blank(i, stop, \" \");\n i = stop;\n } else if (ch === \"\\\"\" || ch === \"'\" || ch === \"`\") {\n let k = i + 1;\n while (k < source.length && source[k] !== ch) {\n if (source[k] === \"\\\\\") k++;\n k++;\n }\n blank(i + 1, k, \"_\");\n i = k + 1;\n } else if (ch === \"/\" && (previousSignificant(i) === \"\" || \"(,=:[!&|?{;\".includes(previousSignificant(i)))) {\n // A regular expression literal: `/` where a value is expected. Not\n // after `}`, which in a .tsx file is far more often `{value}/>`.\n let k = i + 1;\n let inClass = false;\n while (k < source.length && source[k] !== \"\\n\") {\n if (source[k] === \"\\\\\") k++;\n else if (source[k] === \"[\") inClass = true;\n else if (source[k] === \"]\") inClass = false;\n else if (source[k] === \"/\" && !inClass) break;\n k++;\n }\n blank(i + 1, k, \"_\");\n i = k + 1;\n } else {\n i++;\n }\n }\n return out.join(\"\");\n}\n\nconst CLOSERS: Record<string, string> = { \"{\": \"}\", \"[\": \"]\", \"(\": \")\" };\n\n/** The index of the bracket closing the one at `open`, in masked source. */\nfunction matchClose(masked: string, open: number): number {\n const stack: string[] = [];\n for (let i = open; i < masked.length; i++) {\n const ch = masked[i];\n if (ch in CLOSERS) stack.push(CLOSERS[ch]);\n else if (ch === \"}\" || ch === \"]\" || ch === \")\") {\n if (stack.pop() !== ch) return -1;\n if (stack.length === 0) return i;\n }\n }\n return -1;\n}\n\n/** The index of the innermost `{` still open at `at`, in masked source. */\nfunction enclosingBrace(masked: string, at: number): number {\n const stack: number[] = [];\n for (let i = 0; i < at; i++) {\n const ch = masked[i];\n if (ch === \"{\" || ch === \"[\" || ch === \"(\") stack.push(i);\n else if (ch === \"}\" || ch === \"]\" || ch === \")\") stack.pop();\n }\n for (let k = stack.length - 1; k >= 0; k--) {\n if (masked[stack[k]] === \"{\") return stack[k];\n }\n return -1;\n}\n\n/**\n * The position of `key:` as a direct property of the object whose `{` is at\n * `open`, followed by `opener` (`{` or `[`) — or -1.\n */\nfunction directProperty(masked: string, open: number, key: string, opener: \"{\" | \"[\"): { keyAt: number; valueOpen: number } | undefined {\n const close = matchClose(masked, open);\n if (close === -1) return undefined;\n const pattern = new RegExp(`(^|[\\\\s,{])${key}\\\\s*:\\\\s*\\\\${opener}`, \"g\");\n const body = masked.slice(open + 1, close);\n for (const match of body.matchAll(pattern)) {\n const keyAt = open + 1 + (match.index ?? 0) + match[1].length;\n if (enclosingBrace(masked, keyAt) !== open) continue;\n return { keyAt, valueOpen: open + 1 + (match.index ?? 0) + match[0].length - 1 };\n }\n return undefined;\n}\n\nfunction lineStart(source: string, at: number): number {\n return source.lastIndexOf(\"\\n\", at - 1) + 1;\n}\n\nfunction indentAt(source: string, at: number): string {\n const start = lineStart(source, at);\n return /^[ \\t]*/.exec(source.slice(start))?.[0] ?? \"\";\n}\n\n/**\n * The indentation step a file uses: the smallest non-zero leading run of\n * spaces, not counting the ` * ` lines of a block comment.\n */\nfunction indentUnit(source: string): string {\n if (/^\\t/m.test(source)) return \"\\t\";\n let unit = Infinity;\n for (const match of source.matchAll(/^( +)[^\\s*]/gm)) unit = Math.min(unit, match[1].length);\n return \" \".repeat(Number.isFinite(unit) ? unit : 4);\n}\n\nfunction reindent(block: string, indent: string): string {\n return block.split(\"\\n\").map(line => (line ? indent + line : line)).join(\"\\n\");\n}\n\n/**\n * Insert `element` (already indented one level past `indent`) as the last item\n * of the array whose `[` is at `open`.\n */\nfunction appendToArray(source: string, masked: string, open: number, element: string): string {\n const close = matchClose(masked, open);\n const inner = masked.slice(open + 1, close);\n const indent = indentAt(source, open);\n if (inner.trim() === \"\") {\n return `${source.slice(0, open + 1)}\\n${element}\\n${indent}${source.slice(close)}`;\n }\n // After the last non-blank character of the content, keeping any comment\n // after it where it was.\n let last = close - 1;\n while (last > open && /\\s/.test(masked[last])) last--;\n const hasTrailingComma = masked[last] === \",\";\n const insertAt = last + 1;\n return `${source.slice(0, insertAt)}${hasTrailingComma ? \"\" : \",\"}\\n${element}${source.slice(insertAt)}`;\n}\n\n/** Add an import line after the file's last import statement. */\nfunction addImport(source: string, line: string): string {\n const masked = maskCode(source);\n let end = 0;\n for (const match of masked.matchAll(/^import\\b[\\s\\S]*?[\"'][^\"'\\n]*[\"'];?[ \\t]*$/gm)) {\n end = (match.index ?? 0) + match[0].length;\n }\n if (end === 0) return `${line}\\n${source}`;\n return `${source.slice(0, end)}\\n${line}${source.slice(end)}`;\n}\n\n/** A path import from `fromDir` to `toFile`, without extension, always starting with `.`. */\nfunction relativeImport(fromDir: string, toFile: string): string {\n const relative = path.relative(fromDir, toFile).split(path.sep).join(\"/\").replace(/\\.tsx?$/, \"\");\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Where things are\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The admin's frontend directory: the static app that mounts the CMS, or `frontend/`. */\nexport function resolveFrontendDir(projectRoot: string): string | undefined {\n try {\n const cms = cmsMountOf(loadManifest(projectRoot).manifest);\n if (cms) return path.join(projectRoot, cms.app.root);\n } catch {\n // A malformed rebase.json is reported by the commands that own it.\n }\n const fallback = path.join(projectRoot, \"frontend\");\n return fs.existsSync(path.join(fallback, \"src\")) ? fallback : undefined;\n}\n\n/** `<config>/collections`, as the backend app declares it — one resolver for every command. */\nexport { resolveCollectionsDir };\n\nfunction collectionFiles(dir: string): string[] {\n if (!fs.existsSync(dir)) return [];\n const out: string[] = [];\n const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== \"node_modules\" && entry.name !== \"presets\") out.push(...collectionFiles(full));\n } else if (/\\.tsx?$/.test(entry.name) && !/\\.(test|spec|d)\\.tsx?$/.test(entry.name)) {\n out.push(full);\n }\n }\n return out;\n}\n\nconst SLUG_PROPERTY = /(^|[\\s,{])slug\\s*:\\s*([\"'])([^\"'\\n]+)\\2/g;\n\n/** Every `slug: \"…\"` a collection file declares, with where. */\nfunction declaredSlugs(dir: string): { slug: string; file: string; at: number }[] {\n const found: { slug: string; file: string; at: number }[] = [];\n for (const file of collectionFiles(dir)) {\n const source = fs.readFileSync(file, \"utf8\");\n const masked = maskCode(source);\n for (const match of source.matchAll(SLUG_PROPERTY)) {\n const at = (match.index ?? 0) + match[1].length;\n if (masked[at] !== \"s\") continue; // inside a comment or a string\n found.push({ slug: match[3], file, at });\n }\n }\n return found;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// The files\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * The scaffolds live in `templates/views/` rather than in template literals\n * here: they import React and the admin packages, and this package's sources\n * must not name those, even inside a string (`pnpm check:types-headless`).\n */\nfunction viewTemplate(name: string): string {\n const cliRoot = findCliRoot(__dirname);\n if (!cliRoot) throw new Error(`The CLI's templates/views folder is missing from ${__dirname}.`);\n return fs.readFileSync(path.join(cliRoot, \"templates\", \"views\", name), \"utf8\");\n}\n\n/** Walk up to the package root, which holds `templates/views`. */\nfunction findCliRoot(from: string): string | null {\n const root = path.parse(from).root;\n let dir = from;\n while (dir && dir !== root) {\n if (fs.existsSync(path.join(dir, \"templates\", \"views\"))) return dir;\n dir = path.dirname(dir);\n }\n return null;\n}\n\ntype ViewTemplateOptions = { slug: string; componentName: string; label: string; collection: string };\n\n/**\n * A label as JSX text: written as is when it is plain, as a string expression\n * when it holds a character JSX reads — `{`, `}`, `<`, `>`, `&`. Pasted raw,\n * `--name \"KPIs {beta}\"` wrote `<Typography>KPIs {beta}</Typography>`, and the\n * view did not compile (\"Cannot find name 'beta'\").\n */\nfunction jsxText(text: string): string {\n return /[{}<>&]/.test(text) ? `{${JSON.stringify(text)}}` : text;\n}\n\n/** A label inside the leading `/** … *\\/` comment: one line, and no `*\\/` to close it early. */\nfunction commentText(text: string): string {\n return text.replace(/[\\r\\n]+/g, \" \").replaceAll(\"*/\", \"*\\\\/\");\n}\n\nfunction fillViewTemplate(template: string, options: ViewTemplateOptions): string {\n const { slug, componentName, label, collection } = options;\n return template\n .replaceAll(\"\\\"__COLLECTION__\\\"\", JSON.stringify(collection))\n .replaceAll(\"__COLLECTION__\", collection)\n .replaceAll(\"__COMPONENT__\", componentName)\n .replaceAll(\"__label_jsx__\", jsxText(label.toLowerCase()))\n .replaceAll(\"__LABEL_JSX__\", jsxText(label))\n .replaceAll(\"__label__\", commentText(label.toLowerCase()))\n .replaceAll(\"__LABEL__\", commentText(label))\n .replaceAll(\"__SLUG__\", slug);\n}\n\nexport function appViewSource(options: ViewTemplateOptions): string {\n return fillViewTemplate(viewTemplate(\"AppView.tsx.tmpl\"), options);\n}\n\nexport function entityViewSource(options: ViewTemplateOptions): string {\n return fillViewTemplate(viewTemplate(\"EntityView.tsx.tmpl\"), options);\n}\n\nfunction viewsIndexHeader(): string {\n return viewTemplate(\"index.ts.tmpl\");\n}\n\nfunction appViewEntry(options: { slug: string; label: string; icon: string; componentName: string }, unit: string): string {\n return [\n \"{\",\n `${unit}slug: ${JSON.stringify(options.slug)},`,\n `${unit}name: ${JSON.stringify(options.label)},`,\n `${unit}icon: ${JSON.stringify(options.icon)},`,\n `${unit}view: ${options.componentName}`,\n \"}\"\n ].join(\"\\n\");\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Planning\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction readIfExists(file: string): string | undefined {\n return fs.existsSync(file) ? fs.readFileSync(file, \"utf8\") : undefined;\n}\n\n/**\n * The frontend's package.json gains `@rebasepro/cms-types` when it lacks it.\n *\n * The view files import their prop types from it, and under pnpm a package the\n * frontend does not declare does not resolve from the frontend — the frontend's\n * `tsc` would fail on the first generated view. The version is the one the\n * frontend already uses for `@rebasepro/cms`, so the two cannot drift.\n */\nfunction planCmsTypesDependency(frontendDir: string, files: PlannedFile[], manualSteps: string[]): void {\n const manifestFile = path.join(frontendDir, \"package.json\");\n const raw = readIfExists(manifestFile);\n if (raw === undefined) return;\n let manifest: { dependencies?: Record<string, string>; devDependencies?: Record<string, string> };\n try {\n manifest = JSON.parse(raw);\n } catch {\n return;\n }\n const declared = { ...manifest.devDependencies, ...manifest.dependencies };\n if (declared[\"@rebasepro/cms-types\"]) return;\n const version = declared[\"@rebasepro/cms\"] ?? declared[\"@rebasepro/app\"];\n if (!version) return;\n const dependencies = { ...manifest.dependencies, \"@rebasepro/cms-types\": version };\n const sorted = Object.fromEntries(Object.entries(dependencies).sort(([a], [b]) => a.localeCompare(b)));\n const indent = /^(\\s+)\"/m.exec(raw)?.[1] ?? \" \";\n files.push({\n path: manifestFile,\n contents: `${JSON.stringify({ ...manifest, dependencies: sorted }, null, indent)}\\n`,\n action: \"update\"\n });\n manualSteps.push(`Run your package manager's install: ${path.basename(frontendDir)}/package.json now depends on @rebasepro/cms-types, which the view imports its types from.`);\n}\n\nfunction defaultCollectionFor(projectRoot: string): string {\n const slugs = declaredSlugs(resolveCollectionsDir(projectRoot)).map(entry => entry.slug);\n return slugs.find(slug => slug !== \"users\") ?? slugs[0] ?? \"users\";\n}\n\n/**\n * Everything `rebase generate view` would write, without writing it.\n *\n * @throws UsageError when the slug is not a slug, there is no admin panel, the\n * view already exists (without `force`), or `--collection` names nothing.\n */\nexport function planGenerateView(options: GenerateViewOptions): GenerateViewPlan {\n const { projectRoot, slug } = options;\n if (!SLUG_PATTERN.test(slug)) {\n throw new UsageError(\n `\"${slug}\" is not a view slug: use lowercase letters, digits and dashes, starting with a letter (e.g. orders-board).`\n );\n }\n if (!options.collection && RESERVED_SCREEN_SLUGS.includes(slug)) {\n throw new UsageError(\n `\"${slug}\" is reserved: the admin's own routes answer /${slug}, so a screen there would never show. ` +\n `Pick another slug (e.g. ${slug === \"settings\" ? \"app-settings\" : `${slug}-view`}).`\n );\n }\n const frontendDir = resolveFrontendDir(projectRoot);\n if (!frontendDir) {\n throw new UsageError(\n \"This project has no admin panel to add a view to: rebase.json declares no app with a `cms` mount, and there is no frontend/src. \" +\n \"A project created with `rebase init --headless` has no admin.\"\n );\n }\n\n const componentName = viewComponentName(slug);\n const label = options.name?.trim() || viewLabel(slug);\n const viewsDir = path.join(frontendDir, \"src\", \"views\");\n const viewFile = path.join(viewsDir, `${componentName}.tsx`);\n const files: PlannedFile[] = [];\n const manualSteps: string[] = [];\n\n const viewExists = fs.existsSync(viewFile);\n if (viewExists && !options.force) {\n throw new UsageError(\n `${path.relative(projectRoot, viewFile)} already exists. Pass --force to replace it; its registration is kept.`\n );\n }\n const viewAction: PlannedFile[\"action\"] = viewExists ? \"replace\" : \"create\";\n\n if (options.collection) {\n const kind = \"entity\" as const;\n const collectionsDir = resolveCollectionsDir(projectRoot);\n const declared = declaredSlugs(collectionsDir);\n const matches = declared.filter(entry => entry.slug === options.collection);\n if (matches.length === 0) {\n const known = [...new Set(declared.map(entry => entry.slug))].sort();\n throw new UsageError(\n `No collection with slug \"${options.collection}\" under ${path.relative(projectRoot, collectionsDir) || \".\"}.` +\n (known.length ? ` Declared: ${known.join(\", \")}.` : \"\")\n );\n }\n if (matches.length > 1) {\n throw new UsageError(\n `More than one collection declares slug \"${options.collection}\": ` +\n `${matches.map(entry => path.relative(projectRoot, entry.file)).join(\", \")}.`\n );\n }\n const [{ file: collectionFile, at: slugAt }] = matches;\n\n files.push({\n path: viewFile,\n contents: entityViewSource({ slug, componentName, label, collection: options.collection }),\n action: viewAction\n });\n\n const builder = relativeImport(path.dirname(collectionFile), viewFile);\n const source = fs.readFileSync(collectionFile, \"utf8\");\n const updated = registerEntityView(source, slugAt, { key: slug, name: label, builder });\n const where = `${path.relative(projectRoot, collectionFile)}`;\n if (updated === \"already\") {\n // Registered on an earlier run: --force replaced the file only.\n } else if (updated === undefined) {\n manualSteps.push(\n `Add this to admin.entityViews in ${where}: { key: ${JSON.stringify(slug)}, name: ${JSON.stringify(label)}, Builder: ${JSON.stringify(builder)} }`\n );\n } else {\n files.push({ path: collectionFile, contents: updated, action: \"update\" });\n }\n planCmsTypesDependency(frontendDir, files, manualSteps);\n return { kind, componentName, viewFile, files, manualSteps };\n }\n\n files.push({\n path: viewFile,\n contents: appViewSource({ slug, componentName, label, collection: defaultCollectionFor(projectRoot) }),\n action: viewAction\n });\n\n // The list of screens.\n const indexFile = path.join(viewsDir, \"index.ts\");\n const existingIndex = readIfExists(indexFile);\n const icon = options.icon ?? \"LayoutDashboard\";\n if (existingIndex === undefined) {\n const unit = \" \";\n files.push({\n path: indexFile,\n contents: `${viewsIndexHeader()}import { ${componentName} } from \"./${componentName}\";\\n\\n` +\n `export const views: AppView[] = [\\n${reindent(appViewEntry({ slug, label, icon, componentName }, unit), unit)}\\n];\\n`,\n action: \"create\"\n });\n } else {\n const updated = registerAppView(existingIndex, { slug, label, icon, componentName });\n if (updated === undefined) {\n manualSteps.push(\n `Add { slug: ${JSON.stringify(slug)}, name: ${JSON.stringify(label)}, view: ${componentName} } to the views in ${path.relative(projectRoot, indexFile)}.`\n );\n } else if (updated !== \"already\") {\n files.push({ path: indexFile, contents: updated, action: \"update\" });\n }\n }\n\n // App.tsx hands the list to <RebaseCMS>, once.\n const appFile = path.join(frontendDir, \"src\", \"App.tsx\");\n const app = readIfExists(appFile);\n const wired = app === undefined ? undefined : wireViewsIntoApp(app);\n if (wired === undefined) {\n manualSteps.push(\n `Pass the screens to the admin: import { views } from \"./views\" and add views={views} to <RebaseCMS> in ${path.relative(projectRoot, appFile)}` +\n \" (or spread ...views into the views it already passes).\"\n );\n } else if (wired !== \"already\") {\n files.push({ path: appFile, contents: wired, action: \"update\" });\n }\n\n planCmsTypesDependency(frontendDir, files, manualSteps);\n return { kind: \"app\", componentName, viewFile, files, manualSteps };\n}\n\n/**\n * `views/index.ts` with one more entry, `\"already\"` when the slug is listed, or\n * `undefined` when the file has no `export const views … = [`.\n *\n * Exported for its tests.\n */\nexport function registerAppView(\n source: string,\n options: { slug: string; label: string; icon: string; componentName: string }\n): string | \"already\" | undefined {\n const masked = maskCode(source);\n const declaration = /export\\s+const\\s+views\\b[^=]*=\\s*\\[/.exec(masked);\n if (!declaration) return undefined;\n const open = declaration.index + declaration[0].length - 1;\n if (matchClose(masked, open) === -1) return undefined;\n const close = matchClose(masked, open);\n const listed = source.slice(open, close);\n if (new RegExp(`slug\\\\s*:\\\\s*[\"']${options.slug}[\"']`).test(listed)) return \"already\";\n\n const unit = indentUnit(source);\n const indent = indentAt(source, open) + unit;\n const element = reindent(appViewEntry(options, unit), indent);\n const appended = appendToArray(source, masked, open, element);\n return addImport(appended, `import { ${options.componentName} } from \"./${options.componentName}\";`);\n}\n\n/**\n * `App.tsx` with `views={views}` on `<RebaseCMS>` and its import, `\"already\"`\n * when it passes exactly that, or `undefined` when it cannot be done safely:\n * no `<RebaseCMS`, a `views` prop of its own, or a `views` name already in scope.\n *\n * Exported for its tests.\n */\nexport function wireViewsIntoApp(source: string): string | \"already\" | undefined {\n const masked = maskCode(source);\n const tag = /<RebaseCMS\\b/.exec(masked);\n if (!tag) return undefined;\n const tagEnd = masked.indexOf(\">\", tag.index);\n if (tagEnd === -1) return undefined;\n const attributes = masked.slice(tag.index, tagEnd);\n const importsViews = /import\\s*\\{\\s*views\\s*\\}\\s*from\\s*[\"']\\.\\/views(?:\\/index)?[\"']/.test(source);\n if (/\\sviews\\s*=/.test(attributes)) {\n return importsViews && /\\sviews\\s*=\\s*\\{\\s*views\\s*\\}/.test(attributes) ? \"already\" : undefined;\n }\n if (/\\bviews\\b/.test(masked)) return undefined;\n\n const insertAt = tag.index + \"<RebaseCMS\".length;\n const afterTag = source.slice(insertAt);\n const nextLine = /^[ \\t]*\\r?\\n([ \\t]*)\\S/.exec(afterTag);\n const attribute = nextLine ? `\\n${nextLine[1]}views={views}` : \" views={views}\";\n const withProp = source.slice(0, insertAt) + attribute + source.slice(insertAt);\n return addImport(withProp, \"import { views } from \\\"./views\\\";\");\n}\n\n/**\n * The collection file with a `{ key, name, Builder }` entry in the\n * `admin.entityViews` of the collection whose `slug:` is at `slugAt`;\n * `\"already\"` when that key is there; `undefined` when the shape cannot be read.\n *\n * Exported for its tests.\n */\nexport function registerEntityView(\n source: string,\n slugAt: number,\n view: { key: string; name: string; builder: string }\n): string | \"already\" | undefined {\n const masked = maskCode(source);\n const collectionOpen = enclosingBrace(masked, slugAt);\n if (collectionOpen === -1) return undefined;\n const unit = indentUnit(source);\n const entry = [\n \"{\",\n `${unit}key: ${JSON.stringify(view.key)},`,\n `${unit}name: ${JSON.stringify(view.name)},`,\n `${unit}Builder: ${JSON.stringify(view.builder)}`,\n \"}\"\n ].join(\"\\n\");\n\n const admin = directProperty(masked, collectionOpen, \"admin\", \"{\");\n if (admin) {\n const entityViews = directProperty(masked, admin.valueOpen, \"entityViews\", \"[\");\n if (entityViews) {\n const close = matchClose(masked, entityViews.valueOpen);\n if (close === -1) return undefined;\n const listed = source.slice(entityViews.valueOpen, close);\n if (new RegExp(`key\\\\s*:\\\\s*[\"']${view.key}[\"']|[\"']${view.key}[\"']`).test(listed)) return \"already\";\n const indent = indentAt(source, entityViews.keyAt) + unit;\n return appendToArray(source, masked, entityViews.valueOpen, reindent(entry, indent));\n }\n // `entityViews` as the first property of `admin`.\n const indent = indentAt(source, admin.keyAt) + unit;\n const block = `${indent}entityViews: [\\n${reindent(entry, indent + unit)}\\n${indent}],`;\n const adminClose = matchClose(masked, admin.valueOpen);\n const empty = masked.slice(admin.valueOpen + 1, adminClose).trim() === \"\";\n const insertAt = admin.valueOpen + 1;\n return empty\n ? `${source.slice(0, insertAt)}\\n${block.replace(/,$/, \"\")}\\n${indentAt(source, admin.keyAt)}${source.slice(adminClose)}`\n : `${source.slice(0, insertAt)}\\n${block}${source.slice(insertAt)}`;\n }\n\n // No `admin` block: one, right after the `slug` property.\n const slugLineEnd = source.indexOf(\"\\n\", slugAt);\n if (slugLineEnd === -1) return undefined;\n const slugLine = masked.slice(slugAt, slugLineEnd);\n if (!/,\\s*$/.test(slugLine)) return undefined;\n const indent = indentAt(source, slugAt);\n const block = [\n `${indent}admin: {`,\n `${indent}${unit}entityViews: [`,\n reindent(entry, indent + unit + unit),\n `${indent}${unit}]`,\n `${indent}},`\n ].join(\"\\n\");\n return `${source.slice(0, slugLineEnd + 1)}${block}\\n${source.slice(slugLineEnd + 1)}`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// The command\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction printHelp(): void {\n console.log(`\n${chalk.bold(\"rebase generate\")} — scaffold code into this project\n\n${chalk.bold(\"Usage\")}\n rebase generate view <slug> A screen of the admin, in the sidebar\n rebase generate view <slug> --collection <slug> A tab on every record of a collection\n\n${chalk.bold(\"What it writes\")}\n <frontend>/src/views/<Name>View.tsx The component, drawn with @rebasepro/ui\n <frontend>/src/views/index.ts The screens list (AppView[]), wired into\n <RebaseCMS views> in App.tsx on first run\n With --collection, the collection file instead gains an admin.entityViews\n entry that points at the component by path.\n\n${chalk.bold(\"Options\")}\n --collection <slug> Register as a record tab of this collection\n --name <label> Sidebar or tab label ${chalk.gray(\"(default: the slug in sentence case)\")}\n --icon <Lucide name> Sidebar icon for a screen ${chalk.gray(\"(default: LayoutDashboard)\")}\n --dry-run List what would change, and change nothing\n --force Replace an existing view file\n -h, --help Show this help\n`.trim());\n}\n\nexport async function generateCommand(subcommand: string | undefined, rawArgs: string[] = []): Promise<void> {\n if (subcommand === undefined || subcommand === \"--help\" || (subcommand !== \"view\" && wantsHelp(rawArgs))) {\n printHelp();\n return;\n }\n switch (subcommand) {\n case \"view\":\n await generateViewCommand(rawArgs);\n return;\n default:\n throw new UsageError(`Unknown generate command \"${subcommand}\". Available: ${GENERATE_SUBCOMMANDS.join(\", \")}. See \\`rebase generate --help\\`.`);\n }\n}\n\nasync function generateViewCommand(rawArgs: string[]): Promise<void> {\n if (wantsHelp(rawArgs)) {\n printHelp();\n return;\n }\n const { flags, positionals } = parseCommandArgs({\n spec: VIEW_FLAGS,\n rawArgs,\n commandWords: 2,\n command: \"generate view\",\n maxPositionals: 1\n });\n const slug = positionals[0];\n if (!slug) {\n throw new UsageError(\"Name the view: `rebase generate view <slug>`, e.g. `rebase generate view orders-board`.\");\n }\n if (flags[\"--icon\"] && flags[\"--collection\"]) {\n throw new UsageError(\"--icon is for a screen in the sidebar; a record tab (--collection) has no icon here.\");\n }\n\n const projectRoot = requireProjectRoot();\n const plan = planGenerateView({\n projectRoot,\n slug,\n collection: flags[\"--collection\"],\n name: flags[\"--name\"],\n icon: flags[\"--icon\"],\n force: Boolean(flags[\"--force\"])\n });\n const dryRun = Boolean(flags[\"--dry-run\"]);\n\n for (const file of plan.files) {\n if (!dryRun) {\n fs.mkdirSync(path.dirname(file.path), { recursive: true });\n fs.writeFileSync(file.path, file.contents);\n }\n const verb = file.action === \"create\" ? \"created\" : file.action === \"replace\" ? \"replaced\" : \"updated\";\n console.log(`${chalk.green(\"✓\")} ${dryRun ? `would be ${verb}` : verb} ${path.relative(projectRoot, file.path)}`);\n }\n for (const step of plan.manualSteps) {\n console.log(`${chalk.yellow(\"!\")} ${step}`);\n }\n const where = plan.kind === \"app\" ? `/${slug} in the admin` : `a \"${flags[\"--name\"]?.trim() || viewLabel(slug)}\" tab on each ${flags[\"--collection\"]} record`;\n console.log(chalk.gray(` ${plan.componentName} renders at ${where}. Edit ${path.relative(projectRoot, plan.viewFile)} to build the screen.`));\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { n as getPMCommands, t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
|
|
2
|
-
import { c as findProjectRoot, d as readEnvFile } from "./project-
|
|
3
|
-
import { d as findBackendApp, m as manifestExists, p as loadManifest, x as writeManifest } from "./manifest-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { c as findProjectRoot, d as readEnvFile } from "./project-CasK56vN.js";
|
|
3
|
+
import { d as findBackendApp, m as manifestExists, p as loadManifest, x as writeManifest } from "./manifest-BtzDy7KQ.js";
|
|
4
|
+
import { t as DEV_BACKEND_URL_ENV } from "./dev-server-OJsUGZEB.js";
|
|
5
|
+
import { V as readLink } from "./context-GUxkZm-S.js";
|
|
6
|
+
import { n as COLLECTIONS_PATH_RULE, t as COLLECTIONS_FLAG_HELP } from "./path-flags-DNvtEi2-.js";
|
|
7
|
+
import { t as Refusal } from "./refusal-ReeeGP8a.js";
|
|
6
8
|
import { n as isLoadedCollectionFile } from "./collection-drift-BKj_BoMq.js";
|
|
7
9
|
import chalk from "chalk";
|
|
8
10
|
import fs from "fs";
|
|
@@ -81,6 +83,32 @@ function writeRegistration(dir, databaseTypes) {
|
|
|
81
83
|
writeIfChanged(registerPath, REGISTER_SOURCE);
|
|
82
84
|
}
|
|
83
85
|
/**
|
|
86
|
+
* Write the server-side registration from the collection files in
|
|
87
|
+
* `collectionsDir`, exactly as `rebase generate-sdk` writes it, for a build.
|
|
88
|
+
*
|
|
89
|
+
* Only for a project that asked for it: `registerDatabase` in `rebase.json`,
|
|
90
|
+
* or a registration an earlier `--register` left, which is kept current. The
|
|
91
|
+
* registration lives in gitignored `config/generated/`, so a fresh clone (a CI
|
|
92
|
+
* job) has none until something writes it, and a bundle compiled without it
|
|
93
|
+
* types `context.data` as untyped rows: callbacks that read a typed column
|
|
94
|
+
* fail to compile there while they compile locally.
|
|
95
|
+
*
|
|
96
|
+
* Returns the directory written, or null when there was nothing to do.
|
|
97
|
+
* Throws when a `register.ts` there is not ours, as `generate-sdk` refuses.
|
|
98
|
+
*/
|
|
99
|
+
async function writeRegistrationForBuild(collectionsDir, registerDatabase) {
|
|
100
|
+
const dir = registrationDir(collectionsDir);
|
|
101
|
+
if (!registerDatabase && !hasRegistration(dir)) return null;
|
|
102
|
+
if (!fs.existsSync(collectionsDir)) return null;
|
|
103
|
+
const collections = await loadCollections(collectionsDir);
|
|
104
|
+
if (collections.length === 0) return null;
|
|
105
|
+
collections.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
106
|
+
const databaseTypes = generateSDK(collections, { includeReadme: false }).find((file) => file.path === "database.types.ts")?.content;
|
|
107
|
+
if (databaseTypes === void 0) return null;
|
|
108
|
+
writeRegistration(dir, databaseTypes);
|
|
109
|
+
return dir;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
84
112
|
* Whether `rebase.json` asks for the registration (`registerDatabase: true` on
|
|
85
113
|
* the backend app). That is what survives a clone: `generated/` is gitignored,
|
|
86
114
|
* so a `register.ts` from an earlier run is not there to say it.
|
|
@@ -142,21 +170,25 @@ function rememberRegistration(projectRoot) {
|
|
|
142
170
|
*
|
|
143
171
|
* A path to a single module is read as the runtime reads one: its
|
|
144
172
|
* `backendCollections`, or its `collections`.
|
|
173
|
+
*
|
|
174
|
+
* A missing directory, a missing jiti and a module that exports no collections
|
|
175
|
+
* are `Refusal`s: the message says all there is. A collection file that throws
|
|
176
|
+
* on import is not: that is the project's own code failing, and the stack
|
|
177
|
+
* `--debug` prints points at the line, so `bin/rebase.js` keeps its hint.
|
|
145
178
|
*/
|
|
146
179
|
async function loadCollections(collectionsDir) {
|
|
147
180
|
const absDir = path.resolve(collectionsDir);
|
|
148
|
-
if (!fs.existsSync(absDir)) throw new
|
|
181
|
+
if (!fs.existsSync(absDir)) throw new Refusal(`Collections directory not found: ${absDir} (${COLLECTIONS_PATH_RULE})`);
|
|
149
182
|
let jiti;
|
|
150
183
|
try {
|
|
151
184
|
const jitiModule = await import("jiti");
|
|
152
185
|
jiti = jitiModule.default || jitiModule;
|
|
153
186
|
} catch {
|
|
154
|
-
|
|
187
|
+
throw new Refusal(`Could not load 'jiti'. Install it with: ${[
|
|
155
188
|
...getPMCommands(detectPackageManager()).install,
|
|
156
189
|
"-D",
|
|
157
190
|
"jiti"
|
|
158
|
-
].join(" ");
|
|
159
|
-
throw new Error(`Could not load 'jiti'. Install it with: ${installCmd}\njiti is required to dynamically import TypeScript collection definitions.`);
|
|
191
|
+
].join(" ")}\njiti is required to dynamically import TypeScript collection definitions.`);
|
|
160
192
|
}
|
|
161
193
|
if (!fs.statSync(absDir).isDirectory()) {
|
|
162
194
|
const mod = jiti(path.dirname(absDir), {
|
|
@@ -165,7 +197,7 @@ async function loadCollections(collectionsDir) {
|
|
|
165
197
|
})(absDir);
|
|
166
198
|
const listed = mod.backendCollections ?? mod.collections ?? mod.default;
|
|
167
199
|
if (Array.isArray(listed)) return listed;
|
|
168
|
-
throw new
|
|
200
|
+
throw new Refusal(`Could not extract collections from ${absDir}.\nA single collections module exports \`backendCollections\` or \`collections\`: an array of collections.`);
|
|
169
201
|
}
|
|
170
202
|
const jitiInstance = jiti(absDir, {
|
|
171
203
|
interopDefault: true,
|
|
@@ -304,10 +336,14 @@ function mayUseAmbientKey(target, cwd) {
|
|
|
304
336
|
* the one it actually got to `.rebase/state.json`. Printing a hardcoded
|
|
305
337
|
* `localhost:3001` sent people to a port nothing was listening on — or, with
|
|
306
338
|
* several projects on one machine, to a different project's backend. Prefer the
|
|
307
|
-
* port
|
|
308
|
-
*
|
|
339
|
+
* port `rebase dev` says it is starting the backend on (`DEV_BACKEND_URL_ENV`:
|
|
340
|
+
* it regenerates the SDK before the backend binds), then the port this project
|
|
341
|
+
* last ran on; fall back to the literal only when the project has never been
|
|
342
|
+
* started.
|
|
309
343
|
*/
|
|
310
344
|
function resolveExampleBaseUrl(cwd) {
|
|
345
|
+
const fromDev = process.env[DEV_BACKEND_URL_ENV]?.trim();
|
|
346
|
+
if (fromDev) return fromDev;
|
|
311
347
|
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
312
348
|
try {
|
|
313
349
|
const state = JSON.parse(fs.readFileSync(path.join(projectRoot, ".rebase", "state.json"), "utf-8"));
|
|
@@ -484,6 +520,6 @@ export const SCHEMA_VERSION = ${JSON.stringify(schemaVersion)};
|
|
|
484
520
|
console.log("");
|
|
485
521
|
}
|
|
486
522
|
//#endregion
|
|
487
|
-
export { generateSdkCommand };
|
|
523
|
+
export { generateSdkCommand, writeRegistrationForBuild };
|
|
488
524
|
|
|
489
|
-
//# sourceMappingURL=generate_sdk-
|
|
525
|
+
//# sourceMappingURL=generate_sdk-BvcWvoUh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate_sdk-BvcWvoUh.js","names":[],"sources":["../src/commands/generate_sdk.ts"],"sourcesContent":["/**\n * CLI command: generate-sdk\n *\n * Reads every collection file in a directory (default: ./config/collections) —\n * the files the backend serves, not the barrel's list — generates a typed\n * TypeScript SDK, and writes it to the output directory (default: ./generated/sdk).\n *\n * Uses jiti for dynamic TypeScript import of collection files.\n */\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport { CollectionConfig, computeSchemaVersion, deserializeCollections } from \"@rebasepro/types\";\nimport { CodegenError, generateSDK, GeneratedFile, toCollectionAccessor } from \"@rebasepro/codegen\";\nimport { detectPackageManager, getPMCommands } from \"../utils/package-manager\";\nimport { findProjectRoot, readEnvFile } from \"../utils/project\";\nimport { DEV_BACKEND_URL_ENV } from \"../utils/dev-server\";\nimport { Refusal } from \"../utils/refusal\";\nimport { findBackendApp, loadManifest, manifestExists, writeManifest } from \"../manifest\";\nimport { readLink } from \"./cloud/context\";\nimport { COLLECTIONS_FLAG_HELP, COLLECTIONS_PATH_RULE } from \"../utils/path-flags\";\nimport { isLoadedCollectionFile } from \"../utils/collection-drift\";\n\ninterface GenerateSDKArgs {\n collectionsDir: string;\n output: string;\n cwd: string;\n /**\n * Where to read the schema from instead of local source.\n *\n * `link` uses this checkout's linked project; anything else is treated as\n * the base URL of a Rebase backend. This is what lets a repository that\n * contains no collections — a separate frontend, a second web app — generate\n * a typed client from the project it talks to.\n */\n from?: string;\n /** Bearer token for the contract endpoint. Falls back to REBASE_SERVICE_KEY. */\n token?: string;\n /**\n * Also register the generated `Database` for server-side code: write the\n * types and the `Register` augmentation into `config/generated/`. See\n * {@link writeRegistration}.\n */\n register?: boolean;\n /**\n * The directory holding `rebase.json`, where `--register` is remembered.\n * Found from `cwd` when not given.\n */\n projectRoot?: string;\n help?: boolean;\n}\n\n/** What `--register` writes, and what marks a project as having opted in. */\nexport const REGISTER_FILE = \"register.ts\";\n\n/** The first line of {@link REGISTER_FILE}: a file without it is the developer's own. */\nconst REGISTER_MARKER = \"// Auto-generated by `rebase generate-sdk --register`. Do not edit.\";\n\nconst REGISTER_SOURCE = `${REGISTER_MARKER}\n//\n// Registers this project's generated \\`Database\\` on \\`@rebasepro/types\\`, so\n// \\`context.data\\` in collection callbacks, \\`rebase.dataAsAdmin\\`, and the\n// \\`rebase\\` a function or a cron receives are typed from it. Every later\n// \\`rebase generate-sdk\\` (and \\`rebase dev\\`) refreshes this directory; delete\n// it to go back to untyped server-side data.\nimport type { Database } from \"./database.types\";\n\ndeclare module \"@rebasepro/types\" {\n interface Register {\n database: Database;\n }\n}\n`;\n\n/**\n * Where `--register` writes: `generated/` beside the collections directory,\n * which is `config/generated/` in a scaffolded project.\n *\n * Inside `config/` because that is the one directory both compiles of a\n * collection file include: the backend's program (it includes\n * `../config/**`) and the `config` package's own `tsc`. A registration\n * there that imported `../generated/sdk/database.types` pulled a file from\n * outside `config/` into that package's program, which TypeScript refuses\n * (the file is not under its `rootDir`) — so the types are copied in beside\n * the registration rather than imported from the SDK.\n */\nexport function registrationDir(collectionsDir: string): string {\n return path.join(path.dirname(path.resolve(collectionsDir)), \"generated\");\n}\n\n/** Whether this project opted in: the registration is there, and it is ours. */\nfunction hasRegistration(dir: string): boolean {\n try {\n return fs.readFileSync(path.join(dir, REGISTER_FILE), \"utf-8\").startsWith(REGISTER_MARKER);\n } catch {\n return false;\n }\n}\n\n/** Write a file only when its content changed, so a watcher on the directory does not restart for nothing. */\nfunction writeIfChanged(filePath: string, content: string): void {\n try {\n if (fs.readFileSync(filePath, \"utf-8\") === content) return;\n } catch {\n // Not there yet.\n }\n fs.writeFileSync(filePath, content, \"utf-8\");\n}\n\n/**\n * Write the generated `Database` and its `Register` augmentation into\n * {@link registrationDir}. Refuses to overwrite a `register.ts` it did not\n * write.\n */\nfunction writeRegistration(dir: string, databaseTypes: string): void {\n const registerPath = path.join(dir, REGISTER_FILE);\n if (fs.existsSync(registerPath) && !hasRegistration(dir)) {\n throw new Error(\n `${registerPath} exists and was not written by \"rebase generate-sdk --register\". ` +\n \"Move it, or register the Database there yourself.\"\n );\n }\n fs.mkdirSync(dir, { recursive: true });\n writeIfChanged(path.join(dir, \"database.types.ts\"), databaseTypes);\n writeIfChanged(registerPath, REGISTER_SOURCE);\n}\n\n/**\n * Write the server-side registration from the collection files in\n * `collectionsDir`, exactly as `rebase generate-sdk` writes it, for a build.\n *\n * Only for a project that asked for it: `registerDatabase` in `rebase.json`,\n * or a registration an earlier `--register` left, which is kept current. The\n * registration lives in gitignored `config/generated/`, so a fresh clone (a CI\n * job) has none until something writes it, and a bundle compiled without it\n * types `context.data` as untyped rows: callbacks that read a typed column\n * fail to compile there while they compile locally.\n *\n * Returns the directory written, or null when there was nothing to do.\n * Throws when a `register.ts` there is not ours, as `generate-sdk` refuses.\n */\nexport async function writeRegistrationForBuild(collectionsDir: string, registerDatabase: boolean): Promise<string | null> {\n const dir = registrationDir(collectionsDir);\n if (!registerDatabase && !hasRegistration(dir)) return null;\n if (!fs.existsSync(collectionsDir)) return null;\n const collections = await loadCollections(collectionsDir);\n if (collections.length === 0) return null;\n collections.sort((a, b) => a.slug.localeCompare(b.slug));\n const databaseTypes = generateSDK(collections, { includeReadme: false })\n .find((file) => file.path === \"database.types.ts\")?.content;\n if (databaseTypes === undefined) return null;\n writeRegistration(dir, databaseTypes);\n return dir;\n}\n\n/**\n * Whether `rebase.json` asks for the registration (`registerDatabase: true` on\n * the backend app). That is what survives a clone: `generated/` is gitignored,\n * so a `register.ts` from an earlier run is not there to say it.\n *\n * An unreadable manifest answers no; `rebase build` is where it is reported.\n */\nfunction manifestRegisters(projectRoot: string | undefined): boolean {\n if (!projectRoot || !manifestExists(projectRoot)) return false;\n try {\n return findBackendApp(loadManifest(projectRoot).manifest)?.app.registerDatabase === true;\n } catch {\n return false;\n }\n}\n\n/**\n * Remember `--register` in `rebase.json`, so later runs, `rebase dev` and a\n * fresh clone keep registering. Returns where it was written, or why not.\n *\n * Never creates the file: a project without one is synthesized from its\n * layout, and writing one is `rebase apps init`'s decision, not this flag's.\n */\nfunction rememberRegistration(projectRoot: string | undefined): { written: string } | { skipped: string } {\n if (!projectRoot || !manifestExists(projectRoot)) {\n return { skipped: \"No rebase.json here, so the choice lasts as long as the generated files.\" };\n }\n let loaded: ReturnType<typeof loadManifest>;\n try {\n loaded = loadManifest(projectRoot);\n } catch (error) {\n return { skipped: `rebase.json could not be read (${error instanceof Error ? error.message : String(error)}).` };\n }\n const backend = findBackendApp(loaded.manifest);\n if (!backend) return { skipped: \"rebase.json declares no backend app to remember it on.\" };\n if (backend.app.registerDatabase === true) return { written: loaded.filePath ?? projectRoot };\n const manifest = {\n ...loaded.manifest,\n apps: { ...loaded.manifest.apps, [backend.name]: { ...backend.app, registerDatabase: true } }\n };\n return { written: writeManifest(projectRoot, manifest) };\n}\n\n/**\n * Load the collections the backend serves, the way it finds them.\n *\n * A directory is read as `loadCollectionsFromDirectory` in @rebasepro/server\n * reads it: every top-level collection file, each default-exporting one\n * collection. The barrel (`index.ts`) is not a registry. The runtime, the admin\n * panel, `rebase build` and `rebase schema generate` all scan the directory, and\n * the barrel only orders the panel's navigation and declares\n * `defaultSecurityRules`. This command used to read the barrel instead, so a\n * collection file left out of it was created, served at `/api/data/<slug>` and\n * listed in the panel, and missing from the typed SDK alone.\n *\n * A file that does not load is fatal, as it is at boot: `rebase dev` runs this\n * on every save, and skipping the file would overwrite good types with a\n * `Database` that is silently short a collection.\n *\n * A path to a single module is read as the runtime reads one: its\n * `backendCollections`, or its `collections`.\n *\n * A missing directory, a missing jiti and a module that exports no collections\n * are `Refusal`s: the message says all there is. A collection file that throws\n * on import is not: that is the project's own code failing, and the stack\n * `--debug` prints points at the line, so `bin/rebase.js` keeps its hint.\n */\nasync function loadCollections(collectionsDir: string): Promise<CollectionConfig[]> {\n const absDir = path.resolve(collectionsDir);\n\n if (!fs.existsSync(absDir)) {\n throw new Refusal(`Collections directory not found: ${absDir} (${COLLECTIONS_PATH_RULE})`);\n }\n\n let jiti: (id: string, userOptions?: Record<string, unknown>) => (modulePath: string) => Record<string, unknown>;\n try {\n const jitiModule = await import(\"jiti\");\n jiti = (jitiModule.default || jitiModule) as typeof jiti;\n } catch {\n const installCmd = [...getPMCommands(detectPackageManager()).install, \"-D\", \"jiti\"].join(\" \");\n throw new Refusal(\n `Could not load 'jiti'. Install it with: ${installCmd}\\n` +\n \"jiti is required to dynamically import TypeScript collection definitions.\"\n );\n }\n\n if (!fs.statSync(absDir).isDirectory()) {\n const mod = jiti(path.dirname(absDir), { interopDefault: true, esmResolve: true })(absDir);\n const listed = mod.backendCollections ?? mod.collections ?? mod.default;\n if (Array.isArray(listed)) return listed as CollectionConfig[];\n throw new Refusal(\n `Could not extract collections from ${absDir}.\\n` +\n \"A single collections module exports `backendCollections` or `collections`: an array of collections.\"\n );\n }\n\n const jitiInstance = jiti(absDir, {\n interopDefault: true,\n esmResolve: true\n });\n\n const collections: CollectionConfig[] = [];\n const failures: string[] = [];\n const files = fs.readdirSync(absDir).filter(isLoadedCollectionFile).sort();\n\n for (const file of files) {\n try {\n const mod = jitiInstance(path.join(absDir, file));\n const exported = mod.default ?? mod;\n if (exported && typeof exported === \"object\" && \"slug\" in exported) {\n collections.push(exported as CollectionConfig);\n } else {\n failures.push(`${file}: no default export of a collection`);\n }\n } catch (err) {\n failures.push(`${file}: ${(err as Error).message}`);\n }\n }\n\n if (failures.length > 0) {\n throw new Error(\n `Could not load ${failures.length} collection file(s) from ${absDir}:\\n` +\n failures.map(failure => ` • ${failure}`).join(\"\\n\") +\n \"\\n\\nEvery collection file must import cleanly and default-export a collection — \" +\n \"the backend refuses to boot on the same file.\"\n );\n }\n\n return collections;\n}\n\n/**\n * Write generated files to the output directory.\n */\nfunction writeFiles(outputDir: string, files: GeneratedFile[]): void {\n const absOutput = path.resolve(outputDir);\n\n // Create output directory\n fs.mkdirSync(absOutput, { recursive: true });\n\n for (const file of files) {\n const filePath = path.join(absOutput, file.path);\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(filePath, file.content, \"utf-8\");\n }\n}\n\nfunction printSdkHelp(): void {\n console.log(`\n${chalk.bold(\"rebase generate-sdk\")} — generate a typed client from a project's schema\n\n${chalk.bold(\"Usage\")}\n rebase generate-sdk [options]\n\n${chalk.bold(\"Options\")}\n -c, --collections <dir> ${COLLECTIONS_FLAG_HELP}\n (--collections-dir is accepted too)\n -o, --output <dir> Where to write the SDK (default: ./generated/sdk)\n (--out is accepted too, as on 'rebase build')\n --from <link|url> Fetch the schema from a running project instead of\n local source. \"link\" uses this checkout's linked project.\n --token <token> Bearer token for the contract endpoint\n (default: $REBASE_SERVICE_KEY)\n --register Also type server-side data: write the types and the\n Register declaration to config/generated/, and\n remember it in rebase.json so later runs keep it.\n -h, --help Show this help\n\n${chalk.bold(\"Examples\")}\n rebase generate-sdk From local collections\n rebase generate-sdk --from link From the linked project\n rebase generate-sdk --from https://api.acme.com From any Rebase backend\n rebase generate-sdk --register Type context.data and rebase.dataAsAdmin too\n`.trim());\n}\n\n/**\n * Fetch collections from a running project's contract endpoint.\n *\n * The payload replaces relation `target` functions with slug references, so it\n * has to be rehydrated before the generator sees it — the generator *calls*\n * `target()` to decide whether a foreign key is a string or a number, and a\n * missing target silently degrades that to a union rather than failing.\n */\n/** What `--from` sent to the contract endpoint, and which keys it left behind. */\ninterface ContractCredential {\n /** The bearer token sent: `--token`, the shell's key, or none. */\n sent: \"token\" | \"ambient\" | null;\n /** `REBASE_SERVICE_KEY` is in the shell environment. */\n shellKey: boolean;\n /** `REBASE_SERVICE_KEY` is in the project's `.env`. */\n envFileKey: boolean;\n}\n\n/**\n * What to say when the contract endpoint refuses, by what was and was not sent.\n *\n * \"Set REBASE_SERVICE_KEY\" is only right when no key exists. The shell's key is\n * withheld from every host but the linked project, and `.env`'s is never read\n * here — it is the local backend's key, and the linked project is usually a\n * deployed one — so telling a reader whose key is in `.env` to set it sends them\n * to fix something that is not broken.\n */\nfunction contractRefusalHint(credential: ContractCredential): string[] {\n if (credential.sent === \"token\") {\n return [\"The token passed with --token was refused: pass a service key, or an admin's token.\"];\n }\n if (credential.sent === \"ambient\") {\n return [\"REBASE_SERVICE_KEY was sent and refused: it is not this project's service key. Pass the right one with --token.\"];\n }\n if (credential.shellKey) {\n return [\n \"REBASE_SERVICE_KEY is set, but it is only sent to this checkout's linked project, and this host is not it.\",\n \"Pass the key with --token to send it here.\"\n ];\n }\n if (credential.envFileKey) {\n return [\n \"REBASE_SERVICE_KEY in .env is not sent: --from sends the shell's REBASE_SERVICE_KEY, and only to this checkout's linked project.\",\n \"Pass the key with --token.\"\n ];\n }\n return [\"Pass --token <key>, a service key or an admin's token. The shell's REBASE_SERVICE_KEY is sent only to this checkout's linked project.\"];\n}\n\nasync function fetchRemoteCollections(\n baseUrl: string,\n token: string | undefined,\n credential: ContractCredential\n): Promise<{ collections: CollectionConfig[]; schemaVersion: string }> {\n const url = `${baseUrl.replace(/\\/+$/, \"\")}/api/meta/contract`;\n\n const headers: Record<string, string> = { accept: \"application/json\" };\n if (token) headers.authorization = `Bearer ${token}`;\n\n let response: Response;\n try {\n response = await fetch(url, { headers });\n } catch (err) {\n console.log(chalk.red(` ✗ Could not reach ${url}`));\n console.log(chalk.gray(` ${err instanceof Error ? err.message : String(err)}`));\n process.exit(1);\n }\n\n if (response.status === 401 || response.status === 403) {\n console.log(chalk.red(` ✗ Not authorized to read the project contract (${response.status}).`));\n console.log(chalk.gray(\" The contract describes every table and relation, so it is admin-only.\"));\n for (const line of contractRefusalHint(credential)) console.log(chalk.gray(` ${line}`));\n process.exit(1);\n }\n\n if (response.status === 404) {\n console.log(chalk.red(\" ✗ This server has no contract endpoint.\"));\n console.log(chalk.gray(\" It needs to be running Rebase 0.11 or newer.\"));\n process.exit(1);\n }\n\n if (!response.ok) {\n console.log(chalk.red(` ✗ Contract request failed with ${response.status}.`));\n process.exit(1);\n }\n\n const contract = await response.json() as {\n collections?: unknown[];\n schemaVersion?: string;\n };\n\n if (!Array.isArray(contract.collections)) {\n console.log(chalk.red(\" ✗ The contract response did not contain collections.\"));\n process.exit(1);\n }\n\n return {\n collections: deserializeCollections(contract.collections),\n schemaVersion: contract.schemaVersion ?? \"unknown\"\n };\n}\n\n/**\n * Decide whether the ambient service key may be sent to this host.\n *\n * `REBASE_SERVICE_KEY` grants full admin bypass. Attaching it to whatever URL\n * happened to be passed — or, worse, to whatever a committed `.rebase/cloud.json`\n * points at — would hand the project's most powerful credential to a host nobody\n * vetted. An explicit `--token` is a decision the caller made; the ambient\n * variable is not, so it only travels to the project this checkout is linked to.\n */\nfunction mayUseAmbientKey(target: string, cwd: string): boolean {\n const link = readLink(findProjectRoot(cwd) ?? cwd);\n if (!link?.apiUrl) return false;\n try {\n // Origin, not host: with a link recorded as https, an `http://` target\n // for the same host would otherwise pass and send the key in cleartext.\n return new URL(link.apiUrl).origin === new URL(target).origin;\n } catch {\n return false;\n }\n}\n\n/**\n * The base URL to show in the printed usage example.\n *\n * `rebase dev` binds a port derived from the project path, not 3001, and writes\n * the one it actually got to `.rebase/state.json`. Printing a hardcoded\n * `localhost:3001` sent people to a port nothing was listening on — or, with\n * several projects on one machine, to a different project's backend. Prefer the\n * port `rebase dev` says it is starting the backend on (`DEV_BACKEND_URL_ENV`:\n * it regenerates the SDK before the backend binds), then the port this project\n * last ran on; fall back to the literal only when the project has never been\n * started.\n */\nexport function resolveExampleBaseUrl(cwd: string): string {\n const fromDev = process.env[DEV_BACKEND_URL_ENV]?.trim();\n if (fromDev) return fromDev;\n const projectRoot = findProjectRoot(cwd) ?? cwd;\n try {\n const state = JSON.parse(fs.readFileSync(path.join(projectRoot, \".rebase\", \"state.json\"), \"utf-8\"));\n if (typeof state.baseUrl === \"string\" && state.baseUrl) return state.baseUrl;\n if (typeof state.port === \"number\") return `http://localhost:${state.port}`;\n } catch {\n // Never started, or the file is unreadable — fall through.\n }\n return \"http://localhost:3001\";\n}\n\n/** Whether a slug can be written as `rebase.data.<slug>` rather than a lookup. */\nexport function isIdentifierLike(slug: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(slug);\n}\n\n/** Resolve `--from` into a base URL, following the link file when asked. */\nfunction resolveSchemaSource(from: string, cwd: string): string {\n if (from !== \"link\") {\n // A bare hostname or a typo would otherwise be handed to `fetch` and fail\n // with something unhelpful; a non-http scheme has no business here at all.\n let parsed: URL;\n try {\n parsed = new URL(from);\n } catch {\n console.log(chalk.red(` ✗ \"${from}\" is not a valid URL.`));\n console.log(chalk.gray(\" Pass a full URL, e.g. https://api.example.com, or \\\"link\\\".\"));\n process.exit(1);\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n console.log(chalk.red(\" ✗ The project URL must be http or https.\"));\n process.exit(1);\n }\n return from;\n }\n\n const projectRoot = findProjectRoot(cwd) ?? cwd;\n const link = readLink(projectRoot);\n\n if (!link) {\n console.log(chalk.red(\" ✗ This checkout is not linked to a project.\"));\n console.log(chalk.gray(\" Run `rebase cloud link <url>`, or pass --from <url>.\"));\n process.exit(1);\n }\n\n const apiUrl = link.apiUrl;\n if (!apiUrl) {\n console.log(chalk.red(\" ✗ The project link has no API URL.\"));\n console.log(chalk.gray(\" Re-link with `rebase cloud link <url>` to record one.\"));\n process.exit(1);\n }\n\n return apiUrl;\n}\n\n/**\n * Main entry point for the generate-sdk command.\n */\nexport async function generateSdkCommand(args: GenerateSDKArgs): Promise<void> {\n const { collectionsDir, output, cwd } = args;\n\n if (args.help) {\n printSdkHelp();\n return;\n }\n\n const resolvedCollectionsDir = path.isAbsolute(collectionsDir)\n ? collectionsDir\n : path.join(cwd, collectionsDir);\n\n const resolvedOutput = path.isAbsolute(output)\n ? output\n : path.join(cwd, output);\n\n console.log(\"\");\n console.log(chalk.bold(\" 🔧 Rebase SDK Generator\"));\n console.log(\"\");\n\n let collections: CollectionConfig[];\n let remoteSchemaVersion: string | undefined;\n\n if (args.from) {\n const baseUrl = resolveSchemaSource(args.from, cwd);\n console.log(` ${chalk.gray(\"Project:\")} ${baseUrl}`);\n console.log(` ${chalk.gray(\"Output:\")} ${resolvedOutput}`);\n console.log(\"\");\n console.log(chalk.cyan(\" → Fetching the project contract...\"));\n\n const ambient = mayUseAmbientKey(baseUrl, cwd)\n ? process.env.REBASE_SERVICE_KEY\n : undefined;\n\n if (!args.token && !ambient && process.env.REBASE_SERVICE_KEY) {\n console.log(chalk.dim(\n \" (not sending REBASE_SERVICE_KEY — this host is not the linked project; pass --token to override)\"\n ));\n }\n\n const remote = await fetchRemoteCollections(baseUrl, args.token || ambient, {\n sent: args.token ? \"token\" : ambient ? \"ambient\" : null,\n shellKey: Boolean(process.env.REBASE_SERVICE_KEY),\n envFileKey: Boolean(readEnvFile(findProjectRoot(cwd) ?? cwd).REBASE_SERVICE_KEY)\n });\n collections = remote.collections;\n remoteSchemaVersion = remote.schemaVersion;\n } else {\n // A headless project has no collections directory by design: its API is\n // introspected from the live database at boot, and there is nothing here\n // to generate a client from. The scaffold ships `pnpm generate:sdk`\n // anyway, so the documented headless path had a script that could only\n // ever fail — and it failed with a path, which reads as a broken install\n // rather than a question with an answer.\n if (!fs.existsSync(resolvedCollectionsDir)) {\n console.log(chalk.gray(\n \" ○ This project derives its API from the database — \"\n + \"run `rebase schema introspect` first.\"\n ));\n console.log(chalk.gray(\n ` Nothing to generate from: ${resolvedCollectionsDir} does not exist.`\n ));\n console.log(\"\");\n return;\n }\n console.log(` ${chalk.gray(\"Collections:\")} ${resolvedCollectionsDir}`);\n console.log(` ${chalk.gray(\"Output:\")} ${resolvedOutput}`);\n console.log(\"\");\n console.log(chalk.cyan(\" → Loading collection definitions...\"));\n collections = await loadCollections(resolvedCollectionsDir);\n }\n\n // Sort collections alphabetically by slug to ensure deterministic SDK generation\n collections.sort((a, b) => a.slug.localeCompare(b.slug));\n\n if (collections.length === 0) {\n console.log(chalk.red(\" ✗ No collections found. Nothing to generate.\"));\n process.exit(1);\n }\n\n console.log(chalk.green(` ✓ Found ${collections.length} collection(s): ${collections.map(c => c.slug).join(\", \")}`));\n console.log(\"\");\n\n // 2. Generate SDK files\n console.log(chalk.cyan(\" → Generating SDK files...\"));\n let files: GeneratedFile[];\n try {\n files = generateSDK(collections, { baseUrl: resolveExampleBaseUrl(cwd) });\n } catch (err) {\n // A schema that cannot be expressed as valid TypeScript — two slugs\n // that collide on one accessor, a slug with no usable name. The\n // generator refuses rather than emitting a file that does not compile,\n // or one that silently routes a collection's reads to another's table.\n if (err instanceof CodegenError) {\n console.log(\"\");\n console.log(chalk.red(` ✗ ${err.message}`));\n process.exit(1);\n }\n throw err;\n }\n\n // Stamp the schema this SDK was built from.\n //\n // Without it, an app in a separate repository has no way to know its client\n // is stale: the backend moves on, the frontend keeps compiling against types\n // captured weeks ago, and the mismatch only surfaces as a runtime error. With\n // it, CI can compare against `/api/meta/schema-version` and say so.\n //\n // No generation timestamp. Collections are sorted above precisely so that\n // the same schema produces the same bytes; a timestamp put that back,\n // turning every regeneration into a diff and making the obvious staleness\n // gate — `rebase generate-sdk && git diff --exit-code` — impossible to pass.\n // `SCHEMA_VERSION` already identifies what this was built from, and does it\n // in a way that can be compared against a running project.\n const schemaVersion = remoteSchemaVersion ?? computeSchemaVersion(collections);\n files.push({\n path: \"schema.meta.ts\",\n content: `// Auto-generated by \\`rebase generate-sdk\\`. Do not edit.\n//\n// The schema version this SDK was generated from. Compare it against the\n// project's current version to detect drift:\n//\n// curl -s <api-url>/api/meta/schema-version\n//\n// Pass it to the client as \\`schemaVersion\\` and every request carries it in\n// the \\`x-rebase-schema\\` header, so the server can name the drift instead of\n// answering a renamed field with a bare 400.\nexport const SCHEMA_VERSION = ${JSON.stringify(schemaVersion)};\n`\n });\n\n console.log(chalk.green(` ✓ Generated ${files.length} file(s)`));\n console.log(chalk.gray(` schema ${schemaVersion}`));\n\n // 3. Write to disk\n console.log(chalk.cyan(` → Writing to ${resolvedOutput}...`));\n writeFiles(resolvedOutput, files);\n\n // 4. The server-side registration: on request, and kept current once a\n // project has it, so `rebase dev` regenerating the SDK never leaves the\n // server typed against an older schema than the client.\n const registerDir = registrationDir(resolvedCollectionsDir);\n const projectRoot = args.projectRoot ?? findProjectRoot(cwd) ?? undefined;\n if (args.register || hasRegistration(registerDir) || manifestRegisters(projectRoot)) {\n if (!fs.existsSync(path.dirname(registerDir))) {\n console.log(chalk.red(` ✗ No ${path.dirname(registerDir)} to register the Database in.`));\n console.log(chalk.gray(\" --register writes beside the collections directory; pass --collections.\"));\n process.exit(1);\n return;\n }\n const databaseTypes = files.find((file) => file.path === \"database.types.ts\")?.content;\n if (databaseTypes !== undefined) {\n try {\n writeRegistration(registerDir, databaseTypes);\n } catch (error) {\n console.log(chalk.red(` ✗ ${error instanceof Error ? error.message : String(error)}`));\n process.exit(1);\n return;\n }\n console.log(chalk.green(` ✓ Registered the Database for server-side code in ${registerDir}`));\n if (args.register) {\n const remembered = rememberRegistration(projectRoot);\n if (\"written\" in remembered) {\n console.log(chalk.gray(` Remembered in ${path.relative(cwd, remembered.written) || \"rebase.json\"} (registerDatabase).`));\n } else {\n console.log(chalk.yellow(` ${remembered.skipped}`));\n }\n }\n }\n }\n\n console.log(\"\");\n console.log(chalk.green.bold(\" ✓ SDK generated successfully!\"));\n console.log(\"\");\n const typesImport = `./${path.relative(cwd, path.join(resolvedOutput, \"database.types\"))}`;\n const metaImport = `./${path.relative(cwd, path.join(resolvedOutput, \"schema.meta\"))}`;\n const exampleSlug = collections[0]?.slug || \"my_collection\";\n\n console.log(chalk.gray(\" Usage:\"));\n console.log(chalk.gray(\" import { createRebaseClient } from '@rebasepro/client';\"));\n console.log(chalk.gray(` import { collectionsDictionary, type Database } from '${typesImport}';`));\n console.log(chalk.gray(` import { SCHEMA_VERSION } from '${metaImport}';`));\n console.log(\"\");\n console.log(chalk.gray(\" const rebase = createRebaseClient<Database>({\"));\n console.log(chalk.gray(` baseUrl: '${resolveExampleBaseUrl(cwd)}',`));\n // Sent as `x-rebase-schema` on every request. Costs one line here and is\n // the difference between a server that can say \"this client is three\n // deploys behind\" and one that can only reject a field it does not know.\n console.log(chalk.gray(\" schemaVersion: SCHEMA_VERSION,\"));\n // Without the dictionary a hyphenated slug is not resolvable from the\n // property name alone, and the request 404s at runtime.\n console.log(chalk.gray(\" collections: collectionsDictionary,\"));\n console.log(chalk.gray(\" // token: 'your-jwt-token',\"));\n console.log(chalk.gray(\" });\"));\n console.log(\"\");\n // `rebase.data.<accessor>` is the typed surface, so it is what gets printed.\n // `rebase.data.collection(slug)` exists too, but it is generic over\n // `Record<string, unknown>` and has no link to `Database` — it was the\n // headline example here for a while, which advertised the one call shape\n // that throws away the types this command just generated.\n const exampleAccessor = toCollectionAccessor(exampleSlug);\n const exampleAccess = isIdentifierLike(exampleAccessor)\n ? `rebase.data.${exampleAccessor}`\n : `rebase.data[${JSON.stringify(exampleAccessor)}]`;\n console.log(chalk.gray(` const { data } = await ${exampleAccess}.find();`));\n console.log(\"\");\n}\n"],"mappings":"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"}
|
package/dist/index.es.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { i as recordEvent, n as isEnabled, u as errorClass } from "./telemetry-
|
|
2
|
-
import { p as requireProjectRoot } from "./project-
|
|
3
|
-
import { a as unknownCommand, n as parseCommandArgs } from "./args-BX0YD14a.js";
|
|
1
|
+
import { i as recordEvent, n as isEnabled, u as errorClass } from "./telemetry-CgwJPVMO.js";
|
|
2
|
+
import { E as unknownCommand, b as UsageError, i as failAsJson, p as requireProjectRoot, x as parseCommandArgs, y as wantsJsonOutput } from "./project-CasK56vN.js";
|
|
4
3
|
import { n as cliVersion } from "./version-Buyyo1ut.js";
|
|
5
|
-
import { _ as selectDeployApp, a as DEFAULT_SCHEMA_FILE, b as validateManifest, c as buildableApps, d as findBackendApp, f as formatAppAddress, g as resolveBackendPaths, h as manifestPath, i as DEFAULT_FUNCTIONS_DIR, l as cmsMountOf, m as manifestExists, n as DEFAULT_CONFIG_DIR, o as ManifestError, p as loadManifest, r as DEFAULT_CRONS_DIR, s as assessManagedCompatibility, t as CURRENT_RUNTIME_RANGE, u as compareMountOrder, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-
|
|
6
|
-
import { _ as
|
|
4
|
+
import { _ as selectDeployApp, a as DEFAULT_SCHEMA_FILE, b as validateManifest, c as buildableApps, d as findBackendApp, f as formatAppAddress, g as resolveBackendPaths, h as manifestPath, i as DEFAULT_FUNCTIONS_DIR, l as cmsMountOf, m as manifestExists, n as DEFAULT_CONFIG_DIR, o as ManifestError, p as loadManifest, r as DEFAULT_CRONS_DIR, s as assessManagedCompatibility, t as CURRENT_RUNTIME_RANGE, u as compareMountOrder, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-BtzDy7KQ.js";
|
|
5
|
+
import { _ as findUnusedServerEntry, a as VENDOR_TARGET_OS, b as vendorDependencies, c as bundledNpmrc, d as composeBundleManifest, f as describeDepConflicts, g as detectStorageAuthorize, h as detectNativeDependencies, i as VENDOR_TARGET_CPU, l as collectDeclaredDependencies, m as detectFrameworkDepDrift, n as VENDOR_SIZE_MAX_BYTES, o as buildBundle, p as detectDeclaredDepConflicts, r as VENDOR_SIZE_WARN_BYTES, s as buildStaticBundle, t as DEFAULT_BUNDLE_DIR, u as commentSpans, v as foldStaticIntoBundle, y as normalizeEsmSpecifiers } from "./bundle-C6yEtMJ-.js";
|
|
7
6
|
import chalk from "chalk";
|
|
8
7
|
import arg from "arg";
|
|
9
8
|
import path from "path";
|
|
@@ -60,12 +59,14 @@ var namespacedCommands = [
|
|
|
60
59
|
"start",
|
|
61
60
|
"auth",
|
|
62
61
|
"doctor",
|
|
62
|
+
"verify",
|
|
63
63
|
"skills",
|
|
64
64
|
"api-keys",
|
|
65
65
|
"storage",
|
|
66
66
|
"cloud",
|
|
67
67
|
"apps",
|
|
68
68
|
"eject",
|
|
69
|
+
"generate",
|
|
69
70
|
"generate-sdk",
|
|
70
71
|
"telemetry",
|
|
71
72
|
"resources",
|
|
@@ -89,39 +90,43 @@ var NO_VOCABULARY = {
|
|
|
89
90
|
async function commandVocabulary(command) {
|
|
90
91
|
switch (command) {
|
|
91
92
|
case "schema": return {
|
|
92
|
-
subcommands: (await import("./schema-
|
|
93
|
+
subcommands: (await import("./schema-BSXwZSiI.js")).SCHEMA_SUBCOMMANDS,
|
|
93
94
|
aliases: {}
|
|
94
95
|
};
|
|
95
96
|
case "db": return {
|
|
96
|
-
subcommands: (await import("./db-
|
|
97
|
+
subcommands: (await import("./db-KzlqddGD.js")).DB_SUBCOMMANDS,
|
|
97
98
|
aliases: {}
|
|
98
99
|
};
|
|
99
100
|
case "auth": return {
|
|
100
|
-
subcommands: (await import("./auth-
|
|
101
|
+
subcommands: (await import("./auth-dII2jCO1.js")).AUTH_SUBCOMMANDS,
|
|
101
102
|
aliases: {}
|
|
102
103
|
};
|
|
103
104
|
case "skills": return {
|
|
104
|
-
subcommands: (await import("./skills-
|
|
105
|
+
subcommands: (await import("./skills-BU2flMOy.js")).SKILLS_SUBCOMMANDS,
|
|
105
106
|
aliases: {}
|
|
106
107
|
};
|
|
107
108
|
case "api-keys": return {
|
|
108
|
-
subcommands: (await import("./api-keys-
|
|
109
|
+
subcommands: (await import("./api-keys-CyJ26KEJ.js")).API_KEYS_SUBCOMMANDS,
|
|
109
110
|
aliases: {}
|
|
110
111
|
};
|
|
111
112
|
case "storage": return {
|
|
112
|
-
subcommands: (await import("./storage-
|
|
113
|
+
subcommands: (await import("./storage-DtOXGflp.js")).STORAGE_SUBCOMMANDS,
|
|
113
114
|
aliases: {}
|
|
114
115
|
};
|
|
115
116
|
case "apps": return {
|
|
116
|
-
subcommands: (await import("./apps-
|
|
117
|
+
subcommands: (await import("./apps-CnLDV5b6.js")).APPS_SUBCOMMANDS,
|
|
117
118
|
aliases: {}
|
|
118
119
|
};
|
|
119
120
|
case "telemetry": return {
|
|
120
|
-
subcommands: (await import("./telemetry-
|
|
121
|
+
subcommands: (await import("./telemetry-DwK5RQJl.js")).TELEMETRY_SUBCOMMANDS,
|
|
122
|
+
aliases: {}
|
|
123
|
+
};
|
|
124
|
+
case "generate": return {
|
|
125
|
+
subcommands: (await import("./generate-view-IFwCADvb.js")).GENERATE_SUBCOMMANDS,
|
|
121
126
|
aliases: {}
|
|
122
127
|
};
|
|
123
128
|
case "cloud": {
|
|
124
|
-
const cloud = await import("./cloud-
|
|
129
|
+
const cloud = await import("./cloud-BdnmqQaZ.js");
|
|
125
130
|
return {
|
|
126
131
|
subcommands: cloud.CLOUD_GROUP_NAMES,
|
|
127
132
|
aliases: cloud.GROUP_ALIASES
|
|
@@ -226,6 +231,7 @@ async function entry(args) {
|
|
|
226
231
|
error_type: errorClass(error),
|
|
227
232
|
usage: Boolean(error && typeof error === "object" && error.isUsageError)
|
|
228
233
|
}, { projectRoot: process.cwd() });
|
|
234
|
+
if (error instanceof UsageError && wantsJsonOutput(args)) failAsJson(error.message, "usage", `Run \`rebase ${command} --help\` for the flags it takes.`);
|
|
229
235
|
throw error;
|
|
230
236
|
}
|
|
231
237
|
}
|
|
@@ -243,12 +249,12 @@ async function entry(args) {
|
|
|
243
249
|
async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespacedCommands) {
|
|
244
250
|
switch (command) {
|
|
245
251
|
case "__dev-db-daemon": {
|
|
246
|
-
const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-
|
|
252
|
+
const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-zOC1revO.js");
|
|
247
253
|
await runDaemon(parseDaemonArgs(args));
|
|
248
254
|
return;
|
|
249
255
|
}
|
|
250
256
|
case "init": {
|
|
251
|
-
const { createRebaseApp } = await import("./init-
|
|
257
|
+
const { createRebaseApp } = await import("./init-CaU6GhwI.js");
|
|
252
258
|
await createRebaseApp(args);
|
|
253
259
|
break;
|
|
254
260
|
}
|
|
@@ -271,9 +277,9 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
|
|
|
271
277
|
maxPositionals: 0
|
|
272
278
|
});
|
|
273
279
|
const sdkRoot = sdkHelp ? process.cwd() : requireProjectRoot();
|
|
274
|
-
const { generateSdkCommand } = await import("./generate_sdk-
|
|
280
|
+
const { generateSdkCommand } = await import("./generate_sdk-BvcWvoUh.js");
|
|
275
281
|
await generateSdkCommand({
|
|
276
|
-
collectionsDir: sdkArgs["--collections"] || path.join(sdkRoot, "config/collections"),
|
|
282
|
+
collectionsDir: sdkArgs["--collections"] || (sdkHelp ? path.join(sdkRoot, "config/collections") : (await import("./collections-dir-DlvDhime.js")).resolveCollectionsDir(sdkRoot)),
|
|
277
283
|
output: sdkArgs["--output"] || path.join(sdkRoot, "generated/sdk"),
|
|
278
284
|
from: sdkArgs["--from"],
|
|
279
285
|
token: sdkArgs["--token"],
|
|
@@ -285,101 +291,111 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
|
|
|
285
291
|
break;
|
|
286
292
|
}
|
|
287
293
|
case "schema": {
|
|
288
|
-
const { schemaCommand } = await import("./schema-
|
|
294
|
+
const { schemaCommand } = await import("./schema-BSXwZSiI.js");
|
|
289
295
|
await schemaCommand(effectiveSubcommand, args);
|
|
290
296
|
break;
|
|
291
297
|
}
|
|
292
298
|
case "db": {
|
|
293
|
-
const { dbCommand } = await import("./db-
|
|
299
|
+
const { dbCommand } = await import("./db-KzlqddGD.js");
|
|
294
300
|
await dbCommand(effectiveSubcommand, args);
|
|
295
301
|
break;
|
|
296
302
|
}
|
|
297
303
|
case "console": {
|
|
298
|
-
const { consoleCommand } = await import("./console-
|
|
304
|
+
const { consoleCommand } = await import("./console-BXB6-8GT.js");
|
|
299
305
|
await consoleCommand(args);
|
|
300
306
|
break;
|
|
301
307
|
}
|
|
302
308
|
case "dev": {
|
|
303
|
-
const { devCommand } = await import("./dev-
|
|
309
|
+
const { devCommand } = await import("./dev-DTqVMgB3.js");
|
|
304
310
|
await devCommand(args);
|
|
305
311
|
break;
|
|
306
312
|
}
|
|
307
313
|
case "normalize-imports": {
|
|
308
|
-
const { normalizeImportsCommand } = await import("./normalize-imports-
|
|
314
|
+
const { normalizeImportsCommand } = await import("./normalize-imports-D0zXlM6g.js");
|
|
309
315
|
await normalizeImportsCommand(args);
|
|
310
316
|
break;
|
|
311
317
|
}
|
|
312
318
|
case "build": {
|
|
313
|
-
const { buildCommand } = await import("./build-
|
|
319
|
+
const { buildCommand } = await import("./build-Cza7ZQrp.js").then((n) => n.n);
|
|
314
320
|
await buildCommand(args);
|
|
315
321
|
break;
|
|
316
322
|
}
|
|
317
323
|
case "start": {
|
|
318
|
-
const { startCommand } = await import("./start-
|
|
324
|
+
const { startCommand } = await import("./start-mVb6upwY.js");
|
|
319
325
|
await startCommand(args);
|
|
320
326
|
break;
|
|
321
327
|
}
|
|
322
328
|
case "upgrade": {
|
|
323
|
-
const { upgradeCommand } = await import("./upgrade-
|
|
329
|
+
const { upgradeCommand } = await import("./upgrade-B7sVwL8S.js");
|
|
324
330
|
await upgradeCommand(args);
|
|
325
331
|
break;
|
|
326
332
|
}
|
|
327
333
|
case "apps": {
|
|
328
|
-
const { appsCommand } = await import("./apps-
|
|
334
|
+
const { appsCommand } = await import("./apps-CnLDV5b6.js");
|
|
329
335
|
await appsCommand(effectiveSubcommand, args);
|
|
330
336
|
break;
|
|
331
337
|
}
|
|
338
|
+
case "generate": {
|
|
339
|
+
const { generateCommand } = await import("./generate-view-IFwCADvb.js");
|
|
340
|
+
await generateCommand(effectiveSubcommand, args);
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
332
343
|
case "eject": {
|
|
333
|
-
const { ejectCommand } = await import("./eject-
|
|
344
|
+
const { ejectCommand } = await import("./eject-DABcDnPN.js");
|
|
334
345
|
await ejectCommand(args);
|
|
335
346
|
break;
|
|
336
347
|
}
|
|
337
348
|
case "auth": {
|
|
338
|
-
const { authCommand } = await import("./auth-
|
|
349
|
+
const { authCommand } = await import("./auth-dII2jCO1.js");
|
|
339
350
|
await authCommand(effectiveSubcommand, args);
|
|
340
351
|
break;
|
|
341
352
|
}
|
|
342
353
|
case "status": {
|
|
343
|
-
const { statusCommand } = await import("./status-
|
|
354
|
+
const { statusCommand } = await import("./status-BREvtzJm.js");
|
|
344
355
|
await statusCommand(args);
|
|
345
356
|
break;
|
|
346
357
|
}
|
|
347
358
|
case "resources": {
|
|
348
|
-
const { resourcesCommand } = await import("./resources-
|
|
359
|
+
const { resourcesCommand } = await import("./resources-CPSC5Kcu.js");
|
|
349
360
|
await resourcesCommand(args);
|
|
350
361
|
break;
|
|
351
362
|
}
|
|
352
363
|
case "doctor": {
|
|
353
|
-
const { doctorCommand } = await import("./doctor-
|
|
364
|
+
const { doctorCommand } = await import("./doctor-BRWOlqeG.js");
|
|
354
365
|
await doctorCommand(args);
|
|
355
366
|
break;
|
|
356
367
|
}
|
|
368
|
+
case "verify": {
|
|
369
|
+
const { verifyCommand } = await import("./verify-D7UsV_qe.js");
|
|
370
|
+
await verifyCommand(args);
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
357
373
|
case "skills": {
|
|
358
|
-
const { skillsCommand } = await import("./skills-
|
|
374
|
+
const { skillsCommand } = await import("./skills-BU2flMOy.js");
|
|
359
375
|
await skillsCommand(effectiveSubcommand, args);
|
|
360
376
|
break;
|
|
361
377
|
}
|
|
362
378
|
case "api-keys": {
|
|
363
|
-
const { apiKeysCommand } = await import("./api-keys-
|
|
379
|
+
const { apiKeysCommand } = await import("./api-keys-CyJ26KEJ.js");
|
|
364
380
|
await apiKeysCommand(effectiveSubcommand, args);
|
|
365
381
|
break;
|
|
366
382
|
}
|
|
367
383
|
case "storage": {
|
|
368
|
-
const { storageCommand } = await import("./storage-
|
|
384
|
+
const { storageCommand } = await import("./storage-DtOXGflp.js");
|
|
369
385
|
await storageCommand(effectiveSubcommand, args);
|
|
370
386
|
break;
|
|
371
387
|
}
|
|
372
388
|
case "cloud": {
|
|
373
|
-
const { cloudCommand } = await import("./cloud-
|
|
389
|
+
const { cloudCommand } = await import("./cloud-BdnmqQaZ.js");
|
|
374
390
|
await cloudCommand(effectiveSubcommand, args);
|
|
375
391
|
break;
|
|
376
392
|
}
|
|
377
393
|
case "telemetry": {
|
|
378
|
-
const { telemetryCommand } = await import("./telemetry-
|
|
394
|
+
const { telemetryCommand } = await import("./telemetry-DwK5RQJl.js");
|
|
379
395
|
await telemetryCommand(args);
|
|
380
396
|
break;
|
|
381
397
|
}
|
|
382
|
-
default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-
|
|
398
|
+
default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-BdnmqQaZ.js")).CLOUD_GROUP_NAMES });
|
|
383
399
|
}
|
|
384
400
|
}
|
|
385
401
|
/** The global help. Exported so its Options block can be held against {@link ROOT_FLAGS}. */
|
|
@@ -418,7 +434,8 @@ ${chalk.green.bold("Database")}
|
|
|
418
434
|
${chalk.green.bold("Explore")}
|
|
419
435
|
${chalk.blue.bold("console")} A REPL with the project's data in scope ${chalk.gray("(-e <code> runs one snippet)")}
|
|
420
436
|
|
|
421
|
-
${chalk.green.bold("
|
|
437
|
+
${chalk.green.bold("Generate")}
|
|
438
|
+
${chalk.blue.bold("generate view")} ${chalk.gray("<slug>")} Scaffold a custom admin screen ${chalk.gray("(--collection: a record tab)")}
|
|
422
439
|
${chalk.blue.bold("generate-sdk")} Generate a typed TypeScript SDK from collections
|
|
423
440
|
|
|
424
441
|
${chalk.green.bold("Auth")}
|
|
@@ -428,6 +445,7 @@ ${chalk.green.bold("Auth")}
|
|
|
428
445
|
${chalk.green.bold("Diagnostics")}
|
|
429
446
|
${chalk.blue.bold("status")} Show every resource and whether its variables are set
|
|
430
447
|
${chalk.blue.bold("doctor")} Detect schema drift between collections, schema, and DB
|
|
448
|
+
${chalk.blue.bold("verify")} Check collections, RLS coverage and migrations ${chalk.gray("(CI + agent hooks)")}
|
|
431
449
|
${chalk.blue.bold("resources")} List the databases, buckets and topics this project declares
|
|
432
450
|
|
|
433
451
|
${chalk.green.bold("Take ownership")}
|
|
@@ -483,6 +501,6 @@ function telemetryNotice() {
|
|
|
483
501
|
return chalk.gray(`Usage sharing: ${sharing ? "on" : "off"} — ${chalk.cyan("rebase telemetry")} to inspect or change\n`);
|
|
484
502
|
}
|
|
485
503
|
//#endregion
|
|
486
|
-
export { CURRENT_RUNTIME_RANGE, DEFAULT_BUNDLE_DIR, DEFAULT_CONFIG_DIR, DEFAULT_CRONS_DIR, DEFAULT_FUNCTIONS_DIR, DEFAULT_SCHEMA_FILE, ManifestError, VENDOR_SIZE_MAX_BYTES, VENDOR_SIZE_WARN_BYTES, VENDOR_TARGET_CPU, VENDOR_TARGET_OS, assessManagedCompatibility, buildBundle, buildStaticBundle, buildableApps, cmsMountOf, collectDeclaredDependencies, commentSpans, compareMountOrder, composeBundleManifest, describeDepConflicts, detectDeclaredDepConflicts, detectFrameworkDepDrift, detectNativeDependencies, detectStorageAuthorize, entry, findBackendApp, findUnusedServerEntry, foldStaticIntoBundle, formatAppAddress, loadManifest, manifestExists, manifestPath, normalizeEsmSpecifiers, resolveBackendPaths, selectDeployApp, staticAppAddress, synthesizeManifest, validateManifest, vendorDependencies, writeManifest };
|
|
504
|
+
export { CURRENT_RUNTIME_RANGE, DEFAULT_BUNDLE_DIR, DEFAULT_CONFIG_DIR, DEFAULT_CRONS_DIR, DEFAULT_FUNCTIONS_DIR, DEFAULT_SCHEMA_FILE, ManifestError, VENDOR_SIZE_MAX_BYTES, VENDOR_SIZE_WARN_BYTES, VENDOR_TARGET_CPU, VENDOR_TARGET_OS, assessManagedCompatibility, buildBundle, buildStaticBundle, buildableApps, bundledNpmrc, cmsMountOf, collectDeclaredDependencies, commentSpans, compareMountOrder, composeBundleManifest, describeDepConflicts, detectDeclaredDepConflicts, detectFrameworkDepDrift, detectNativeDependencies, detectStorageAuthorize, entry, findBackendApp, findUnusedServerEntry, foldStaticIntoBundle, formatAppAddress, loadManifest, manifestExists, manifestPath, normalizeEsmSpecifiers, resolveBackendPaths, selectDeployApp, staticAppAddress, synthesizeManifest, validateManifest, vendorDependencies, writeManifest };
|
|
487
505
|
|
|
488
506
|
//# sourceMappingURL=index.es.js.map
|