@rebasepro/cli 0.25.1 → 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.
Files changed (151) hide show
  1. package/README.md +2 -1
  2. package/bin/rebase.js +143 -4
  3. package/dist/{agent-setup-BYb2Tbdz.js → agent-setup-D9mHRZ5R.js} +125 -3
  4. package/dist/agent-setup-D9mHRZ5R.js.map +1 -0
  5. package/dist/{api-keys-CSMbsmAn.js → api-keys-CyJ26KEJ.js} +41 -9
  6. package/dist/api-keys-CyJ26KEJ.js.map +1 -0
  7. package/dist/{apps-iBXNZhVN.js → apps-CnLDV5b6.js} +6 -6
  8. package/dist/{apps-iBXNZhVN.js.map → apps-CnLDV5b6.js.map} +1 -1
  9. package/dist/{atlas-dev-database-BusbHP6n.js → atlas-dev-database-BODqdCWt.js} +2 -2
  10. package/dist/{atlas-dev-database-BusbHP6n.js.map → atlas-dev-database-BODqdCWt.js.map} +1 -1
  11. package/dist/{auth-DRsTWPky.js → auth-dII2jCO1.js} +10 -7
  12. package/dist/auth-dII2jCO1.js.map +1 -0
  13. package/dist/{branch-pointer-Bn_FjNld.js → branch-pointer-BQUF6lYa.js} +1 -1
  14. package/dist/{build-et7Rccxi.js → build-Cza7ZQrp.js} +6 -6
  15. package/dist/{build-et7Rccxi.js.map → build-Cza7ZQrp.js.map} +1 -1
  16. package/dist/{bundle-DlqkDYSe.js → bundle-C6yEtMJ-.js} +53 -5
  17. package/dist/bundle-C6yEtMJ-.js.map +1 -0
  18. package/dist/bundle.d.ts +14 -0
  19. package/dist/{cloud-B-ZIjHrA.js → cloud-BdnmqQaZ.js} +8527 -4340
  20. package/dist/cloud-BdnmqQaZ.js.map +1 -0
  21. package/dist/collections-dir-DlvDhime.js +69 -0
  22. package/dist/collections-dir-DlvDhime.js.map +1 -0
  23. package/dist/commands/agent-setup.d.ts +58 -0
  24. package/dist/commands/api-keys.d.ts +13 -0
  25. package/dist/commands/cloud/activity.d.ts +25 -0
  26. package/dist/commands/cloud/app-key.d.ts +18 -0
  27. package/dist/commands/cloud/auth.d.ts +1 -0
  28. package/dist/commands/cloud/billing-invoices.d.ts +39 -0
  29. package/dist/commands/cloud/claim.d.ts +7 -0
  30. package/dist/commands/cloud/context.d.ts +115 -6
  31. package/dist/commands/cloud/deploy-summary.d.ts +162 -0
  32. package/dist/commands/cloud/deploy.d.ts +64 -0
  33. package/dist/commands/cloud/env.d.ts +24 -0
  34. package/dist/commands/cloud/index.d.ts +13 -1
  35. package/dist/commands/cloud/init.d.ts +143 -0
  36. package/dist/commands/cloud/login-flow.d.ts +51 -0
  37. package/dist/commands/cloud/notifications.d.ts +28 -0
  38. package/dist/commands/cloud/orgs.d.ts +13 -0
  39. package/dist/commands/cloud/previews.d.ts +123 -0
  40. package/dist/commands/cloud/resources.d.ts +68 -14
  41. package/dist/commands/cloud/runtime-logs.d.ts +176 -0
  42. package/dist/commands/cloud/service-key.d.ts +15 -0
  43. package/dist/commands/cloud/token-capabilities.d.ts +61 -8
  44. package/dist/commands/cloud/tokens.d.ts +18 -3
  45. package/dist/commands/cloud/usage.d.ts +63 -0
  46. package/dist/commands/dev.d.ts +10 -0
  47. package/dist/commands/doctor.d.ts +1 -1
  48. package/dist/commands/generate-view.d.ts +94 -0
  49. package/dist/commands/generate_sdk.d.ts +15 -0
  50. package/dist/commands/skills.d.ts +4 -3
  51. package/dist/commands/storage.d.ts +4 -0
  52. package/dist/commands/verify.d.ts +96 -0
  53. package/dist/{consent-BaB-eQKG.js → consent-BD7F29T3.js} +2 -2
  54. package/dist/{consent-BaB-eQKG.js.map → consent-BD7F29T3.js.map} +1 -1
  55. package/dist/{console-BlD9kjFW.js → console-BXB6-8GT.js} +12 -6
  56. package/dist/console-BXB6-8GT.js.map +1 -0
  57. package/dist/{context-DHiiiJ5C.js → context-GUxkZm-S.js} +481 -24
  58. package/dist/context-GUxkZm-S.js.map +1 -0
  59. package/dist/{daemon-DDMRbz4T.js → daemon-Cp7oNXth.js} +2 -2
  60. package/dist/{daemon-DDMRbz4T.js.map → daemon-Cp7oNXth.js.map} +1 -1
  61. package/dist/{db-9P6MnmdC.js → db-KzlqddGD.js} +37 -30
  62. package/dist/db-KzlqddGD.js.map +1 -0
  63. package/dist/{derive-MTdClnkc.js → derive-ae9UOoOB.js} +2 -2
  64. package/dist/{derive-MTdClnkc.js.map → derive-ae9UOoOB.js.map} +1 -1
  65. package/dist/{dev-BDN_OKXA.js → dev-DTqVMgB3.js} +59 -32
  66. package/dist/dev-DTqVMgB3.js.map +1 -0
  67. package/dist/{dev-preflight-FT9GbJVj.js → dev-preflight-Cxv3TiD1.js} +2 -2
  68. package/dist/{dev-preflight-FT9GbJVj.js.map → dev-preflight-Cxv3TiD1.js.map} +1 -1
  69. package/dist/{dev-server-CIZwAfZa.js → dev-server-OJsUGZEB.js} +2 -2
  70. package/dist/{dev-server-CIZwAfZa.js.map → dev-server-OJsUGZEB.js.map} +1 -1
  71. package/dist/{doctor-D8YXz7df.js → doctor-BRWOlqeG.js} +13 -11
  72. package/dist/doctor-BRWOlqeG.js.map +1 -0
  73. package/dist/{eject-izG2KjMo.js → eject-DABcDnPN.js} +3 -3
  74. package/dist/{eject-izG2KjMo.js.map → eject-DABcDnPN.js.map} +1 -1
  75. package/dist/{fold-static-CybSay_W.js → fold-static-BnAK-anQ.js} +3 -3
  76. package/dist/{fold-static-CybSay_W.js.map → fold-static-BnAK-anQ.js.map} +1 -1
  77. package/dist/generate-view-IFwCADvb.js +662 -0
  78. package/dist/generate-view-IFwCADvb.js.map +1 -0
  79. package/dist/{generate_sdk-B4R65oUV.js → generate_sdk-BvcWvoUh.js} +33 -7
  80. package/dist/generate_sdk-BvcWvoUh.js.map +1 -0
  81. package/dist/index.es.js +57 -38
  82. package/dist/index.es.js.map +1 -1
  83. package/dist/{init-DYaeppEN.js → init-CaU6GhwI.js} +8 -8
  84. package/dist/{init-DYaeppEN.js.map → init-CaU6GhwI.js.map} +1 -1
  85. package/dist/last-dev-database-DpW5dfoX.js +2 -0
  86. package/dist/{manifest-nvPdLlJY.js → manifest-BtzDy7KQ.js} +36 -3
  87. package/dist/{manifest-nvPdLlJY.js.map → manifest-BtzDy7KQ.js.map} +1 -1
  88. package/dist/{normalize-imports-BYw8ad87.js → normalize-imports-D0zXlM6g.js} +3 -3
  89. package/dist/{normalize-imports-BYw8ad87.js.map → normalize-imports-D0zXlM6g.js.map} +1 -1
  90. package/dist/{path-flags-BFgG9V6y.js → path-flags-DNvtEi2-.js} +5 -4
  91. package/dist/path-flags-DNvtEi2-.js.map +1 -0
  92. package/dist/{prepare-1rVNd2PF.js → prepare-CTw9NEkh.js} +4 -4
  93. package/dist/{prepare-1rVNd2PF.js.map → prepare-CTw9NEkh.js.map} +1 -1
  94. package/dist/{project-g4K6kV1t.js → project-CasK56vN.js} +2 -2
  95. package/dist/{project-g4K6kV1t.js.map → project-CasK56vN.js.map} +1 -1
  96. package/dist/resolve-D647F1LA.js +2 -0
  97. package/dist/{resources-CovP8AZ-.js → resources-CPSC5Kcu.js} +4 -4
  98. package/dist/{resources-CovP8AZ-.js.map → resources-CPSC5Kcu.js.map} +1 -1
  99. package/dist/{schema-nuxvvc50.js → schema-BSXwZSiI.js} +9 -7
  100. package/dist/schema-BSXwZSiI.js.map +1 -0
  101. package/dist/{skills-DeUIsZcT.js → skills-BU2flMOy.js} +52 -7
  102. package/dist/skills-BU2flMOy.js.map +1 -0
  103. package/dist/{start-RzZqDroW.js → start-mVb6upwY.js} +5 -5
  104. package/dist/{start-RzZqDroW.js.map → start-mVb6upwY.js.map} +1 -1
  105. package/dist/static-syntax-check.d.ts +64 -0
  106. package/dist/{status-D9Zm88NZ.js → status-BREvtzJm.js} +7 -7
  107. package/dist/{status-D9Zm88NZ.js.map → status-BREvtzJm.js.map} +1 -1
  108. package/dist/{storage-BB3umRfw.js → storage-DtOXGflp.js} +159 -15
  109. package/dist/storage-DtOXGflp.js.map +1 -0
  110. package/dist/{telemetry-HfU5uAh1.js → telemetry-CgwJPVMO.js} +2 -2
  111. package/dist/{telemetry-HfU5uAh1.js.map → telemetry-CgwJPVMO.js.map} +1 -1
  112. package/dist/{telemetry-TseNLk6X.js → telemetry-DwK5RQJl.js} +4 -4
  113. package/dist/{telemetry-TseNLk6X.js.map → telemetry-DwK5RQJl.js.map} +1 -1
  114. package/dist/{upgrade-apiPKKE_.js → upgrade-B7sVwL8S.js} +4 -4
  115. package/dist/{upgrade-apiPKKE_.js.map → upgrade-B7sVwL8S.js.map} +1 -1
  116. package/dist/utils/collections-dir.d.ts +14 -0
  117. package/dist/utils/path-flags.d.ts +2 -1
  118. package/dist/utils/tool-stdio.d.ts +1 -1
  119. package/dist/verify-D7UsV_qe.js +730 -0
  120. package/dist/verify-D7UsV_qe.js.map +1 -0
  121. package/package.json +9 -7
  122. package/templates/eject/backend/src/index.ts +9 -1
  123. package/templates/generated-schemas/ecommerce.ts +3 -0
  124. package/templates/overlays/baas/ai-instructions.md +13 -0
  125. package/templates/template/.claude/hooks/post-edit-collection.sh +99 -0
  126. package/templates/template/.claude/settings.json +17 -0
  127. package/templates/template/.env.example +10 -1
  128. package/templates/template/ai-instructions.md +21 -1
  129. package/templates/template/config/collections/presets/ecommerce/index.ts +23 -0
  130. package/templates/template/docker-compose.yml +4 -1
  131. package/templates/template/frontend/package.json +1 -0
  132. package/templates/views/AppView.tsx.tmpl +138 -0
  133. package/templates/views/EntityView.tsx.tmpl +64 -0
  134. package/templates/views/index.ts.tmpl +8 -0
  135. package/dist/agent-setup-BYb2Tbdz.js.map +0 -1
  136. package/dist/api-keys-CSMbsmAn.js.map +0 -1
  137. package/dist/auth-DRsTWPky.js.map +0 -1
  138. package/dist/bundle-DlqkDYSe.js.map +0 -1
  139. package/dist/cloud-B-ZIjHrA.js.map +0 -1
  140. package/dist/console-BlD9kjFW.js.map +0 -1
  141. package/dist/context-DHiiiJ5C.js.map +0 -1
  142. package/dist/db-9P6MnmdC.js.map +0 -1
  143. package/dist/dev-BDN_OKXA.js.map +0 -1
  144. package/dist/doctor-D8YXz7df.js.map +0 -1
  145. package/dist/generate_sdk-B4R65oUV.js.map +0 -1
  146. package/dist/last-dev-database-B_75fxZC.js +0 -2
  147. package/dist/path-flags-BFgG9V6y.js.map +0 -1
  148. package/dist/resolve-BQUAC3Wi.js +0 -2
  149. package/dist/schema-nuxvvc50.js.map +0 -1
  150. package/dist/skills-DeUIsZcT.js.map +0 -1
  151. package/dist/storage-BB3umRfw.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,9 +1,9 @@
