@rebasepro/cli 0.24.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 (156) hide show
  1. package/bin/rebase.js +3 -0
  2. package/dist/agent-setup-B31F00DC.js +324 -0
  3. package/dist/agent-setup-B31F00DC.js.map +1 -0
  4. package/dist/api-keys-Bl1I9q7M.js +525 -0
  5. package/dist/api-keys-Bl1I9q7M.js.map +1 -0
  6. package/dist/apps-CNgQJjg5.js +340 -0
  7. package/dist/apps-CNgQJjg5.js.map +1 -0
  8. package/dist/args-BnmsEXvu.js +109 -0
  9. package/dist/args-BnmsEXvu.js.map +1 -0
  10. package/dist/atlas-dev-database-D_LP_Woq.js +62 -0
  11. package/dist/atlas-dev-database-D_LP_Woq.js.map +1 -0
  12. package/dist/auth-aySHEF45.js +414 -0
  13. package/dist/auth-aySHEF45.js.map +1 -0
  14. package/dist/branch-pointer-DvSHBjjz.js +2 -0
  15. package/dist/build-DIHWIqO4.js +336 -0
  16. package/dist/build-DIHWIqO4.js.map +1 -0
  17. package/dist/bundle-CqURVN-K.js +1621 -0
  18. package/dist/bundle-CqURVN-K.js.map +1 -0
  19. package/dist/bundle.d.ts +6 -1
  20. package/dist/cli.d.ts +2 -2
  21. package/dist/cloud-DjByQlkW.js +9667 -0
  22. package/dist/cloud-DjByQlkW.js.map +1 -0
  23. package/dist/collection-drift-BKj_BoMq.js +106 -0
  24. package/dist/collection-drift-BKj_BoMq.js.map +1 -0
  25. package/dist/commands/api-keys.d.ts +2 -0
  26. package/dist/commands/console.d.ts +12 -0
  27. package/dist/commands/db.d.ts +64 -24
  28. package/dist/commands/dev.d.ts +103 -6
  29. package/dist/commands/generate_sdk.d.ts +26 -0
  30. package/dist/commands/init.d.ts +58 -0
  31. package/dist/commands/skills.d.ts +22 -7
  32. package/dist/commands/start.d.ts +15 -0
  33. package/dist/commands/storage.d.ts +46 -0
  34. package/dist/commands/upgrade.d.ts +1 -0
  35. package/dist/consent-ClRHmcxf.js +76 -0
  36. package/dist/consent-ClRHmcxf.js.map +1 -0
  37. package/dist/console-D6SJf8k_.js +102 -0
  38. package/dist/console-D6SJf8k_.js.map +1 -0
  39. package/dist/context-BqhRydBg.js +1234 -0
  40. package/dist/context-BqhRydBg.js.map +1 -0
  41. package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
  42. package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
  43. package/dist/daemon-pzsQwDHa.js +2 -0
  44. package/dist/db-B7RuNuaQ.js +1312 -0
  45. package/dist/db-B7RuNuaQ.js.map +1 -0
  46. package/dist/derive-Dl0z2OWi.js +484 -0
  47. package/dist/derive-Dl0z2OWi.js.map +1 -0
  48. package/dist/dev-CYr_WXan.js +1599 -0
  49. package/dist/dev-CYr_WXan.js.map +1 -0
  50. package/dist/dev-db/atlas-dev-database.d.ts +32 -0
  51. package/dist/dev-db/daemon-entry.d.ts +13 -0
  52. package/dist/dev-db/last-dev-database.d.ts +41 -0
  53. package/dist/dev-db/prepare.d.ts +19 -3
  54. package/dist/dev-db/pull.d.ts +90 -5
  55. package/dist/dev-db/resolve.d.ts +26 -2
  56. package/dist/dev-preflight-B-LYyBf1.js +2 -0
  57. package/dist/dev-server-DG8Tt-uf.js +96 -0
  58. package/dist/dev-server-DG8Tt-uf.js.map +1 -0
  59. package/dist/doctor-BP8cZ-7F.js +771 -0
  60. package/dist/doctor-BP8cZ-7F.js.map +1 -0
  61. package/dist/eject-DizdoecV.js +335 -0
  62. package/dist/eject-DizdoecV.js.map +1 -0
  63. package/dist/fold-static-BC9CYicw.js +201 -0
  64. package/dist/fold-static-BC9CYicw.js.map +1 -0
  65. package/dist/function-portability-BIvlvR9q.js +265 -0
  66. package/dist/function-portability-BIvlvR9q.js.map +1 -0
  67. package/dist/generate_sdk-BPqdJc3Q.js +489 -0
  68. package/dist/generate_sdk-BPqdJc3Q.js.map +1 -0
  69. package/dist/index.es.js +151 -24674
  70. package/dist/index.es.js.map +1 -1
  71. package/dist/init-Utstvh2Q.js +1149 -0
  72. package/dist/init-Utstvh2Q.js.map +1 -0
  73. package/dist/last-dev-database-B58g89uA.js +2 -0
  74. package/dist/manifest-DRp0UVTj.js +880 -0
  75. package/dist/manifest-DRp0UVTj.js.map +1 -0
  76. package/dist/manifest.d.ts +15 -3
  77. package/dist/normalize-imports-X0Tgze9y.js +107 -0
  78. package/dist/normalize-imports-X0Tgze9y.js.map +1 -0
  79. package/dist/{package-manager-CXQevsE1.js → package-manager-DSEOwTqM.js} +2 -2
  80. package/dist/{package-manager-CXQevsE1.js.map → package-manager-DSEOwTqM.js.map} +1 -1
  81. package/dist/path-flags-BFgG9V6y.js +91 -0
  82. package/dist/path-flags-BFgG9V6y.js.map +1 -0
  83. package/dist/precompress.d.ts +17 -0
  84. package/dist/prepare-CDN6lSpz.js +1236 -0
  85. package/dist/prepare-CDN6lSpz.js.map +1 -0
  86. package/dist/{project-DmaGLmH2.js → project-Wp2zoyeN.js} +33 -4
  87. package/dist/project-Wp2zoyeN.js.map +1 -0
  88. package/dist/pull-CrGYMEsy.js +458 -0
  89. package/dist/pull-CrGYMEsy.js.map +1 -0
  90. package/dist/resolve-B2O-wKKk.js +2 -0
  91. package/dist/resources-FD7AfZx8.js +183 -0
  92. package/dist/resources-FD7AfZx8.js.map +1 -0
  93. package/dist/schema-DMdr431S.js +125 -0
  94. package/dist/schema-DMdr431S.js.map +1 -0
  95. package/dist/skills-DTFibT1m.js +642 -0
  96. package/dist/skills-DTFibT1m.js.map +1 -0
  97. package/dist/start-DEa-hOBh.js +267 -0
  98. package/dist/start-DEa-hOBh.js.map +1 -0
  99. package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
  100. package/dist/state-Do7ZJYkF.js.map +1 -0
  101. package/dist/status-DxnJTekv.js +352 -0
  102. package/dist/status-DxnJTekv.js.map +1 -0
  103. package/dist/storage-DyVq-f_F.js +303 -0
  104. package/dist/storage-DyVq-f_F.js.map +1 -0
  105. package/dist/telemetry/identity.d.ts +10 -1
  106. package/dist/telemetry-C8Uq8phb.js +129 -0
  107. package/dist/telemetry-C8Uq8phb.js.map +1 -0
  108. package/dist/telemetry-EMFRVRQi.js +351 -0
  109. package/dist/telemetry-EMFRVRQi.js.map +1 -0
  110. package/dist/unknown-command-DNwDcX3w.js +98 -0
  111. package/dist/unknown-command-DNwDcX3w.js.map +1 -0
  112. package/dist/upgrade-CtZtRkTE.js +1332 -0
  113. package/dist/upgrade-CtZtRkTE.js.map +1 -0
  114. package/dist/upgrade.d.ts +24 -3
  115. package/dist/utils/dev-preflight.d.ts +47 -5
  116. package/dist/utils/dev-server.d.ts +30 -0
  117. package/dist/utils/path-flags.d.ts +15 -2
  118. package/dist/utils/project.d.ts +16 -0
  119. package/dist/utils/temp-archive.d.ts +9 -0
  120. package/dist/{version-DsgBmP22.js → version-Buyyo1ut.js} +2 -2
  121. package/dist/{version-DsgBmP22.js.map → version-Buyyo1ut.js.map} +1 -1
  122. package/package.json +7 -7
  123. package/templates/eject/Dockerfile +4 -2
  124. package/templates/eject/backend/src/env.ts +1 -1
  125. package/templates/eject/backend/src/index.ts +29 -4
  126. package/templates/eject/docker-compose.custom.yml +8 -4
  127. package/templates/generated-schemas/blank.ts +40 -0
  128. package/templates/generated-schemas/blog.ts +127 -0
  129. package/templates/generated-schemas/ecommerce.ts +93 -0
  130. package/templates/overlays/baas/config/package.json +1 -0
  131. package/templates/overlays/baas/package.json +1 -0
  132. package/templates/template/.env.example +10 -4
  133. package/templates/template/README.md +11 -4
  134. package/templates/template/ai-instructions.md +3 -2
  135. package/templates/template/config/resources.ts +7 -6
  136. package/templates/template/docker-compose.yml +9 -3
  137. package/templates/template/frontend/vite.config.ts +13 -3
  138. package/templates/template/package.json +1 -0
  139. package/templates/template/scripts/example.ts +2 -1
  140. package/templates/template/tsconfig.json +25 -0
  141. package/dist/branch-pointer-kk9F5FBO.js +0 -111
  142. package/dist/branch-pointer-kk9F5FBO.js.map +0 -1
  143. package/dist/constraints-DKGbNfUW.js +0 -48
  144. package/dist/constraints-DKGbNfUW.js.map +0 -1
  145. package/dist/daemon-C8p32i-n.js +0 -357
  146. package/dist/daemon-C8p32i-n.js.map +0 -1
  147. package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
  148. package/dist/dev-preflight-CNLl4rdo.js +0 -367
  149. package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
  150. package/dist/project-DmaGLmH2.js.map +0 -1
  151. package/dist/pull-Dywm5FWP.js +0 -232
  152. package/dist/pull-Dywm5FWP.js.map +0 -1
  153. package/dist/resolve-BAeRUBhg.js +0 -74
  154. package/dist/resolve-BAeRUBhg.js.map +0 -1
  155. package/dist/state-C59Elrnt.js.map +0 -1
  156. package/templates/template/backend/src/schema.generated.ts +0 -13
