@rebasepro/cli 0.23.0 → 0.24.1-canary.g19596ef

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/README.md +19 -3
  2. package/bin/rebase.js +4 -1
  3. package/dist/agent-setup-B31F00DC.js +324 -0
  4. package/dist/agent-setup-B31F00DC.js.map +1 -0
  5. package/dist/api-keys-Bl1I9q7M.js +525 -0
  6. package/dist/api-keys-Bl1I9q7M.js.map +1 -0
  7. package/dist/apps-CNgQJjg5.js +340 -0
  8. package/dist/apps-CNgQJjg5.js.map +1 -0
  9. package/dist/args-BnmsEXvu.js +109 -0
  10. package/dist/args-BnmsEXvu.js.map +1 -0
  11. package/dist/atlas-dev-database-D_LP_Woq.js +62 -0
  12. package/dist/atlas-dev-database-D_LP_Woq.js.map +1 -0
  13. package/dist/auth-aySHEF45.js +414 -0
  14. package/dist/auth-aySHEF45.js.map +1 -0
  15. package/dist/branch-pointer-DvSHBjjz.js +2 -0
  16. package/dist/build-DIHWIqO4.js +336 -0
  17. package/dist/build-DIHWIqO4.js.map +1 -0
  18. package/dist/bundle-CqURVN-K.js +1621 -0
  19. package/dist/bundle-CqURVN-K.js.map +1 -0
  20. package/dist/bundle.d.ts +12 -3
  21. package/dist/cli.d.ts +23 -2
  22. package/dist/cloud-DjByQlkW.js +9667 -0
  23. package/dist/cloud-DjByQlkW.js.map +1 -0
  24. package/dist/collection-drift-BKj_BoMq.js +106 -0
  25. package/dist/collection-drift-BKj_BoMq.js.map +1 -0
  26. package/dist/commands/__test_support__/parser-specs.d.ts +13 -0
  27. package/dist/commands/agent-setup.d.ts +116 -0
  28. package/dist/commands/api-keys.d.ts +86 -23
  29. package/dist/commands/apps.d.ts +17 -0
  30. package/dist/commands/auth.d.ts +7 -0
  31. package/dist/commands/build.d.ts +5 -1
  32. package/dist/commands/cloud/auth.d.ts +4 -3
  33. package/dist/commands/cloud/bundle-deploy.d.ts +45 -0
  34. package/dist/commands/cloud/context.d.ts +44 -5
  35. package/dist/commands/cloud/cron.d.ts +53 -0
  36. package/dist/commands/cloud/debug.d.ts +134 -0
  37. package/dist/commands/cloud/index.d.ts +89 -12
  38. package/dist/commands/cloud/token-capabilities.d.ts +76 -0
  39. package/dist/commands/cloud/tokens.d.ts +23 -0
  40. package/dist/commands/console.d.ts +12 -0
  41. package/dist/commands/db.d.ts +79 -25
  42. package/dist/commands/dev.d.ts +181 -13
  43. package/dist/commands/doctor.d.ts +5 -0
  44. package/dist/commands/generate_sdk.d.ts +29 -2
  45. package/dist/commands/init.d.ts +115 -14
  46. package/dist/commands/schema.d.ts +6 -0
  47. package/dist/commands/skills.d.ts +126 -7
  48. package/dist/commands/start.d.ts +44 -0
  49. package/dist/commands/storage.d.ts +46 -0
  50. package/dist/commands/upgrade.d.ts +1 -0
  51. package/dist/consent-ClRHmcxf.js +76 -0
  52. package/dist/consent-ClRHmcxf.js.map +1 -0
  53. package/dist/console-D6SJf8k_.js +102 -0
  54. package/dist/console-D6SJf8k_.js.map +1 -0
  55. package/dist/context-BqhRydBg.js +1234 -0
  56. package/dist/context-BqhRydBg.js.map +1 -0
  57. package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
  58. package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
  59. package/dist/daemon-pzsQwDHa.js +2 -0
  60. package/dist/db-B7RuNuaQ.js +1312 -0
  61. package/dist/db-B7RuNuaQ.js.map +1 -0
  62. package/dist/derive-Dl0z2OWi.js +484 -0
  63. package/dist/derive-Dl0z2OWi.js.map +1 -0
  64. package/dist/dev-CYr_WXan.js +1599 -0
  65. package/dist/dev-CYr_WXan.js.map +1 -0
  66. package/dist/dev-db/atlas-dev-database.d.ts +32 -0
  67. package/dist/dev-db/daemon-entry.d.ts +13 -0
  68. package/dist/dev-db/daemon.d.ts +10 -0
  69. package/dist/dev-db/last-dev-database.d.ts +41 -0
  70. package/dist/dev-db/prepare.d.ts +29 -3
  71. package/dist/dev-db/pull.d.ts +90 -5
  72. package/dist/dev-db/resolve.d.ts +26 -2
  73. package/dist/dev-preflight-B-LYyBf1.js +2 -0
  74. package/dist/dev-server-DG8Tt-uf.js +96 -0
  75. package/dist/dev-server-DG8Tt-uf.js.map +1 -0
  76. package/dist/doctor-BP8cZ-7F.js +771 -0
  77. package/dist/doctor-BP8cZ-7F.js.map +1 -0
  78. package/dist/eject-DizdoecV.js +335 -0
  79. package/dist/eject-DizdoecV.js.map +1 -0
  80. package/dist/fold-static-BC9CYicw.js +201 -0
  81. package/dist/fold-static-BC9CYicw.js.map +1 -0
  82. package/dist/fold-static.d.ts +26 -3
  83. package/dist/function-portability-BIvlvR9q.js +265 -0
  84. package/dist/function-portability-BIvlvR9q.js.map +1 -0
  85. package/dist/generate_sdk-BPqdJc3Q.js +489 -0
  86. package/dist/generate_sdk-BPqdJc3Q.js.map +1 -0
  87. package/dist/index.es.js +199 -22095
  88. package/dist/index.es.js.map +1 -1
  89. package/dist/init-Utstvh2Q.js +1149 -0
  90. package/dist/init-Utstvh2Q.js.map +1 -0
  91. package/dist/last-dev-database-B58g89uA.js +2 -0
  92. package/dist/manifest-DRp0UVTj.js +880 -0
  93. package/dist/manifest-DRp0UVTj.js.map +1 -0
  94. package/dist/manifest.d.ts +56 -4
  95. package/dist/normalize-imports-X0Tgze9y.js +107 -0
  96. package/dist/normalize-imports-X0Tgze9y.js.map +1 -0
  97. package/dist/package-manager-DSEOwTqM.js +193 -0
  98. package/dist/package-manager-DSEOwTqM.js.map +1 -0
  99. package/dist/path-flags-BFgG9V6y.js +91 -0
  100. package/dist/path-flags-BFgG9V6y.js.map +1 -0
  101. package/dist/precompress.d.ts +17 -0
  102. package/dist/prepare-CDN6lSpz.js +1236 -0
  103. package/dist/prepare-CDN6lSpz.js.map +1 -0
  104. package/dist/{project-3WCbrrfW.js → project-Wp2zoyeN.js} +34 -184
  105. package/dist/project-Wp2zoyeN.js.map +1 -0
  106. package/dist/pull-CrGYMEsy.js +458 -0
  107. package/dist/pull-CrGYMEsy.js.map +1 -0
  108. package/dist/resolve-B2O-wKKk.js +2 -0
  109. package/dist/resources-FD7AfZx8.js +183 -0
  110. package/dist/resources-FD7AfZx8.js.map +1 -0
  111. package/dist/schema-DMdr431S.js +125 -0
  112. package/dist/schema-DMdr431S.js.map +1 -0
  113. package/dist/skills-DTFibT1m.js +642 -0
  114. package/dist/skills-DTFibT1m.js.map +1 -0
  115. package/dist/start-DEa-hOBh.js +267 -0
  116. package/dist/start-DEa-hOBh.js.map +1 -0
  117. package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
  118. package/dist/state-Do7ZJYkF.js.map +1 -0
  119. package/dist/status-DxnJTekv.js +352 -0
  120. package/dist/status-DxnJTekv.js.map +1 -0
  121. package/dist/storage-DyVq-f_F.js +303 -0
  122. package/dist/storage-DyVq-f_F.js.map +1 -0
  123. package/dist/telemetry/identity.d.ts +10 -1
  124. package/dist/telemetry-C8Uq8phb.js +129 -0
  125. package/dist/telemetry-C8Uq8phb.js.map +1 -0
  126. package/dist/telemetry-EMFRVRQi.js +351 -0
  127. package/dist/telemetry-EMFRVRQi.js.map +1 -0
  128. package/dist/unknown-command-DNwDcX3w.js +98 -0
  129. package/dist/unknown-command-DNwDcX3w.js.map +1 -0
  130. package/dist/upgrade-CtZtRkTE.js +1332 -0
  131. package/dist/upgrade-CtZtRkTE.js.map +1 -0
  132. package/dist/upgrade.d.ts +38 -5
  133. package/dist/utils/dev-preflight.d.ts +47 -5
  134. package/dist/utils/dev-server.d.ts +30 -0
  135. package/dist/utils/path-flags.d.ts +31 -0
  136. package/dist/utils/project.d.ts +16 -0
  137. package/dist/utils/temp-archive.d.ts +9 -0
  138. package/dist/version-Buyyo1ut.js +58 -0
  139. package/dist/version-Buyyo1ut.js.map +1 -0
  140. package/package.json +7 -7
  141. package/templates/eject/Dockerfile +4 -2
  142. package/templates/eject/backend/src/env.ts +1 -1
  143. package/templates/eject/backend/src/index.ts +42 -4
  144. package/templates/eject/docker-compose.custom.yml +8 -4
  145. package/templates/generated-schemas/blank.ts +40 -0
  146. package/templates/generated-schemas/blog.ts +127 -0
  147. package/templates/generated-schemas/ecommerce.ts +93 -0
  148. package/templates/overlays/baas/ai-instructions.md +1 -1
  149. package/templates/overlays/baas/config/package.json +1 -0
  150. package/templates/overlays/baas/config/storage.ts +5 -3
  151. package/templates/overlays/baas/package.json +1 -0
  152. package/templates/template/.cursorrules +1 -1
  153. package/templates/template/.env.example +20 -10
  154. package/templates/template/.github/copilot-instructions.md +1 -1
  155. package/templates/template/.mcp.json +2 -2
  156. package/templates/template/.windsurfrules +1 -1
  157. package/templates/template/AGENTS.md +1 -1
  158. package/templates/template/CLAUDE.md +1 -1
  159. package/templates/template/README.md +21 -15
  160. package/templates/template/ai-instructions.md +5 -4
  161. package/templates/template/backend/functions/hello.ts +8 -0
  162. package/templates/template/backend/package.json +1 -1
  163. package/templates/template/config/resources.ts +7 -6
  164. package/templates/template/config/storage.ts +5 -3
  165. package/templates/template/docker-compose.yml +15 -9
  166. package/templates/template/frontend/vite.config.ts +13 -3
  167. package/templates/template/gitignore +6 -1
  168. package/templates/template/package.json +5 -3
  169. package/templates/template/scripts/example.ts +6 -4
  170. package/templates/template/tsconfig.json +25 -0
  171. package/dist/branch-pointer-dBiClJ0p.js +0 -111
  172. package/dist/branch-pointer-dBiClJ0p.js.map +0 -1
  173. package/dist/constraints-DKGbNfUW.js +0 -48
  174. package/dist/constraints-DKGbNfUW.js.map +0 -1
  175. package/dist/daemon-DR9Tk0La.js +0 -355
  176. package/dist/daemon-DR9Tk0La.js.map +0 -1
  177. package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
  178. package/dist/dev-preflight-CNLl4rdo.js +0 -367
  179. package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
  180. package/dist/project-3WCbrrfW.js.map +0 -1
  181. package/dist/pull-Dywm5FWP.js +0 -232
  182. package/dist/pull-Dywm5FWP.js.map +0 -1
  183. package/dist/resolve-BAeRUBhg.js +0 -74
  184. package/dist/resolve-BAeRUBhg.js.map +0 -1
  185. package/dist/state-C59Elrnt.js.map +0 -1
  186. package/templates/template/backend/src/schema.generated.ts +0 -13