1
1
  import { n as getPMCommands, t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
2
- import { c as findProjectRoot, d as readEnvFile } from "./project-g4K6kV1t.js";
3
- import { d as findBackendApp, m as manifestExists, p as loadManifest, x as writeManifest } from "./manifest-nvPdLlJY.js";
4
- import { t as DEV_BACKEND_URL_ENV } from "./dev-server-CIZwAfZa.js";
5
- import { M as readLink } from "./context-DHiiiJ5C.js";
6
- import { n as COLLECTIONS_PATH_RULE, t as COLLECTIONS_FLAG_HELP } from "./path-flags-BFgG9V6y.js";
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
7
  import { t as Refusal } from "./refusal-ReeeGP8a.js";
8
8
  import { n as isLoadedCollectionFile } from "./collection-drift-BKj_BoMq.js";
9
9
  import chalk from "chalk";
@@ -83,6 +83,32 @@ function writeRegistration(dir, databaseTypes) {
83
83
  writeIfChanged(registerPath, REGISTER_SOURCE);
84
84
  }
85
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
+ /**
86
112
  * Whether `rebase.json` asks for the registration (`registerDatabase: true` on
87
113
  * the backend app). That is what survives a clone: `generated/` is gitignored,
88
114
  * so a `register.ts` from an earlier run is not there to say it.
@@ -494,6 +520,6 @@ export const SCHEMA_VERSION = ${JSON.stringify(schemaVersion)};
494
520
  console.log("");
495
521
  }
496
522
  //#endregion
497
- export { generateSdkCommand };
523
+ export { generateSdkCommand, writeRegistrationForBuild };
498
524
 
499
- //# sourceMappingURL=generate_sdk-B4R65oUV.js.map
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,8 +1,8 @@
1
- import { i as recordEvent, n as isEnabled, u as errorClass } from "./telemetry-HfU5uAh1.js";
2
- import { T as unknownCommand, b as parseCommandArgs, p as requireProjectRoot } from "./project-g4K6kV1t.js";
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";
3
3
  import { n as cliVersion } from "./version-Buyyo1ut.js";
4
- import { _ as selectDeployApp, a as DEFAULT_SCHEMA_FILE, b as validateManifest, c as buildableApps, d as findBackendApp, f as formatAppAddress, g as resolveBackendPaths, h as manifestPath, i as DEFAULT_FUNCTIONS_DIR, l as cmsMountOf, m as manifestExists, n as DEFAULT_CONFIG_DIR, o as ManifestError, p as loadManifest, r as DEFAULT_CRONS_DIR, s as assessManagedCompatibility, t as CURRENT_RUNTIME_RANGE, u as compareMountOrder, v as staticAppAddress, x as writeManifest, y as synthesizeManifest } from "./manifest-nvPdLlJY.js";
5
- import { _ as foldStaticIntoBundle, a as VENDOR_TARGET_OS, c as collectDeclaredDependencies, d as describeDepConflicts, f as detectDeclaredDepConflicts, g as findUnusedServerEntry, h as detectStorageAuthorize, i as VENDOR_TARGET_CPU, l as commentSpans, m as detectNativeDependencies, n as VENDOR_SIZE_MAX_BYTES, o as buildBundle, p as detectFrameworkDepDrift, r as VENDOR_SIZE_WARN_BYTES, s as buildStaticBundle, t as DEFAULT_BUNDLE_DIR, u as composeBundleManifest, v as normalizeEsmSpecifiers, y as vendorDependencies } from "./bundle-DlqkDYSe.js";
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";
6
6
  import chalk from "chalk";
7
7
  import arg from "arg";
8
8
  import path from "path";
@@ -59,12 +59,14 @@ var namespacedCommands = [
59
59
  "start",
60
60
  "auth",
61
61
  "doctor",
62
+ "verify",
62
63
  "skills",
63
64
  "api-keys",
64
65
  "storage",
65
66
  "cloud",
66
67
  "apps",
67
68
  "eject",
69
+ "generate",
68
70
  "generate-sdk",
69
71
  "telemetry",
70
72
  "resources",
@@ -88,39 +90,43 @@ var NO_VOCABULARY = {
88
90
  async function commandVocabulary(command) {
89
91
  switch (command) {
90
92
  case "schema": return {
91
- subcommands: (await import("./schema-nuxvvc50.js")).SCHEMA_SUBCOMMANDS,
93
+ subcommands: (await import("./schema-BSXwZSiI.js")).SCHEMA_SUBCOMMANDS,
92
94
  aliases: {}
93
95
  };
94
96
  case "db": return {
95
- subcommands: (await import("./db-9P6MnmdC.js")).DB_SUBCOMMANDS,
97
+ subcommands: (await import("./db-KzlqddGD.js")).DB_SUBCOMMANDS,
96
98
  aliases: {}
97
99
  };
98
100
  case "auth": return {
99
- subcommands: (await import("./auth-DRsTWPky.js")).AUTH_SUBCOMMANDS,
101
+ subcommands: (await import("./auth-dII2jCO1.js")).AUTH_SUBCOMMANDS,
100
102
  aliases: {}
101
103
  };
102
104
  case "skills": return {
103
- subcommands: (await import("./skills-DeUIsZcT.js")).SKILLS_SUBCOMMANDS,
105
+ subcommands: (await import("./skills-BU2flMOy.js")).SKILLS_SUBCOMMANDS,
104
106
  aliases: {}
105
107
  };
106
108
  case "api-keys": return {
107
- subcommands: (await import("./api-keys-CSMbsmAn.js")).API_KEYS_SUBCOMMANDS,
109
+ subcommands: (await import("./api-keys-CyJ26KEJ.js")).API_KEYS_SUBCOMMANDS,
108
110
  aliases: {}
109
111
  };
110
112
  case "storage": return {
111
- subcommands: (await import("./storage-BB3umRfw.js")).STORAGE_SUBCOMMANDS,
113
+ subcommands: (await import("./storage-DtOXGflp.js")).STORAGE_SUBCOMMANDS,
112
114
  aliases: {}
113
115
  };
114
116
  case "apps": return {
115
- subcommands: (await import("./apps-iBXNZhVN.js")).APPS_SUBCOMMANDS,
117
+ subcommands: (await import("./apps-CnLDV5b6.js")).APPS_SUBCOMMANDS,
116
118
  aliases: {}
117
119
  };
118
120
  case "telemetry": return {
119
- subcommands: (await import("./telemetry-TseNLk6X.js")).TELEMETRY_SUBCOMMANDS,
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,
120
126
  aliases: {}
121
127
  };
122
128
  case "cloud": {
123
- const cloud = await import("./cloud-B-ZIjHrA.js");
129
+ const cloud = await import("./cloud-BdnmqQaZ.js");
124
130
  return {
125
131
  subcommands: cloud.CLOUD_GROUP_NAMES,
126
132
  aliases: cloud.GROUP_ALIASES
@@ -225,6 +231,7 @@ async function entry(args) {
225
231
  error_type: errorClass(error),
226
232
  usage: Boolean(error && typeof error === "object" && error.isUsageError)
227
233
  }, { projectRoot: process.cwd() });
234
+ if (error instanceof UsageError && wantsJsonOutput(args)) failAsJson(error.message, "usage", `Run \`rebase ${command} --help\` for the flags it takes.`);
228
235
  throw error;
229
236
  }
230
237
  }
@@ -247,7 +254,7 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
247
254
  return;
248
255
  }
249
256
  case "init": {
250
- const { createRebaseApp } = await import("./init-DYaeppEN.js");
257
+ const { createRebaseApp } = await import("./init-CaU6GhwI.js");
251
258
  await createRebaseApp(args);
252
259
  break;
253
260
  }
@@ -270,9 +277,9 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
270
277
  maxPositionals: 0
271
278
  });
272
279
  const sdkRoot = sdkHelp ? process.cwd() : requireProjectRoot();
273
- const { generateSdkCommand } = await import("./generate_sdk-B4R65oUV.js");
280
+ const { generateSdkCommand } = await import("./generate_sdk-BvcWvoUh.js");
274
281
  await generateSdkCommand({
275
- 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)),
276
283
  output: sdkArgs["--output"] || path.join(sdkRoot, "generated/sdk"),
277
284
  from: sdkArgs["--from"],
278
285
  token: sdkArgs["--token"],
@@ -284,101 +291,111 @@ async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespac
284
291
  break;
285
292
  }
286
293
  case "schema": {
287
- const { schemaCommand } = await import("./schema-nuxvvc50.js");
294
+ const { schemaCommand } = await import("./schema-BSXwZSiI.js");
288
295
  await schemaCommand(effectiveSubcommand, args);
289
296
  break;
290
297
  }
291
298
  case "db": {
292
- const { dbCommand } = await import("./db-9P6MnmdC.js");
299
+ const { dbCommand } = await import("./db-KzlqddGD.js");
293
300
  await dbCommand(effectiveSubcommand, args);
294
301
  break;
295
302
  }
296
303
  case "console": {
297
- const { consoleCommand } = await import("./console-BlD9kjFW.js");
304
+ const { consoleCommand } = await import("./console-BXB6-8GT.js");
298
305
  await consoleCommand(args);
299
306
  break;
300
307
  }
301
308
  case "dev": {
302
- const { devCommand } = await import("./dev-BDN_OKXA.js");
309
+ const { devCommand } = await import("./dev-DTqVMgB3.js");
303
310
  await devCommand(args);
304
311
  break;
305
312
  }
306
313
  case "normalize-imports": {
307
- const { normalizeImportsCommand } = await import("./normalize-imports-BYw8ad87.js");
314
+ const { normalizeImportsCommand } = await import("./normalize-imports-D0zXlM6g.js");
308
315
  await normalizeImportsCommand(args);
309
316
  break;
310
317
  }
311
318
  case "build": {
312
- const { buildCommand } = await import("./build-et7Rccxi.js").then((n) => n.n);
319
+ const { buildCommand } = await import("./build-Cza7ZQrp.js").then((n) => n.n);
313
320
  await buildCommand(args);
314
321
  break;
315
322
  }
316
323
  case "start": {
317
- const { startCommand } = await import("./start-RzZqDroW.js");
324
+ const { startCommand } = await import("./start-mVb6upwY.js");
318
325
  await startCommand(args);
319
326
  break;
320
327
  }
321
328
  case "upgrade": {
322
- const { upgradeCommand } = await import("./upgrade-apiPKKE_.js");
329
+ const { upgradeCommand } = await import("./upgrade-B7sVwL8S.js");
323
330
  await upgradeCommand(args);
324
331
  break;
325
332
  }
326
333
  case "apps": {
327
- const { appsCommand } = await import("./apps-iBXNZhVN.js");
334
+ const { appsCommand } = await import("./apps-CnLDV5b6.js");
328
335
  await appsCommand(effectiveSubcommand, args);
329
336
  break;
330
337
  }
338
+ case "generate": {
339
+ const { generateCommand } = await import("./generate-view-IFwCADvb.js");
340
+ await generateCommand(effectiveSubcommand, args);
341
+ break;
342
+ }
331
343
  case "eject": {
332
- const { ejectCommand } = await import("./eject-izG2KjMo.js");
344
+ const { ejectCommand } = await import("./eject-DABcDnPN.js");
333
345
  await ejectCommand(args);
334
346
  break;
335
347
  }
336
348
  case "auth": {
337
- const { authCommand } = await import("./auth-DRsTWPky.js");
349
+ const { authCommand } = await import("./auth-dII2jCO1.js");
338
350
  await authCommand(effectiveSubcommand, args);
339
351
  break;
340
352
  }
341
353
  case "status": {
342
- const { statusCommand } = await import("./status-D9Zm88NZ.js");
354
+ const { statusCommand } = await import("./status-BREvtzJm.js");
343
355
  await statusCommand(args);
344
356
  break;
345
357
  }
346
358
  case "resources": {
347
- const { resourcesCommand } = await import("./resources-CovP8AZ-.js");
359
+ const { resourcesCommand } = await import("./resources-CPSC5Kcu.js");
348
360
  await resourcesCommand(args);
349
361
  break;
350
362
  }
351
363
  case "doctor": {
352
- const { doctorCommand } = await import("./doctor-D8YXz7df.js");
364
+ const { doctorCommand } = await import("./doctor-BRWOlqeG.js");
353
365
  await doctorCommand(args);
354
366
  break;
355
367
  }
368
+ case "verify": {
369
+ const { verifyCommand } = await import("./verify-D7UsV_qe.js");
370
+ await verifyCommand(args);
371
+ break;
372
+ }
356
373
  case "skills": {
357
- const { skillsCommand } = await import("./skills-DeUIsZcT.js");
374
+ const { skillsCommand } = await import("./skills-BU2flMOy.js");
358
375
  await skillsCommand(effectiveSubcommand, args);
359
376
  break;
360
377
  }
361
378
  case "api-keys": {
362
- const { apiKeysCommand } = await import("./api-keys-CSMbsmAn.js");
379
+ const { apiKeysCommand } = await import("./api-keys-CyJ26KEJ.js");
363
380
  await apiKeysCommand(effectiveSubcommand, args);
364
381
  break;
365
382
  }
366
383
  case "storage": {
367
- const { storageCommand } = await import("./storage-BB3umRfw.js");
384
+ const { storageCommand } = await import("./storage-DtOXGflp.js");
368
385
  await storageCommand(effectiveSubcommand, args);
369
386
  break;
370
387
  }
371
388
  case "cloud": {
372
- const { cloudCommand } = await import("./cloud-B-ZIjHrA.js");
389
+ const { cloudCommand } = await import("./cloud-BdnmqQaZ.js");
373
390
  await cloudCommand(effectiveSubcommand, args);
374
391
  break;
375
392
  }
376
393
  case "telemetry": {
377
- const { telemetryCommand } = await import("./telemetry-TseNLk6X.js");
394
+ const { telemetryCommand } = await import("./telemetry-DwK5RQJl.js");
378
395
  await telemetryCommand(args);
379
396
  break;
380
397
  }
381
- default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-B-ZIjHrA.js")).CLOUD_GROUP_NAMES });
398
+ default: unknownCommand(command, namespacedCommands, "", { cloud: (await import("./cloud-BdnmqQaZ.js")).CLOUD_GROUP_NAMES });
382
399
  }
383
400
  }
384
401
  /** The global help. Exported so its Options block can be held against {@link ROOT_FLAGS}. */
@@ -417,7 +434,8 @@ ${chalk.green.bold("Database")}
417
434
  ${chalk.green.bold("Explore")}
418
435
  ${chalk.blue.bold("console")} A REPL with the project's data in scope ${chalk.gray("(-e <code> runs one snippet)")}
419
436
 
420
- ${chalk.green.bold("SDK")}
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)")}
421
439
  ${chalk.blue.bold("generate-sdk")} Generate a typed TypeScript SDK from collections
422
440
 
423
441
  ${chalk.green.bold("Auth")}
@@ -427,6 +445,7 @@ ${chalk.green.bold("Auth")}
427
445
  ${chalk.green.bold("Diagnostics")}
428
446
  ${chalk.blue.bold("status")} Show every resource and whether its variables are set
429
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)")}
430
449
  ${chalk.blue.bold("resources")} List the databases, buckets and topics this project declares
431
450
 
432
451
  ${chalk.green.bold("Take ownership")}
@@ -482,6 +501,6 @@ function telemetryNotice() {
482
501
  return chalk.gray(`Usage sharing: ${sharing ? "on" : "off"} — ${chalk.cyan("rebase telemetry")} to inspect or change\n`);
483
502
  }
484
503
  //#endregion
485
- 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 };
486
505
 
487
506
  //# sourceMappingURL=index.es.js.map