@@ -0,0 +1,106 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { DEFAULT_DATA_SOURCE_KEY, getDataSourceCapabilities } from "@rebasepro/types";
4
+ //#region src/utils/collection-drift.ts
5
+ /**
6
+ * Which edits under `config/collections` can put the *SQL* schema out of date.
7
+ *
8
+ * `rebase dev` watches that directory and, on any change, either tells the
9
+ * developer to run `rebase schema generate` / `rebase db push` or runs them.
10
+ * The watcher is recursive and knows nothing about what it is watching, so it
11
+ * said that about every file under the directory — including a
12
+ * `collections/firestore/exercises.ts`, whose documents live in Firestore and
13
+ * for which there is no Drizzle schema to regenerate and no database to push
14
+ * to. Advice that is wrong on every edit is advice a developer learns to
15
+ * ignore, which is worse than none: the same box is the only warning for the
16
+ * Postgres collection next to it, where it is real.
17
+ *
18
+ * Two independent reasons a change cannot affect the SQL schema, both checked
19
+ * here:
20
+ *
21
+ * 1. **The loader would never read the file.** `loadCollectionsFromDirectory`
22
+ * reads the top level of the collections directory only — no recursion, no
23
+ * `index`, no tests, no declarations. A file it does not read cannot change
24
+ * what it returns, and the watcher must not claim otherwise.
25
+ * 2. **Every collection in it is served by another engine.** A Firestore or
26
+ * MongoDB collection has no table, no migration and no policies.
27
+ *
28
+ * The engine check reads the source text rather than importing the module: the
29
+ * CLI runs as plain Node and cannot evaluate a project's TypeScript, and a
30
+ * watcher must answer in the time between two keystrokes. Anything it cannot
31
+ * read confidently counts as SQL-affecting — a spurious warning is a nuisance,
32
+ * a suppressed one hides real drift.
33
+ */
34
+ /**
35
+ * Would `loadCollectionsFromDirectory` load this file?
36
+ *
37
+ * Mirrors that loader's own `isCollectionFile` plus its flat (non-recursive)
38
+ * scan. `relativePath` is relative to the collections directory, as `fs.watch`
39
+ * reports it.
40
+ */
41
+ function isLoadedCollectionFile(relativePath) {
42
+ const normalized = relativePath.split(path.sep).join("/");
43
+ if (normalized.includes("/")) return false;
44
+ const file = normalized;
45
+ if (!file.endsWith(".ts") && !file.endsWith(".js")) return false;
46
+ if (file.startsWith(".")) return false;
47
+ if (file.includes(".test.")) return false;
48
+ if (file.endsWith(".d.ts")) return false;
49
+ if (file === "index.ts" || file === "index.js") return false;
50
+ return true;
51
+ }
52
+ var ENGINE_LITERAL = /\bengine\s*:\s*["'`]([^"'`]+)["'`]/g;
53
+ var DATA_SOURCE_LITERAL = /\bdataSource\s*:\s*["'`]([^"'`]+)["'`]/g;
54
+ /**
55
+ * Drop comments, so a `// engine: "firestore"` in a docblock cannot silence a
56
+ * warning about the Postgres collection the file actually declares.
57
+ *
58
+ * Deliberately naive — it does not understand strings, so a `//` inside one
59
+ * (a URL in a default value) eats the rest of that line. That only ever removes
60
+ * text, and removing an engine literal makes this file *more* likely to warn,
61
+ * which is the side to be wrong on.
62
+ */
63
+ function stripComments(source) {
64
+ return source.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\n]*/g, " ");
65
+ }
66
+ function literals(source, pattern) {
67
+ const found = [];
68
+ for (const match of source.matchAll(pattern)) found.push(match[1]);
69
+ return found;
70
+ }
71
+ /**
72
+ * Does this collection source declare anything a SQL toolchain would own?
73
+ *
74
+ * The fallback order matches `resolveDataSource`: an explicit `engine` wins,
75
+ * and a collection that only names a `dataSource` is resolved as if the key
76
+ * were the engine — which is what that function does when no registry is
77
+ * available, and the CLI has none. An engine nobody recognises counts as
78
+ * relational, for the reason `isRelationalCollection` gives.
79
+ *
80
+ * A file declaring several collections is SQL-affecting if *any* of them is.
81
+ */
82
+ function declaresRelationalCollection(rawSource) {
83
+ const source = stripComments(rawSource);
84
+ const engines = literals(source, ENGINE_LITERAL);
85
+ const declared = engines.length > 0 ? engines : literals(source, DATA_SOURCE_LITERAL).filter((key) => key !== DEFAULT_DATA_SOURCE_KEY);
86
+ if (declared.length === 0) return true;
87
+ return declared.some((engine) => getDataSourceCapabilities(engine).supportsRelations);
88
+ }
89
+ /**
90
+ * Can this edit have changed the generated SQL schema?
91
+ *
92
+ * Answers `true` when it cannot tell — an unreadable file is a reason to warn,
93
+ * not a reason to go quiet.
94
+ */
95
+ function affectsSqlSchema(collectionsDir, relativePath) {
96
+ if (!isLoadedCollectionFile(relativePath)) return false;
97
+ try {
98
+ return declaresRelationalCollection(fs.readFileSync(path.join(collectionsDir, relativePath), "utf8"));
99
+ } catch {
100
+ return true;
101
+ }
102
+ }
103
+ //#endregion
104
+ export { isLoadedCollectionFile as n, affectsSqlSchema as t };
105
+
106
+ //# sourceMappingURL=collection-drift-BKj_BoMq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-drift-BKj_BoMq.js","names":[],"sources":["../src/utils/collection-drift.ts"],"sourcesContent":["/**\n * Which edits under `config/collections` can put the *SQL* schema out of date.\n *\n * `rebase dev` watches that directory and, on any change, either tells the\n * developer to run `rebase schema generate` / `rebase db push` or runs them.\n * The watcher is recursive and knows nothing about what it is watching, so it\n * said that about every file under the directory — including a\n * `collections/firestore/exercises.ts`, whose documents live in Firestore and\n * for which there is no Drizzle schema to regenerate and no database to push\n * to. Advice that is wrong on every edit is advice a developer learns to\n * ignore, which is worse than none: the same box is the only warning for the\n * Postgres collection next to it, where it is real.\n *\n * Two independent reasons a change cannot affect the SQL schema, both checked\n * here:\n *\n * 1. **The loader would never read the file.** `loadCollectionsFromDirectory`\n * reads the top level of the collections directory only — no recursion, no\n * `index`, no tests, no declarations. A file it does not read cannot change\n * what it returns, and the watcher must not claim otherwise.\n * 2. **Every collection in it is served by another engine.** A Firestore or\n * MongoDB collection has no table, no migration and no policies.\n *\n * The engine check reads the source text rather than importing the module: the\n * CLI runs as plain Node and cannot evaluate a project's TypeScript, and a\n * watcher must answer in the time between two keystrokes. Anything it cannot\n * read confidently counts as SQL-affecting — a spurious warning is a nuisance,\n * a suppressed one hides real drift.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport { DEFAULT_DATA_SOURCE_KEY, getDataSourceCapabilities } from \"@rebasepro/types\";\n\n/**\n * Would `loadCollectionsFromDirectory` load this file?\n *\n * Mirrors that loader's own `isCollectionFile` plus its flat (non-recursive)\n * scan. `relativePath` is relative to the collections directory, as `fs.watch`\n * reports it.\n */\nexport function isLoadedCollectionFile(relativePath: string): boolean {\n const normalized = relativePath.split(path.sep).join(\"/\");\n // A nested path is a subdirectory, which the loader does not descend into.\n if (normalized.includes(\"/\")) return false;\n\n const file = normalized;\n if (!file.endsWith(\".ts\") && !file.endsWith(\".js\")) return false;\n if (file.startsWith(\".\")) return false;\n if (file.includes(\".test.\")) return false;\n if (file.endsWith(\".d.ts\")) return false;\n // The directory's own module: defaults live there, not a collection.\n if (file === \"index.ts\" || file === \"index.js\") return false;\n return true;\n}\n\nconst ENGINE_LITERAL = /\\bengine\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g;\nconst DATA_SOURCE_LITERAL = /\\bdataSource\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g;\n\n/**\n * Drop comments, so a `// engine: \"firestore\"` in a docblock cannot silence a\n * warning about the Postgres collection the file actually declares.\n *\n * Deliberately naive — it does not understand strings, so a `//` inside one\n * (a URL in a default value) eats the rest of that line. That only ever removes\n * text, and removing an engine literal makes this file *more* likely to warn,\n * which is the side to be wrong on.\n */\nfunction stripComments(source: string): string {\n return source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/\\/\\/[^\\n]*/g, \" \");\n}\n\nfunction literals(source: string, pattern: RegExp): string[] {\n const found: string[] = [];\n for (const match of source.matchAll(pattern)) found.push(match[1]);\n return found;\n}\n\n/**\n * Does this collection source declare anything a SQL toolchain would own?\n *\n * The fallback order matches `resolveDataSource`: an explicit `engine` wins,\n * and a collection that only names a `dataSource` is resolved as if the key\n * were the engine — which is what that function does when no registry is\n * available, and the CLI has none. An engine nobody recognises counts as\n * relational, for the reason `isRelationalCollection` gives.\n *\n * A file declaring several collections is SQL-affecting if *any* of them is.\n */\nexport function declaresRelationalCollection(rawSource: string): boolean {\n const source = stripComments(rawSource);\n const engines = literals(source, ENGINE_LITERAL);\n const declared = engines.length > 0\n ? engines\n : literals(source, DATA_SOURCE_LITERAL).filter(key => key !== DEFAULT_DATA_SOURCE_KEY);\n\n if (declared.length === 0) return true;\n return declared.some(engine => getDataSourceCapabilities(engine).supportsRelations);\n}\n\n/**\n * Can this edit have changed the generated SQL schema?\n *\n * Answers `true` when it cannot tell — an unreadable file is a reason to warn,\n * not a reason to go quiet.\n */\nexport function affectsSqlSchema(collectionsDir: string, relativePath: string): boolean {\n if (!isLoadedCollectionFile(relativePath)) return false;\n try {\n return declaresRelationalCollection(\n fs.readFileSync(path.join(collectionsDir, relativePath), \"utf8\")\n );\n } catch {\n // Deleted between the event and the read, or unreadable. Both leave the\n // schema genuinely in question.\n return true;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,uBAAuB,cAA+B;CAClE,MAAM,aAAa,aAAa,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG;CAExD,IAAI,WAAW,SAAS,GAAG,GAAG,OAAO;CAErC,MAAM,OAAO;CACb,IAAI,CAAC,KAAK,SAAS,KAAK,KAAK,CAAC,KAAK,SAAS,KAAK,GAAG,OAAO;CAC3D,IAAI,KAAK,WAAW,GAAG,GAAG,OAAO;CACjC,IAAI,KAAK,SAAS,QAAQ,GAAG,OAAO;CACpC,IAAI,KAAK,SAAS,OAAO,GAAG,OAAO;CAEnC,IAAI,SAAS,cAAc,SAAS,YAAY,OAAO;CACvD,OAAO;AACX;AAEA,IAAM,iBAAiB;AACvB,IAAM,sBAAsB;;;;;;;;;;AAW5B,SAAS,cAAc,QAAwB;CAC3C,OAAO,OAAO,QAAQ,qBAAqB,GAAG,CAAC,CAAC,QAAQ,eAAe,GAAG;AAC9E;AAEA,SAAS,SAAS,QAAgB,SAA2B;CACzD,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG,MAAM,KAAK,MAAM,EAAE;CACjE,OAAO;AACX;;;;;;;;;;;;AAaA,SAAgB,6BAA6B,WAA4B;CACrE,MAAM,SAAS,cAAc,SAAS;CACtC,MAAM,UAAU,SAAS,QAAQ,cAAc;CAC/C,MAAM,WAAW,QAAQ,SAAS,IAC5B,UACA,SAAS,QAAQ,mBAAmB,CAAC,CAAC,QAAO,QAAO,QAAQ,uBAAuB;CAEzF,IAAI,SAAS,WAAW,GAAG,OAAO;CAClC,OAAO,SAAS,MAAK,WAAU,0BAA0B,MAAM,CAAC,CAAC,iBAAiB;AACtF;;;;;;;AAQA,SAAgB,iBAAiB,gBAAwB,cAA+B;CACpF,IAAI,CAAC,uBAAuB,YAAY,GAAG,OAAO;CAClD,IAAI;EACA,OAAO,6BACH,GAAG,aAAa,KAAK,KAAK,gBAAgB,YAAY,GAAG,MAAM,CACnE;CACJ,QAAQ;EAGJ,OAAO;CACX;AACJ"}
@@ -1,6 +1,8 @@
1
1
  import { type ApiKeyMasked, type ScopeSummary } from "@rebasepro/types";