@@ -0,0 +1,183 @@
1
+ import { i as failAsJson, p as requireProjectRoot } from "./project-Wp2zoyeN.js";
2
+ import { n as parseCommandArgs, r as wantsHelp } from "./args-BnmsEXvu.js";
3
+ import { d as findBackendApp, o as ManifestError, p as loadManifest } from "./manifest-DRp0UVTj.js";
4
+ import { a as projectResourceGraph, l as writeResourceGraphFile, n as deriveOptionsFor, o as readResourceGraphFile, r as deriveResourceGraph, s as serializeResourceGraph, t as RESOURCE_GRAPH_FILENAME } from "./derive-Dl0z2OWi.js";
5
+ import chalk from "chalk";
6
+ import path from "path";
7
+ import { declaredSubscriptions } from "@rebasepro/types";
8
+ //#region src/commands/resources.ts
9
+ /**
10
+ * CLI command: rebase resources
11
+ *
12
+ * Shows what a project declares, and keeps the committed graph honest.
13
+ *
14
+ * The graph is generated, so it can drift the moment somebody adds a bucket and
15
+ * does not regenerate. Drift here is not cosmetic: the committed file is what a
16
+ * host reads to decide what to provision, so a stale one means the console
17
+ * offers a project one set of resources while the runtime asks for another.
18
+ * `--check` is the gate that makes that impossible to land.
19
+ */
20
+ function usage() {
21
+ console.log(`
22
+ ${chalk.bold("rebase resources")} — what this project needs
23
+
24
+ ${chalk.blue("rebase resources")} List them, declared and implicit
25
+ ${chalk.blue("rebase resources --write")} Regenerate ${RESOURCE_GRAPH_FILENAME}
26
+ ${chalk.blue("rebase resources --check")} Fail if the committed graph is stale
27
+ ${chalk.blue("rebase resources --json")} The same set, machine-readable; with --check or --write,
28
+ their result too (a failed check is an error envelope, exit 1)
29
+
30
+ A resource is declared in config code — ${chalk.gray("database(\"analytics\"), bucket(\"media\"), topic(\"signups\")")} —
31
+ and never in ${RESOURCE_GRAPH_FILENAME}, which is generated from those declarations so a host
32
+ can read what a project needs without building it. A backend also has a default
33
+ database and a default storage source nobody declared; both are listed here,
34
+ marked ${chalk.gray("implicit")}, and neither is written to that file — the host supplies them.
35
+ `);
36
+ }
37
+ /**
38
+ * Render the projection the way somebody reads it: grouped by kind, key first.
39
+ *
40
+ * The projection, not the raw graph. `rebase status` has always included the
41
+ * implicit default database and bucket and this listing did not, so the two
42
+ * commands answered "what does this project need" differently on the same stock
43
+ * scaffold. There is no "no resources declared" case any more: a backend has a
44
+ * database and a storage source whether or not anyone wrote them down.
45
+ */
46
+ function print(resources) {
47
+ const order = [
48
+ "database",
49
+ "bucket",
50
+ "topic",
51
+ "queue",
52
+ "cron",
53
+ "function"
54
+ ];
55
+ const kinds = [...new Set(resources.map((r) => r.kind))].sort((a, b) => (order.indexOf(a) === -1 ? 99 : order.indexOf(a)) - (order.indexOf(b) === -1 ? 99 : order.indexOf(b)));
56
+ for (const kind of kinds) {
57
+ console.log(`\n ${chalk.bold(kind)}`);
58
+ for (const r of resources.filter((x) => x.kind === kind)) {
59
+ const bits = [];
60
+ if (kind === "cron") {
61
+ bits.push(chalk.cyan(String(r.options.schedule)));
62
+ bits.push(chalk.gray(r.options.timezone ? String(r.options.timezone) : "local time"));
63
+ } else if (kind === "function") {
64
+ bits.push(chalk.gray(String(r.options.file ?? "")));
65
+ if (r.options.portable === false) bits.push(chalk.yellow("node-only"));
66
+ } else {
67
+ bits.push(chalk.gray(r.engine));
68
+ if (r.transport !== "server") bits.push(chalk.yellow(r.transport));
69
+ for (const [k, v] of Object.entries(r.options)) bits.push(chalk.gray(`${k}=${String(v)}`));
70
+ }
71
+ if (r.implicit) bits.push(chalk.gray("implicit"));
72
+ console.log(` ${r.key.padEnd(24)} ${bits.join(" · ")}`);
73
+ if (kind === "topic") for (const sub of declaredSubscriptions(r.key)) console.log(` ${chalk.gray("→")} ${sub.name}`);
74
+ if (r.usedBy && r.usedBy.length > 0) console.log(` ${chalk.gray("used by")} ${chalk.gray(r.usedBy.join(", "))}`);
75
+ }
76
+ }
77
+ console.log("");
78
+ }
79
+ async function resourcesCommand(rawArgs) {
80
+ if (wantsHelp(rawArgs)) return usage();
81
+ const { flags } = parseCommandArgs({
82
+ spec: {
83
+ "--write": Boolean,
84
+ "--check": Boolean,
85
+ "--json": Boolean
86
+ },
87
+ rawArgs,
88
+ commandWords: 1,
89
+ command: "resources",
90
+ maxPositionals: 0
91
+ });
92
+ const projectRoot = requireProjectRoot();
93
+ const asJson = Boolean(flags["--json"]);
94
+ let backendApp;
95
+ try {
96
+ const backend = findBackendApp(loadManifest(projectRoot).manifest);
97
+ if (!backend) {
98
+ if (asJson) failAsJson("This project declares no backend app, so it declares no resources.", "no_backend_app", "Add a backend app to rebase.json, or run `rebase apps init`.");
99
+ console.error(chalk.red("This project declares no backend app, so it declares no resources."));
100
+ process.exitCode = 1;
101
+ return;
102
+ }
103
+ backendApp = backend.app;
104
+ } catch (err) {
105
+ if (err instanceof ManifestError) {
106
+ if (asJson) failAsJson(err.message, "manifest_invalid", "Fix rebase.json, then run this again.", err.issues.map((issue) => ({
107
+ path: issue.path,
108
+ message: issue.message
109
+ })));
110
+ console.error(chalk.red(err.message));
111
+ for (const issue of err.issues) console.error(` ${chalk.gray(issue.path)} ${issue.message}`);
112
+ process.exitCode = 1;
113
+ return;
114
+ }
115
+ throw err;
116
+ }
117
+ const { graph, issues } = await deriveResourceGraph(deriveOptionsFor(projectRoot, backendApp));
118
+ if (issues.length > 0) {
119
+ if (asJson) failAsJson(`${issues.length} problem(s) in the declared resources.`, "resource_declaration_invalid", "Fix the declarations the issues name, then run this again.", issues.map((issue) => ({
120
+ path: issue.path,
121
+ message: issue.message
122
+ })));
123
+ console.error(chalk.red(`\n✗ ${issues.length} problem(s) in the declared resources:\n`));
124
+ for (const issue of issues) console.error(` ${chalk.bold(issue.path)} ${issue.message}`);
125
+ console.error("");
126
+ process.exitCode = 1;
127
+ return;
128
+ }
129
+ const projection = () => ({
130
+ version: graph.version,
131
+ resources: projectResourceGraph(graph)
132
+ });
133
+ if (flags["--check"]) {
134
+ const committed = readResourceGraphFile(projectRoot);
135
+ const status = committed === serializeResourceGraph(graph) ? "current" : committed === null && graph.resources.length === 0 ? "nothing-declared" : null;
136
+ if (status !== null) {
137
+ if (asJson) {
138
+ console.log(JSON.stringify({
139
+ ...projection(),
140
+ check: {
141
+ file: RESOURCE_GRAPH_FILENAME,
142
+ status
143
+ }
144
+ }, null, 2));
145
+ return;
146
+ }
147
+ console.log(status === "current" ? chalk.green(`✓ ${RESOURCE_GRAPH_FILENAME} matches the declarations.`) : chalk.gray("✓ Nothing declared, so there is nothing to record."));
148
+ return;
149
+ }
150
+ const state = committed === null ? "missing" : "stale";
151
+ if (asJson) failAsJson(`${RESOURCE_GRAPH_FILENAME} is ${state}.`, `resource_graph_${state}`, "Regenerate it with `rebase resources --write`, and commit it.");
152
+ console.error(chalk.red(`\n✗ ${RESOURCE_GRAPH_FILENAME} is ${state}.\n`));
153
+ console.error(" A host reads this file to decide what to provision, so a stale one means the\n console offers one set of resources while the runtime asks for another.\n");
154
+ console.error(` Regenerate it: ${chalk.blue("rebase resources --write")}\n`);
155
+ process.exitCode = 1;
156
+ return;
157
+ }
158
+ if (flags["--write"]) {
159
+ const { changed, file } = writeResourceGraphFile(projectRoot, graph);
160
+ const relative = path.relative(projectRoot, file);
161
+ if (asJson) {
162
+ console.log(JSON.stringify({
163
+ ...projection(),
164
+ written: {
165
+ file: relative,
166
+ changed
167
+ }
168
+ }, null, 2));
169
+ return;
170
+ }
171
+ console.log(changed ? chalk.green(`✓ Wrote ${relative}`) : chalk.gray(`${relative} already matched the declarations.`));
172
+ return;
173
+ }
174
+ if (asJson) {
175
+ console.log(JSON.stringify(projection(), null, 2));
176
+ return;
177
+ }
178
+ print(projectResourceGraph(graph));
179
+ }
180
+ //#endregion
181
+ export { resourcesCommand };
182
+
183
+ //# sourceMappingURL=resources-FD7AfZx8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources-FD7AfZx8.js","names":[],"sources":["../src/commands/resources.ts"],"sourcesContent":["/**\n * CLI command: rebase resources\n *\n * Shows what a project declares, and keeps the committed graph honest.\n *\n * The graph is generated, so it can drift the moment somebody adds a bucket and\n * does not regenerate. Drift here is not cosmetic: the committed file is what a\n * host reads to decide what to provision, so a stale one means the console\n * offers a project one set of resources while the runtime asks for another.\n * `--check` is the gate that makes that impossible to land.\n */\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport { failAsJson, requireProjectRoot } from \"../utils/project\";\nimport { findBackendApp, loadManifest, ManifestError } from \"../manifest\";\nimport { parseCommandArgs, wantsHelp } from \"../utils/args\";\nimport {\n RESOURCE_GRAPH_FILENAME,\n deriveOptionsFor, deriveResourceGraph,\n projectResourceGraph,\n readResourceGraphFile,\n serializeResourceGraph,\n writeResourceGraphFile,\n type ProjectedResource\n} from \"../resources/derive\";\nimport { declaredSubscriptions, type RebaseBackendAppConfig } from \"@rebasepro/types\";\n\nfunction usage(): void {\n console.log(`\n${chalk.bold(\"rebase resources\")} — what this project needs\n\n ${chalk.blue(\"rebase resources\")} List them, declared and implicit\n ${chalk.blue(\"rebase resources --write\")} Regenerate ${RESOURCE_GRAPH_FILENAME}\n ${chalk.blue(\"rebase resources --check\")} Fail if the committed graph is stale\n ${chalk.blue(\"rebase resources --json\")} The same set, machine-readable; with --check or --write,\n their result too (a failed check is an error envelope, exit 1)\n\nA resource is declared in config code — ${chalk.gray('database(\"analytics\"), bucket(\"media\"), topic(\"signups\")')} —\nand never in ${RESOURCE_GRAPH_FILENAME}, which is generated from those declarations so a host\ncan read what a project needs without building it. A backend also has a default\ndatabase and a default storage source nobody declared; both are listed here,\nmarked ${chalk.gray(\"implicit\")}, and neither is written to that file — the host supplies them.\n`);\n}\n\n/**\n * Render the projection the way somebody reads it: grouped by kind, key first.\n *\n * The projection, not the raw graph. `rebase status` has always included the\n * implicit default database and bucket and this listing did not, so the two\n * commands answered \"what does this project need\" differently on the same stock\n * scaffold. There is no \"no resources declared\" case any more: a backend has a\n * database and a storage source whether or not anyone wrote them down.\n */\nfunction print(resources: ProjectedResource[]): void {\n // Infrastructure first, then code: what needs binding is what a reader\n // is here to check.\n const order = [\"database\", \"bucket\", \"topic\", \"queue\", \"cron\", \"function\"];\n const kinds = [...new Set(resources.map(r => r.kind))]\n .sort((a, b) => (order.indexOf(a) === -1 ? 99 : order.indexOf(a)) - (order.indexOf(b) === -1 ? 99 : order.indexOf(b)));\n for (const kind of kinds) {\n console.log(`\\n ${chalk.bold(kind)}`);\n for (const r of resources.filter(x => x.kind === kind)) {\n const bits: string[] = [];\n if (kind === \"cron\") {\n bits.push(chalk.cyan(String(r.options.schedule)));\n bits.push(chalk.gray(r.options.timezone ? String(r.options.timezone) : \"local time\"));\n } else if (kind === \"function\") {\n bits.push(chalk.gray(String(r.options.file ?? \"\")));\n if (r.options.portable === false) bits.push(chalk.yellow(\"node-only\"));\n } else {\n bits.push(chalk.gray(r.engine));\n if (r.transport !== \"server\") bits.push(chalk.yellow(r.transport));\n for (const [k, v] of Object.entries(r.options)) bits.push(chalk.gray(`${k}=${String(v)}`));\n }\n // Marked, not hidden: a declared resource is recorded in\n // `rebase.resources.json` for a host to provision, and an implicit\n // one is a default the runtime supplies regardless.\n if (r.implicit) bits.push(chalk.gray(\"implicit\"));\n console.log(` ${r.key.padEnd(24)} ${bits.join(\" · \")}`);\n if (kind === \"topic\") {\n for (const sub of declaredSubscriptions(r.key)) {\n console.log(` ${chalk.gray(\"→\")} ${sub.name}`);\n }\n }\n if (r.usedBy && r.usedBy.length > 0) {\n console.log(` ${chalk.gray(\"used by\")} ${chalk.gray(r.usedBy.join(\", \"))}`);\n }\n }\n }\n console.log(\"\");\n}\n\nexport async function resourcesCommand(rawArgs: string[]): Promise<void> {\n if (wantsHelp(rawArgs)) return usage();\n\n const { flags } = parseCommandArgs({\n spec: {\n \"--write\": Boolean,\n \"--check\": Boolean,\n \"--json\": Boolean\n },\n rawArgs,\n commandWords: 1,\n command: \"resources\",\n maxPositionals: 0\n });\n\n const projectRoot = requireProjectRoot();\n\n // Every exit below has a `--json` arm, for the reason in `failAsJson`:\n // `--json` is a promise about stdout, and a promise kept on one exit of a\n // command and broken on the next is not one.\n const asJson = Boolean(flags[\"--json\"]);\n\n let backendApp: RebaseBackendAppConfig;\n try {\n const loaded = loadManifest(projectRoot);\n const backend = findBackendApp(loaded.manifest);\n if (!backend) {\n if (asJson) {\n failAsJson(\n \"This project declares no backend app, so it declares no resources.\",\n \"no_backend_app\",\n \"Add a backend app to rebase.json, or run `rebase apps init`.\"\n );\n }\n console.error(chalk.red(\"This project declares no backend app, so it declares no resources.\"));\n process.exitCode = 1;\n return;\n }\n backendApp = backend.app;\n } catch (err) {\n if (err instanceof ManifestError) {\n if (asJson) {\n failAsJson(err.message, \"manifest_invalid\", \"Fix rebase.json, then run this again.\",\n err.issues.map(issue => ({ path: issue.path, message: issue.message })));\n }\n console.error(chalk.red(err.message));\n for (const issue of err.issues) console.error(` ${chalk.gray(issue.path)} ${issue.message}`);\n process.exitCode = 1;\n return;\n }\n throw err;\n }\n\n const { graph, issues } = await deriveResourceGraph(deriveOptionsFor(projectRoot, backendApp));\n\n if (issues.length > 0) {\n if (asJson) {\n failAsJson(\n `${issues.length} problem(s) in the declared resources.`,\n \"resource_declaration_invalid\",\n \"Fix the declarations the issues name, then run this again.\",\n issues.map(issue => ({ path: issue.path, message: issue.message }))\n );\n }\n console.error(chalk.red(`\\n✗ ${issues.length} problem(s) in the declared resources:\\n`));\n for (const issue of issues) console.error(` ${chalk.bold(issue.path)} ${issue.message}`);\n console.error(\"\");\n process.exitCode = 1;\n return;\n }\n\n // The projection, so this and `rebase status --json` describe the same\n // set. `version` is kept so a reader of either can tell them apart from a\n // future shape. `--check` and `--write` add what they did to it: `--json`\n // changes how the answer is printed, never which question is answered — it\n // used to return here, so `--check --json` exited 0 on any drift and\n // `--write --json` wrote nothing.\n const projection = () => ({ version: graph.version, resources: projectResourceGraph(graph) });\n\n if (flags[\"--check\"]) {\n const committed = readResourceGraphFile(projectRoot);\n const expected = serializeResourceGraph(graph);\n // Declaring nothing and having no file is a consistent state, not a\n // stale one. The file records declarations; a project with none has\n // nothing to record, and its default database and bucket are implicit\n // by design — that is the overwhelmingly common project and it must not\n // be required to commit an empty file saying so.\n //\n // This mattered the moment the check was put in a gate: it would have\n // failed this repository's own reference app, which declares nothing,\n // and every scaffolded project until someone declared a second bucket.\n const status = committed === expected\n ? \"current\"\n : committed === null && graph.resources.length === 0 ? \"nothing-declared\" : null;\n\n if (status !== null) {\n if (asJson) {\n console.log(JSON.stringify({ ...projection(), check: { file: RESOURCE_GRAPH_FILENAME, status } }, null, 2));\n return;\n }\n console.log(status === \"current\"\n ? chalk.green(`✓ ${RESOURCE_GRAPH_FILENAME} matches the declarations.`)\n : chalk.gray(\"✓ Nothing declared, so there is nothing to record.\"));\n return;\n }\n\n const state = committed === null ? \"missing\" : \"stale\";\n if (asJson) {\n failAsJson(\n `${RESOURCE_GRAPH_FILENAME} is ${state}.`,\n `resource_graph_${state}`,\n \"Regenerate it with `rebase resources --write`, and commit it.\"\n );\n }\n console.error(chalk.red(`\\n✗ ${RESOURCE_GRAPH_FILENAME} is ${state}.\\n`));\n console.error(\n \" A host reads this file to decide what to provision, so a stale one means the\\n\" +\n \" console offers one set of resources while the runtime asks for another.\\n\"\n );\n console.error(` Regenerate it: ${chalk.blue(\"rebase resources --write\")}\\n`);\n process.exitCode = 1;\n return;\n }\n\n if (flags[\"--write\"]) {\n const { changed, file } = writeResourceGraphFile(projectRoot, graph);\n const relative = path.relative(projectRoot, file);\n if (asJson) {\n console.log(JSON.stringify({ ...projection(), written: { file: relative, changed } }, null, 2));\n return;\n }\n console.log(changed\n ? chalk.green(`✓ Wrote ${relative}`)\n : chalk.gray(`${relative} already matched the declarations.`));\n return;\n }\n\n if (asJson) {\n console.log(JSON.stringify(projection(), null, 2));\n return;\n }\n\n print(projectResourceGraph(graph));\n}\n"],"mappings":"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"}
@@ -0,0 +1,125 @@
1
+ import { i as recordEvent } from "./telemetry-EMFRVRQi.js";
2
+ import { f as requireBackendDir, h as resolvePluginCliScript, l as getActiveBackendPlugin, o as findEnvFile, p as requireProjectRoot, r as exitDependenciesNotInstalled } from "./project-Wp2zoyeN.js";
3
+ import { r as wantsHelp } from "./args-BnmsEXvu.js";
4
+ import { t as unknownCommand } from "./unknown-command-DNwDcX3w.js";
5
+ import { r as refuseMissingCollectionsPath, t as COLLECTIONS_FLAG_HELP } from "./path-flags-BFgG9V6y.js";
6
+ import { DEV_DATABASE_KIND_ENV, devDatabaseKind } from "./prepare-CDN6lSpz.js";
7
+ import { absolutizeLocalPathArgs, n as argsFromCommand, spawnDriverCli, t as reportSpawnFailure } from "./db-B7RuNuaQ.js";
8
+ import chalk from "chalk";
9
+ //#region src/commands/schema.ts
10
+ /**
11
+ * CLI command: rebase schema <action>
12
+ */
13
+ /**
14
+ * The line handed to the driver, its paths resolved from where the command was
15
+ * run (the driver runs in `backend/`). `--schema` is left alone: on
16
+ * `introspect` it names a Postgres schema, not a file.
17
+ */
18
+ function schemaDriverArgs(rawArgs, cwd) {
19
+ return absolutizeLocalPathArgs(argsFromCommand(rawArgs, "schema"), cwd, [
20
+ "--collections",
21
+ "-c",
22
+ "--output",
23
+ "-o",
24
+ "--out"
25
+ ]);
26
+ }
27
+ async function schemaCommand(subcommand, rawArgs) {
28
+ if (!subcommand || subcommand === "--help" || wantsHelp(rawArgs)) {
29
+ printSchemaHelp(subcommand === "--help" ? void 0 : subcommand);
30
+ return;
31
+ }
32
+ if (!SCHEMA_ACTION_HELP[subcommand]) unknownCommand(subcommand, Object.keys(SCHEMA_ACTION_HELP), "schema");
33
+ const projectRoot = requireProjectRoot();
34
+ recordEvent("cli.schema", { subcommand: subcommand ?? "none" }, { projectRoot });
35
+ const backendDir = requireBackendDir(projectRoot);
36
+ const activePlugin = getActiveBackendPlugin(backendDir);
37
+ if (!activePlugin) {
38
+ console.error(chalk.red("✗ Could not detect an active database plugin."));
39
+ console.error(chalk.gray(" Make sure a package like @rebasepro/server-postgres is installed in backend/package.json."));
40
+ process.exit(1);
41
+ }
42
+ const pluginCli = resolvePluginCliScript(backendDir, activePlugin);
43
+ if (!pluginCli) exitDependenciesNotInstalled(projectRoot);
44
+ const envFile = findEnvFile(projectRoot);
45
+ const env = { ...process.env };
46
+ if (envFile) env.DOTENV_CONFIG_PATH = envFile;
47
+ env[DEV_DATABASE_KIND_ENV] = devDatabaseKind(projectRoot) ?? "";
48
+ refuseMissingCollectionsPath(rawArgs, process.cwd(), backendDir);
49
+ try {
50
+ await spawnDriverCli({
51
+ projectRoot,
52
+ backendDir,
53
+ pluginCli,
54
+ env
55
+ }, schemaDriverArgs(rawArgs, process.cwd()));
56
+ } catch (error) {
57
+ reportSpawnFailure(error);
58
+ process.exit(1);
59
+ }
60
+ }
61
+ /** One page per subcommand, so `rebase schema <action> --help` says something. */
62
+ var SCHEMA_ACTION_HELP = {
63
+ generate: {
64
+ usage: "rebase schema generate [--collections <dir>] [--output <file>] [--watch]",
65
+ summary: "Generate the Drizzle schema from the collection definitions.",
66
+ notes: ["--watch regenerates on every change to a collection file."]
67
+ },
68
+ introspect: {
69
+ usage: "rebase schema introspect [--collections <dir>] [--output <dir>] [--schema <name>] [--force]",
70
+ summary: "Read an existing database and write Rebase collection definitions from it.",
71
+ notes: ["--force overwrites collection files that are already there."]
72
+ },
73
+ stale: {
74
+ usage: "rebase schema stale [--collections <dir>] [--output <file>] [--fix]",
75
+ summary: "Report generated schema files that no longer match the collections.",
76
+ notes: ["--fix regenerates them instead of only reporting."]
77
+ }
78
+ };
79
+ /** Every subcommand the family dispatches — the help table's keys. */
80
+ var SCHEMA_SUBCOMMANDS = Object.keys(SCHEMA_ACTION_HELP);
81
+ function printSchemaHelp(action) {
82
+ const entry = action ? SCHEMA_ACTION_HELP[action] : void 0;
83
+ if (entry) {
84
+ console.log(`
85
+ ${chalk.bold(`rebase schema ${action}`)}
86
+
87
+ ${entry.summary}
88
+
89
+ ${chalk.green.bold("Usage")}
90
+ ${chalk.blue(entry.usage)}
91
+ ${entry.notes?.length ? `\n${chalk.green.bold("Notes")}\n${entry.notes.map((n) => ` ${chalk.gray(`• ${n}`)}`).join("\n")}\n` : ""}
92
+ ${chalk.gray("Run `rebase schema --help` for every subcommand.")}
93
+ `);
94
+ return;
95
+ }
96
+ console.log(`
97
+ ${chalk.bold("rebase schema")} — Schema management commands
98
+
99
+ ${chalk.green.bold("Usage")}
100
+ rebase schema ${chalk.blue("<command>")} [options]
101
+
102
+ ${chalk.green.bold("Commands")}
103
+ ${chalk.gray("(Commands are provided by your active database driver plugin)")}
104
+ ${chalk.blue.bold("generate")} Generate Schema from collection definitions
105
+ ${chalk.blue.bold("introspect")} Introspect an existing database to generate collection definitions
106
+ ${chalk.blue.bold("stale")} Report generated schema files that no longer match the collections
107
+
108
+ ${chalk.green.bold("generate Options")}
109
+ ${chalk.blue("--collections, -c")} ${COLLECTIONS_FLAG_HELP}
110
+ ${chalk.blue("--output, -o")} Output path for generated schema
111
+ ${chalk.blue("--watch, -w")} Watch for changes and regenerate automatically
112
+
113
+ ${chalk.green.bold("introspect Options")}
114
+ ${chalk.blue("--output, -o")} Output directory for generated collection files
115
+ ${chalk.blue("--schema")} Postgres schema to read (default: public)
116
+ ${chalk.blue("--force, -f")} Overwrite collection files that already exist
117
+
118
+ ${chalk.green.bold("stale Options")}
119
+ ${chalk.blue("--fix")} Regenerate the stale files instead of only reporting them
120
+ `);
121
+ }
122
+ //#endregion
123
+ export { SCHEMA_SUBCOMMANDS, schemaCommand };
124
+
125
+ //# sourceMappingURL=schema-DMdr431S.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-DMdr431S.js","names":[],"sources":["../src/commands/schema.ts"],"sourcesContent":["/**\n * CLI command: rebase schema <action>\n */\nimport chalk from \"chalk\";\nimport { spawnDriverCli } from \"./db\";\nimport {\n requireProjectRoot,\n requireBackendDir,\n getActiveBackendPlugin,\n resolvePluginCliScript,\n resolveTsx,\n findEnvFile,\n exitDependenciesNotInstalled\n} from \"../utils/project\";\nimport { recordEvent } from \"../telemetry\";\nimport { wantsHelp } from \"../utils/args\";\nimport { reportSpawnFailure } from \"../utils/spawn-error\";\nimport { argsFromCommand } from \"../utils/command-words\";\nimport { unknownCommand } from \"../utils/unknown-command\";\nimport { DEV_DATABASE_KIND_ENV, devDatabaseKind } from \"../dev-db/prepare\";\nimport { absolutizeLocalPathArgs } from \"./db\";\nimport { COLLECTIONS_FLAG_HELP, refuseMissingCollectionsPath } from \"../utils/path-flags\";\n\n/**\n * The line handed to the driver, its paths resolved from where the command was\n * run (the driver runs in `backend/`). `--schema` is left alone: on\n * `introspect` it names a Postgres schema, not a file.\n */\nexport function schemaDriverArgs(rawArgs: string[], cwd: string): string[] {\n return absolutizeLocalPathArgs(argsFromCommand(rawArgs, \"schema\"), cwd, [\"--collections\", \"-c\", \"--output\", \"-o\", \"--out\"]);\n}\n\nexport async function schemaCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void> {\n // `--help` is answered here, before `requireProjectRoot` and before the\n // driver is spawned — the same shape `db.ts` already uses, and for the same\n // reason.\n //\n // `cli.ts` rewrites the subcommand to `\"--help\"` only when the user named\n // none, so `rebase schema --help` was covered and `rebase schema generate\n // --help` was not: the flag travelled into `rawArgs.slice(2)` and reached\n // the driver, whose own `schemaCommand` has no `--help` case. It *ran the\n // generator* — overwriting `src/schema.generated.ts` — for a flag whose\n // entire job is to print text. Worse, the first thing it hit outside a\n // project was `requireProjectRoot`, so `rebase schema introspect --help` in\n // an empty directory exited 1 with \"Could not find a Rebase project root\":\n // help you cannot read until you already have a project is help for nobody.\n if (!subcommand || subcommand === \"--help\" || wantsHelp(rawArgs)) {\n printSchemaHelp(subcommand === \"--help\" ? undefined : subcommand);\n return;\n }\n\n // A typo is answered here, in the same words every other family uses.\n //\n // It used to travel to the driver, which said the bare line `Unknown schema\n // command.` — no list, no pointer, no did-you-mean, for a family with three\n // subcommands. The set comes from the help table, so what a typo is measured\n // against and what `--help` prints cannot drift apart.\n if (!SCHEMA_ACTION_HELP[subcommand]) {\n unknownCommand(subcommand, Object.keys(SCHEMA_ACTION_HELP), \"schema\");\n }\n\n const projectRoot = requireProjectRoot();\n\n // Fire-and-forget, and a no-op unless the developer opted in. Never awaited:\n // the command is what the user is waiting for, and a slow collector must not\n // sit in front of it.\n void recordEvent(\"cli.schema\", { subcommand: subcommand ?? \"none\" }, { projectRoot });\n const backendDir = requireBackendDir(projectRoot);\n\n const activePlugin = getActiveBackendPlugin(backendDir);\n if (!activePlugin) {\n console.error(chalk.red(\"✗ Could not detect an active database plugin.\"));\n console.error(chalk.gray(\" Make sure a package like @rebasepro/server-postgres is installed in backend/package.json.\"));\n process.exit(1);\n }\n\n const pluginCli = resolvePluginCliScript(backendDir, activePlugin);\n if (!pluginCli) {\n exitDependenciesNotInstalled(projectRoot);\n }\n\n // Set up environment with DOTENV_CONFIG_PATH\n const envFile = findEnvFile(projectRoot);\n const env: Record<string, string> = { ...process.env as Record<string, string> };\n if (envFile) {\n env.DOTENV_CONFIG_PATH = envFile;\n }\n // Which database this project is on, so the driver's closing line does not\n // recommend a command that database refuses. A pure decision — nothing is\n // started, which matters here above all: `schema generate` reads collection\n // files and writes one file, and booting a database to run it would be a\n // side effect nobody asked for.\n env[DEV_DATABASE_KIND_ENV] = devDatabaseKind(projectRoot) ?? \"\";\n\n refuseMissingCollectionsPath(rawArgs, process.cwd(), backendDir);\n\n try {\n // The one spawn, shared with `db`. This file used to carry its own copy\n // of the tsx-or-node decision; three copies of that rule existed and two\n // were fixed while the third went on spawning plain node.\n await spawnDriverCli(\n { projectRoot, backendDir, pluginCli, env },\n schemaDriverArgs(rawArgs, process.cwd())\n );\n } catch (error) {\n // A child that ran and exited non-zero already printed its diagnostics\n // through inherited stdio; a child that never started (ENOENT on tsx,\n // EACCES on the script) printed nothing at all, and this used to exit 1\n // in silence.\n reportSpawnFailure(error);\n process.exit(1);\n }\n}\n\n/** One page per subcommand, so `rebase schema <action> --help` says something. */\nconst SCHEMA_ACTION_HELP: Record<string, { usage: string; summary: string; notes?: string[] }> = {\n generate: {\n usage: \"rebase schema generate [--collections <dir>] [--output <file>] [--watch]\",\n summary: \"Generate the Drizzle schema from the collection definitions.\",\n notes: [\"--watch regenerates on every change to a collection file.\"]\n },\n introspect: {\n usage: \"rebase schema introspect [--collections <dir>] [--output <dir>] [--schema <name>] [--force]\",\n summary: \"Read an existing database and write Rebase collection definitions from it.\",\n notes: [\"--force overwrites collection files that are already there.\"]\n },\n stale: {\n usage: \"rebase schema stale [--collections <dir>] [--output <file>] [--fix]\",\n summary: \"Report generated schema files that no longer match the collections.\",\n notes: [\"--fix regenerates them instead of only reporting.\"]\n }\n};\n\n/** Every subcommand the family dispatches — the help table's keys. */\nexport const SCHEMA_SUBCOMMANDS = Object.keys(SCHEMA_ACTION_HELP);\n\nfunction printSchemaHelp(action?: string) {\n const entry = action ? SCHEMA_ACTION_HELP[action] : undefined;\n if (entry) {\n console.log(`\n${chalk.bold(`rebase schema ${action}`)}\n\n ${entry.summary}\n\n${chalk.green.bold(\"Usage\")}\n ${chalk.blue(entry.usage)}\n${entry.notes?.length ? `\\n${chalk.green.bold(\"Notes\")}\\n${entry.notes.map(n => ` ${chalk.gray(`• ${n}`)}`).join(\"\\n\")}\\n` : \"\"}\n${chalk.gray(\"Run `rebase schema --help` for every subcommand.\")}\n`);\n return;\n }\n\n console.log(`\n${chalk.bold(\"rebase schema\")} — Schema management commands\n\n${chalk.green.bold(\"Usage\")}\n rebase schema ${chalk.blue(\"<command>\")} [options]\n\n${chalk.green.bold(\"Commands\")}\n ${chalk.gray(\"(Commands are provided by your active database driver plugin)\")}\n ${chalk.blue.bold(\"generate\")} Generate Schema from collection definitions\n ${chalk.blue.bold(\"introspect\")} Introspect an existing database to generate collection definitions\n ${chalk.blue.bold(\"stale\")} Report generated schema files that no longer match the collections\n\n${chalk.green.bold(\"generate Options\")}\n ${chalk.blue(\"--collections, -c\")} ${COLLECTIONS_FLAG_HELP}\n ${chalk.blue(\"--output, -o\")} Output path for generated schema\n ${chalk.blue(\"--watch, -w\")} Watch for changes and regenerate automatically\n\n${chalk.green.bold(\"introspect Options\")}\n ${chalk.blue(\"--output, -o\")} Output directory for generated collection files\n ${chalk.blue(\"--schema\")} Postgres schema to read (default: public)\n ${chalk.blue(\"--force, -f\")} Overwrite collection files that already exist\n\n${chalk.green.bold(\"stale Options\")}\n ${chalk.blue(\"--fix\")} Regenerate the stale files instead of only reporting them\n`);\n}\n"],"mappings":"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"}