2
2
  /** Everything the switch below dispatches, for the did-you-mean. */
3
3
  export declare const API_KEYS_SUBCOMMANDS: readonly ["list", "get", "create", "revoke", "scopes"];
4
+ /** The running backend's URL. Shared with `rebase storage`. */
5
+ export declare function resolveBaseUrl(env: Record<string, string>, projectRoot?: string): string;
4
6
  /**
5
7
  * What to print when a request fails: the server's error code and message,
6
8
  * which is what says why — `SCOPE_EXCEEDS_CREATOR`, `INVALID_SCOPES`,
@@ -0,0 +1,12 @@
1
+ export declare const CONSOLE_FLAGS: {
2
+ readonly "--eval": StringConstructor;
3
+ readonly "-e": "--eval";
4
+ readonly "--collections": StringConstructor;
5
+ readonly "-c": "--collections";
6
+ readonly "--database-url": StringConstructor;
7
+ readonly "--docker": BooleanConstructor;
8
+ };
9
+ /** Where the REPL keeps its history: the project's own `.rebase/`, which the scaffold ignores. */
10
+ export declare function consoleHistoryPath(projectRoot: string): string;
11
+ export declare function printConsoleHelp(): void;
12
+ export declare function consoleCommand(rawArgs: string[]): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import { type PreparedDatabase } from "../dev-db/prepare.js";
2
2
  import { type DevDatabase } from "../dev-db/resolve.js";
3
+ import type { AtlasDevDatabase } from "../dev-db/atlas-dev-database.js";
3
4
  /**
4
5
  * The connection string a prepared database actually answers on.
5
6
  *
@@ -69,30 +70,35 @@ export declare class ManagedDatabaseRefusal extends Error {
69
70
  /** Print a refusal exactly as the guards used to print it themselves. */
70
71
  export declare function printManagedDatabaseRefusal(refusal: ManagedDatabaseRefusal): void;
71
72
  /**
72
- * Stop an Atlas-backed subcommand before it fails inside Atlas on the managed
73
+ * The variable the driver reads for Atlas's dev database
74
+ * (`ATLAS_DEV_URL_ENV` in `@rebasepro/server-postgres`, which this CLI does not
75
+ * depend on).
76
+ */
77
+ export declare const ATLAS_DEV_URL_ENV = "REBASE_ATLAS_DEV_URL";
78
+ /**
79
+ * The empty database an Atlas-backed subcommand plans against, on the managed
73
80
  * development database.
74
81
  *
75
- * **PGlite serves exactly one database.** `CREATE DATABASE "postgres_dev_diff"`
76
- * against it reports success and creates nothing, so Atlas connects its dev-url
77
- * straight back to the database it is meant to be comparing against, finds the
78
- * project's own tables there, and stops with
79
- * `connected database is not clean: found schema "public"`. Verified on a
80
- * completely fresh scaffold, so this is not a leftover-state problem that a
81
- * reset would fix — the model does not fit the engine.
82
- *
83
- * Before this guard the failure was worse than unhelpful. The first thing the
84
- * reader hit was `pq: SSL is not enabled on the server`, whose remedy box said
85
- * to append `sslmode=disable` to `DATABASE_URL` — a variable `rebase init`
86
- * deliberately leaves unset, which is the very reason the managed database was
87
- * in use. Two errors deep, about a variable that does not exist, for a command
88
- * the quickstart told them to run.
89
- *
90
- * There is nothing to fix by trying harder here: Atlas's other dev-url option
91
- * is `docker://`, and needing Docker is precisely what the managed database
92
- * exists to avoid. So this says what the managed database can and cannot do,
93
- * and names the two things that work.
82
+ * **PGlite serves exactly one database.** Atlas computes a change by replaying
83
+ * the desired schema into a second, empty one; on a real server the driver
84
+ * makes it as `<db>_dev_diff`, but `CREATE DATABASE` against PGlite reports
85
+ * success and creates nothing, so Atlas connected straight back to the
86
+ * database it was comparing and stopped with `connected database is not
87
+ * clean`. These commands were refused outright on the managed database — and
88
+ * with them every way to drop, rename or narrow a column there, since boot
89
+ * only adds.
90
+ *
91
+ * So a throwaway second PGlite is started for the command instead — in
92
+ * memory, in this process, gone when the command ends — and handed to the
93
+ * driver as `REBASE_ATLAS_DEV_URL`. Nothing else about the push changes: the
94
+ * destructive gate is the driver's, and holds as it does everywhere.
95
+ *
96
+ * `undefined` when none is needed: another database kind (the driver makes its
97
+ * own), a subcommand that is not Atlas's, or a `REBASE_ATLAS_DEV_URL` the
98
+ * developer set. When one cannot be started — PGlite is an optional
99
+ * dependency — the old refusal stands, with the reason.
94
100
  */
95
- export declare function refuseAtlasOnManagedDatabase(rawArgs: string[], kind: string): void;
101
+ export declare function atlasDevDatabaseFor(rawArgs: string[], kind: string, env: Readonly<Record<string, string | undefined>>, start?: () => Promise<AtlasDevDatabase>): Promise<AtlasDevDatabase | undefined>;
96
102
  /**
97
103
  * Stop `rebase db branch` before it reports a branch that is not one.
98
104
  *
@@ -121,11 +127,25 @@ export declare function refuseAtlasOnManagedDatabase(rawArgs: string[], kind: st
121
127
  * an invitation to do the broken thing, and `info` would confirm a size for a
122
128
  * database that was never made.
123
129
  *
124
- * `refuseAtlasOnManagedDatabase` above is the same shape for a different
125
- * reason, and its comment named `branch` as one of the subcommands it does not
126
- * cover. It does now.
130
+ * Push, generate and migrate had the same problem — Atlas's scratch database
131
+ * is a second database too — and get a throwaway PGlite of their own instead
132
+ * (`atlasDevDatabaseFor` above). A branch cannot: it is meant to keep the
133
+ * project's data, and a throwaway instance has none.
127
134
  */
128
135
  export declare function refuseBranchOnManagedDatabase(rawArgs: string[], kind: string): void;
136
+ /**
137
+ * Resolve the active driver's CLI and the environment it should run in.
138
+ *
139
+ * Shared by the two runners below. Deliberately does NOT resolve a database:
140
+ * `schema generate` reads collection files and writes one file, and starting a
141
+ * database to run it would be a side effect nobody asked for.
142
+ */
143
+ export declare function resolveDriverCli(): Promise<{
144
+ projectRoot: string;
145
+ backendDir: string;
146
+ pluginCli: string;
147
+ env: Record<string, string>;
148
+ }>;
129
149
  /**
130
150
  * The one place this CLI spawns the driver's own CLI.
131
151
  *
@@ -147,6 +167,12 @@ export declare function refuseBranchOnManagedDatabase(rawArgs: string[], kind: s
147
167
  * tsx whenever it is installed — a devDependency of every scaffold, for exactly
148
168
  * this reason. Without it a `.ts` entry cannot run at all; a built entry still
149
169
  * runs, and the subcommands that never touch the project's TypeScript still work.
170
+ *
171
+ * tsx's loader in one Node (`node --import`) rather than the `tsx` binary,
172
+ * which is a shell shim and a relay Node in front of the same loader: one Node
173
+ * start instead of two, ~50–100 ms on each of the driver runs every `rebase
174
+ * dev` start and every collection save makes. The binary stays the fallback for
175
+ * a tsx whose loader does not resolve as a package — a global install.
150
176
  */
151
177
  export declare function spawnDriverCli(resolved: {
152
178
  projectRoot: string;
@@ -171,6 +197,20 @@ export declare function runDriverDbCommand(rawArgs: string[], options?: {
171
197
  quiet?: boolean;
172
198
  }): Promise<void>;
173
199
  export declare function dbCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
200
+ /**
201
+ * Start the compose database a `db … --docker` was asked to talk to.
202
+ *
203
+ * `--docker` resolved the compose URL and stopped there, so every `db`
204
+ * subcommand carrying it reached a container nobody had started —
205
+ * `ECONNREFUSED 127.0.0.1:5436`, two lines, no diagnosis — including the
206
+ * commands the managed-database refusals send readers to `--docker` for.
207
+ *
208
+ * `rebase dev --docker`'s preflight, called with the compose URL and nothing
209
+ * to push: this is not a schema step, and `rebase db push --docker` is the
210
+ * push. A failure here is reported and not fatal — the command runs and its
211
+ * own connection error follows, which is the same contract `dev` keeps.
212
+ */
213
+ export declare function ensureDockerDatabase(projectRoot: string, rawArgs: readonly string[]): Promise<void>;
174
214
  /** Every subcommand the family dispatches — the help table's keys. */
175
215
  export declare const DB_SUBCOMMANDS: string[];
176
216
  /**
@@ -30,6 +30,21 @@ import { type PreparedDatabase } from "../dev-db/prepare.js";
30
30
  * Exported so `dev-crash-marker.test.ts` can hold the running tsx to it.
31
31
  */
32
32
  export declare const WATCHER_RESTART_MARKER: RegExp;
33
+ /**
34
+ * Calls `onLine` with each line a child process writes to `stream`.
35
+ *
36
+ * A pipe hands over whatever has been written so far, so one line can arrive
37
+ * in two chunks. Split chunk by chunk, "Server running at http://localhost:3001"
38
+ * could read as two fragments that neither matched, and `rebase dev` then
39
+ * never announced the backend or started the admin panel. So the piece after
40
+ * the last newline is held for the next chunk, decoded as UTF-8 across chunk
41
+ * boundaries. A held piece is handed over at the end of the stream, or after
42
+ * `idleFlushMs` with nothing more written, so a prompt or a progress line
43
+ * still shows when it is written.
44
+ *
45
+ * Exported for its test.
46
+ */
47
+ export declare function forEachOutputLine(stream: NodeJS.ReadableStream | null | undefined, onLine: (line: string) => void, idleFlushMs?: number): void;
33
48
  /**
34
49
  * The corrected banner line, when the backend says it moved port.
35
50
  *
@@ -95,6 +110,16 @@ export declare function devRestartTrigger(projectRoot: string): string | null;
95
110
  * collections directory alone (`--exclude` wins over its dependency tracking),
96
111
  * and dev restarts the backend itself, once, after the regeneration — through
97
112
  * `restartTrigger`, which tsx watches.
113
+ *
114
+ * Every included directory also gets tsx's own default ignores, made absolute.
115
+ * tsx resolves those defaults (`**\/node_modules/**`, `**\/.*`, …) against its
116
+ * cwd, which is `backend/`, so they never reached `config/`, a sibling: chokidar
117
+ * walked `config/node_modules` — following symlinks — before tsx spawned the
118
+ * backend at all, and kept every file in it watched. In the monorepo's example
119
+ * app that was 17 s before the first backend line and 1,400 open files, and any
120
+ * install (or another checkout's Vite build writing `.vite-temp` deep inside
121
+ * that tree) restarted the backend. A `.DS_Store` or an editor swap file in
122
+ * `config/` restarted it too.
98
123
  */
99
124
  export declare function devWatchArgs(projectRoot: string, paths: {
100
125
  REBASE_DEV_FUNCTIONS?: string;
@@ -110,12 +135,6 @@ export declare const DEV_PORT_FILENAME = ".rebase-dev-port";
110
135
  * template still says this number, so the two cannot drift apart in silence.
111
136
  */
112
137
  export declare const SCAFFOLD_DEFAULT_PORT = 3001;
113
- /**
114
- * Compute a deterministic port from the project root path.
115
- * Range: 3001–3999 (avoids privileged ports and common services).
116
- * Two different project directories will almost always get different ports.
117
- */
118
- export declare function getProjectPort(projectRoot: string): number;
119
138
  /**
120
139
  * Which rung of the ladder below decided the port.
121
140
  *
@@ -294,6 +313,21 @@ export declare const DEV_FLAGS: {
294
313
  readonly "-P": "--port";
295
314
  readonly "--no-db": BooleanConstructor;
296
315
  };
316
+ /** What {@link ensureGeneratedSchema} did at startup. */
317
+ export type SchemaGeneration = "generated" | "skipped" | "failed";
318
+ /**
319
+ * Whether dev must still run the driver's `schema stale --fix` before the
320
+ * backend boots.
321
+ *
322
+ * Not after a regeneration that succeeded: that wrote `schema.generated.ts`
323
+ * from these collections with this driver, moments earlier, and `stale`
324
+ * compares the file against the same generator — it can only answer "nothing
325
+ * stale", and it cost a driver process (~0.6 s) on every start. The repair it
326
+ * exists for, a library upgrade that changed what the generator derives, is
327
+ * exactly what the regeneration already did. When generation was skipped or
328
+ * failed, the preflight is the remaining safety net and still runs.
329
+ */
330
+ export declare function needsStaleSchemaPreflight(generation: SchemaGeneration): boolean;
297
331
  /**
298
332
  * One variable's value out of `.env` text, or undefined when it has none.
299
333
  *
@@ -322,4 +356,67 @@ export declare function readEnvValue(envText: string, key: string): string | und
322
356
  * it is invisible in any assertion about the push's *outcome*.
323
357
  */
324
358
  export declare function schemaPushArgv(databaseUrl: string | undefined): string[];
359
+ /**
360
+ * Start-up's independent halves, overlapped rather than run one after another.
361
+ *
362
+ * `rebase dev` used to regenerate the schema and the SDK, then derive the
363
+ * resource graph (every collection evaluated again, in this process), then
364
+ * start the managed database and wait for it — about a second when it was not
365
+ * already running — and only then spawn the backend. None of the three reads
366
+ * what another writes: the generators read `config/` and write
367
+ * `backend/src/schema.generated.ts` and `generated/sdk/`; the derivation reads
368
+ * `config/resources.ts` and the collections; the database needs neither, and
369
+ * `schema generate` never connects to one. So `database` starts first and is
370
+ * collected last.
371
+ *
372
+ * `preflight` is the exception, and the reason this is not one `Promise.all`:
373
+ * on the `--docker` path it pushes the schema the generators have just written,
374
+ * so it still runs after them.
375
+ *
376
+ * A database that fails to start is reported where it always was — after the
377
+ * generators' and the preflight's output — rather than ahead of it, and it is
378
+ * never an unhandled rejection while they run.
379
+ *
380
+ * Exported for its test.
381
+ */
382
+ export declare function overlapDevStartup<T>(steps: {
383
+ generate: () => Promise<SchemaGeneration>;
384
+ preflight: () => Promise<void>;
385
+ /** Resolve and, for the managed database, start it. `null` when this run starts none. */
386
+ database: (() => Promise<T>) | null;
387
+ }): Promise<{
388
+ schemaGeneration: SchemaGeneration;
389
+ database: T | null;
390
+ }>;
391
+ /**
392
+ * Whether the admin panel can start beside the backend instead of after it.
393
+ *
394
+ * Vite has to be told the backend's URL when it starts (`VITE_API_URL`), and
395
+ * the backend's port is only certain once it has bound — so the admin panel
396
+ * used to wait for "Server running at", and the time to it was the backend's
397
+ * whole boot plus Vite's start. It can start beside the backend whenever the
398
+ * port the backend will bind is known in advance:
399
+ *
400
+ * - **named with `--port`**: the server binds it or refuses to start, never
401
+ * walks past it (`REBASE_DEV_PORT_EXPLICIT`), and `pinnedPortRefusal` has
402
+ * already checked that nothing answers there;
403
+ * - **free, and the port the backend tries first**: the server tries the port
404
+ * its last run landed on before the one it is given (`.rebase-dev-port`), so
405
+ * a remembered port must be this one — the "kept from the last run" rung —
406
+ * or absent, which it is after every clean exit, and the derived port is
407
+ * then the one tried. A port something already answers on would make the
408
+ * backend move, so that case keeps the old order.
409
+ *
410
+ * Nothing here can rule out another process taking the port in the second the
411
+ * backend boots, so `devCommand` still compares the announced port with the
412
+ * one Vite was given and restarts the admin panel when they differ.
413
+ *
414
+ * Exported for its test.
415
+ */
416
+ export declare function frontendCanStartWithBackend(options: {
417
+ projectRoot: string;
418
+ port: number;
419
+ pinned: boolean;
420
+ probe?: (host: string, port: number) => Promise<boolean>;
421
+ }): Promise<boolean>;
325
422
  export declare function devCommand(rawArgs: string[]): Promise<void>;
@@ -22,8 +22,34 @@ interface GenerateSDKArgs {
22
22
  from?: string;
23
23
  /** Bearer token for the contract endpoint. Falls back to REBASE_SERVICE_KEY. */
24
24
  token?: string;
25
+ /**
26
+ * Also register the generated `Database` for server-side code: write the
27
+ * types and the `Register` augmentation into `config/generated/`. See
28
+ * {@link writeRegistration}.
29
+ */
30
+ register?: boolean;
31
+ /**
32
+ * The directory holding `rebase.json`, where `--register` is remembered.
33
+ * Found from `cwd` when not given.
34
+ */
35
+ projectRoot?: string;
25
36
  help?: boolean;
26
37
  }
38
+ /** What `--register` writes, and what marks a project as having opted in. */
39
+ export declare const REGISTER_FILE = "register.ts";
40
+ /**
41
+ * Where `--register` writes: `generated/` beside the collections directory,
42
+ * which is `config/generated/` in a scaffolded project.
43
+ *
44
+ * Inside `config/` because that is the one directory both compiles of a
45
+ * collection file include: the backend's program (it includes
46
+ * `../config/**`) and the `config` package's own `tsc`. A registration
47
+ * there that imported `../generated/sdk/database.types` pulled a file from
48
+ * outside `config/` into that package's program, which TypeScript refuses
49
+ * (the file is not under its `rootDir`) — so the types are copied in beside
50
+ * the registration rather than imported from the SDK.
51
+ */
52
+ export declare function registrationDir(collectionsDir: string): string;
27
53
  /**
28
54
  * The base URL to show in the printed usage example.
29
55
  *
@@ -96,6 +96,14 @@ export type InitQuestion = {
96
96
  default: unknown;
97
97
  when?: (answers: Record<string, unknown>) => boolean;
98
98
  };
99
+ /**
100
+ * Why `input` cannot be this project's `DATABASE_URL`, or null when it can.
101
+ *
102
+ * The runtime refuses anything that is not a URL, and only a Postgres one can
103
+ * work, so `init` refuses the same — before the scaffold is written around it.
104
+ * The value itself is never repeated back: it may hold a password.
105
+ */
106
+ export declare function databaseUrlProblem(input: string): string | null;
99
107
  export declare function buildInitQuestions(params: BuildQuestionsParams): InitQuestion[];
100
108
  /**
101
109
  * The `cd` a user must type to enter the new project.
@@ -127,6 +135,33 @@ export declare const INIT_FLAGS: {
127
135
  "-t": string;
128
136
  "-y": string;
129
137
  };
138
+ /** What the closing "Next steps" depend on: the project's shape, and what `init` managed to do. */
139
+ export interface InitNextStepsInput {
140
+ headless: boolean;
141
+ /** `--database-url` was given, so `.env` names the user's own database. */
142
+ ownDatabase: boolean;
143
+ /** Introspection was asked for. */
144
+ introspect: boolean;
145
+ /** Introspection ran and produced collections. */
146
+ introspected: boolean;
147
+ /** Dependencies were installed. */
148
+ installed: boolean;
149
+ /** What the reader types to enter the project; "" when they are in it. */
150
+ cdTarget: string;
151
+ pm: PMCommands;
152
+ }
153
+ /**
154
+ * The "Next steps" `init` closes on, every command one that works as printed.
155
+ *
156
+ * Each flavour has its own steps, and the branch for one flavour must not run
157
+ * for another. The `--database-url` branch was checked before the headless one,
158
+ * so `init --headless --database-url` — the documented BaaS path — opened on
159
+ * `pnpm run db:push`: a script the headless scaffold does not have, for a
160
+ * schema it does not declare (its tables are the developer's own), with an
161
+ * Atlas it does not install. `init-next-steps.test.ts` holds every script
162
+ * named here to the scaffold it is printed for.
163
+ */
164
+ export declare function initNextSteps(input: InitNextStepsInput): string[];
130
165
  /**
131
166
  * The closing "AI Agent Skills" lines, each command one its reader can run.
132
167
  *
@@ -163,6 +198,29 @@ export declare function scaffoldConflictMessage(projectName: string, displayPath
163
198
  * function created is pointed at `main`.
164
199
  */
165
200
  export declare function initGitRepository(targetDirectory: string): Promise<boolean>;
201
+ /**
202
+ * Where the generated Drizzle schema for each preset ships, beside the template.
203
+ *
204
+ * `rebase dev` regenerates `backend/src/schema.generated.ts` on every start, and
205
+ * the Studio's schema editor refuses to commit over a dirty copy of it — a
206
+ * schema change must not sweep up somebody's work in progress. So whatever
207
+ * `init` writes there, and commits under `--git`, has to be byte-for-byte what
208
+ * that first regeneration produces. A stub (`export const tables = {}`) was
209
+ * rewritten on the first `rebase dev`, and every new project's first Studio
210
+ * edit was refused with `SCHEMA_EDIT_DIRTY_TREE` before its owner had changed
211
+ * a thing.
212
+ *
213
+ * The file cannot be generated here: generation loads the collection files,
214
+ * and they import `@rebasepro/cms-types`, which the project does not have
215
+ * until it is installed — `init --git` without `--install` commits first. So
216
+ * each preset's output is generated in this repository and shipped, and
217
+ * `init-generated-schema.test.ts` fails the moment one of them differs from
218
+ * what the generator writes for that preset's collections.
219
+ *
220
+ * Outside `templates/template` on purpose: a preset's schema must not be
221
+ * copied into a project that chose another preset.
222
+ */
223
+ export declare function shippedSchemaPath(preset: TemplatePreset): string;
166
224
  /**
167
225
  * Whether `port` is free — on the wildcard address *and* on both loopback addresses.
168
226
  *
@@ -215,15 +215,27 @@ export interface InstalledAgent {
215
215
  */
216
216
  export declare function detectInstalledAgents(home?: string): InstalledAgent[];
217
217
  /** Install skills for a specific agent into the project directory. */
218
- export declare function installForAgent(agentKey: AgentKey, skills: LoadedSkill[], projectDir: string): {
218
+ /**
219
+ * The file in each target directory that records what the installer wrote:
220
+ * relative path → sha256 of the bytes written. A dotfile, so no agent loads it
221
+ * as a rule.
222
+ */
223
+ export declare const SKILLS_MANIFEST = ".rebase-skills.json";
224
+ /** What one agent's install did. */
225
+ export interface AgentInstallResult {
219
226
  skills: number;
220
227
  assets: number;
221
- };
228
+ /** Files left as they are because they were edited since the last install (relative to the target dir). */
229
+ kept: string[];
230
+ /** Files of skills the bundle no longer ships, removed because nobody edited them. */
231
+ removed: string[];
232
+ }
233
+ export declare function installForAgent(agentKey: AgentKey, skills: LoadedSkill[], projectDir: string, options?: {
234
+ force?: boolean;
235
+ }): AgentInstallResult;
222
236
  /** What `installSkills` did for one agent. */
223
- export interface SkillsInstallResult {
237
+ export interface SkillsInstallResult extends AgentInstallResult {
224
238
  agent: AgentKey;
225
- skills: number;
226
- assets: number;
227
239
  /** An earlier agent in the same run that already wrote this directory. */
228
240
  sharedWith?: AgentKey;
229
241
  }
@@ -233,7 +245,9 @@ export interface SkillsInstallResult {
233
245
  * Gemini and Codex both read `.agents/skills`; installing twice would write the
234
246
  * same 21 files twice and report two installs of one directory.
235
247
  */
236
- export declare function installSkills(agents: readonly AgentKey[], skills: LoadedSkill[], projectDir: string): SkillsInstallResult[];
248
+ export declare function installSkills(agents: readonly AgentKey[], skills: LoadedSkill[], projectDir: string, options?: {
249
+ force?: boolean;
250
+ }): SkillsInstallResult[];
237
251
  /** Everything the switch below dispatches, for the did-you-mean. */
238
252
  export declare const SKILLS_SUBCOMMANDS: readonly ["install"];
239
253
  export declare function skillsCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
@@ -243,10 +257,11 @@ export declare function skillsCommand(subcommand: string | undefined, rawArgs: s
243
257
  * given.
244
258
  */
245
259
  export declare function parseAgentFlags(rawArgs: string[]): AgentKey[] | null;
246
- /** `rebase skills install`'s whole line: the agents it names, and `--mcp`. */
260
+ /** `rebase skills install`'s whole line: the agents it names, `--mcp` and `--force`. */
247
261
  export declare function parseSkillsInstallLine(rawArgs: string[]): {
248
262
  agents: AgentKey[] | null;
249
263
  mcp: boolean;
264
+ force: boolean;
250
265
  };
251
266
  /**
252
267
  * The agents a list of `--agent` values names, or null when it names none.
@@ -1,4 +1,5 @@
1
1
  import type { RebaseBundleStatic } from "@rebasepro/types";
2
+ import type { DevDatabase } from "../dev-db/resolve.js";
2
3
  /** The NODE_ENV the runtime will see, and where it comes from. */
3
4
  export interface StartNodeEnv {
4
5
  value: string | undefined;
@@ -27,4 +28,18 @@ export declare function nonProductionWarning(nodeEnv: StartNodeEnv): string[] |
27
28
  * and nothing said why. One line per such app, with a command that reaches it.
28
29
  */
29
30
  export declare function hostRoutedNotice(staticApps: readonly RebaseBundleStatic[], port: string | undefined): string[];
31
+ /**
32
+ * What to say when there is no DATABASE_URL for the runtime, or `null`.
33
+ *
34
+ * The runtime requires one, and its refusal — `DATABASE_URL: is required`, and
35
+ * a link to the self-hosting docs — is right for a deployment and says nothing
36
+ * to the reader most likely to see it: someone running the scaffold's own
37
+ * `.env`, which leaves DATABASE_URL commented out because `rebase dev` brings a
38
+ * database of its own. That database is one command away, so this names it.
39
+ *
40
+ * `kind` is what `rebase dev` runs this project on, so the line can say which
41
+ * database `rebase db url` will print. A blank value is unset, as the runtime
42
+ * reads it.
43
+ */
44
+ export declare function missingDatabaseUrl(env: Record<string, string | undefined>, kind: DevDatabase["kind"] | null): string[] | null;
30
45
  export declare function startCommand(rawArgs?: string[]): Promise<void>;