@prisma-next/cli 0.3.0-dev.12 → 0.3.0-dev.123

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 (215) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +470 -134
  3. package/dist/cli-errors-ByGuoqNj.mjs +3 -0
  4. package/dist/cli-errors-D6HxRn3A.d.mts +2 -0
  5. package/dist/cli.d.mts +1 -0
  6. package/dist/cli.js +1 -2350
  7. package/dist/cli.mjs +242 -0
  8. package/dist/cli.mjs.map +1 -0
  9. package/dist/client-612RJJD_.mjs +1069 -0
  10. package/dist/client-612RJJD_.mjs.map +1 -0
  11. package/dist/commands/contract-emit.d.mts +7 -0
  12. package/dist/commands/contract-emit.d.mts.map +1 -0
  13. package/dist/commands/contract-emit.mjs +8 -0
  14. package/dist/commands/contract-infer.d.mts +7 -0
  15. package/dist/commands/contract-infer.d.mts.map +1 -0
  16. package/dist/commands/contract-infer.mjs +9 -0
  17. package/dist/commands/db-init.d.mts +7 -0
  18. package/dist/commands/db-init.d.mts.map +1 -0
  19. package/dist/commands/db-init.mjs +125 -0
  20. package/dist/commands/db-init.mjs.map +1 -0
  21. package/dist/commands/db-schema.d.mts +7 -0
  22. package/dist/commands/db-schema.d.mts.map +1 -0
  23. package/dist/commands/db-schema.mjs +55 -0
  24. package/dist/commands/db-schema.mjs.map +1 -0
  25. package/dist/commands/db-sign.d.mts +7 -0
  26. package/dist/commands/db-sign.d.mts.map +1 -0
  27. package/dist/commands/db-sign.mjs +136 -0
  28. package/dist/commands/db-sign.mjs.map +1 -0
  29. package/dist/commands/db-update.d.mts +7 -0
  30. package/dist/commands/db-update.d.mts.map +1 -0
  31. package/dist/commands/db-update.mjs +122 -0
  32. package/dist/commands/db-update.mjs.map +1 -0
  33. package/dist/commands/db-verify.d.mts +7 -0
  34. package/dist/commands/db-verify.d.mts.map +1 -0
  35. package/dist/commands/db-verify.mjs +311 -0
  36. package/dist/commands/db-verify.mjs.map +1 -0
  37. package/dist/commands/migration-apply.d.mts +36 -0
  38. package/dist/commands/migration-apply.d.mts.map +1 -0
  39. package/dist/commands/migration-apply.mjs +241 -0
  40. package/dist/commands/migration-apply.mjs.map +1 -0
  41. package/dist/commands/migration-plan.d.mts +47 -0
  42. package/dist/commands/migration-plan.d.mts.map +1 -0
  43. package/dist/commands/migration-plan.mjs +288 -0
  44. package/dist/commands/migration-plan.mjs.map +1 -0
  45. package/dist/commands/migration-ref.d.mts +43 -0
  46. package/dist/commands/migration-ref.d.mts.map +1 -0
  47. package/dist/commands/migration-ref.mjs +194 -0
  48. package/dist/commands/migration-ref.mjs.map +1 -0
  49. package/dist/commands/migration-show.d.mts +28 -0
  50. package/dist/commands/migration-show.d.mts.map +1 -0
  51. package/dist/commands/migration-show.mjs +139 -0
  52. package/dist/commands/migration-show.mjs.map +1 -0
  53. package/dist/commands/migration-status.d.mts +85 -0
  54. package/dist/commands/migration-status.d.mts.map +1 -0
  55. package/dist/commands/migration-status.mjs +8 -0
  56. package/dist/commands/migration-verify.d.mts +16 -0
  57. package/dist/commands/migration-verify.d.mts.map +1 -0
  58. package/dist/commands/migration-verify.mjs +87 -0
  59. package/dist/commands/migration-verify.mjs.map +1 -0
  60. package/dist/config-loader-d_KF19Tw.mjs +43 -0
  61. package/dist/config-loader-d_KF19Tw.mjs.map +1 -0
  62. package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
  63. package/dist/config-loader.d.mts.map +1 -0
  64. package/dist/config-loader.mjs +3 -0
  65. package/dist/contract-emit-CVv7dbQ9.mjs +187 -0
  66. package/dist/contract-emit-CVv7dbQ9.mjs.map +1 -0
  67. package/dist/contract-infer-Bvw8u8Eu.mjs +83 -0
  68. package/dist/contract-infer-Bvw8u8Eu.mjs.map +1 -0
  69. package/dist/exports/config-types.d.mts +2 -0
  70. package/dist/exports/config-types.mjs +3 -0
  71. package/dist/exports/control-api.d.mts +626 -0
  72. package/dist/exports/control-api.d.mts.map +1 -0
  73. package/dist/exports/control-api.mjs +107 -0
  74. package/dist/exports/control-api.mjs.map +1 -0
  75. package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +10 -5
  76. package/dist/exports/index.d.mts.map +1 -0
  77. package/dist/exports/index.mjs +134 -0
  78. package/dist/exports/index.mjs.map +1 -0
  79. package/dist/extract-sql-ddl-Jf5blEO0.mjs +26 -0
  80. package/dist/extract-sql-ddl-Jf5blEO0.mjs.map +1 -0
  81. package/dist/framework-components-M2j-qPfr.mjs +59 -0
  82. package/dist/framework-components-M2j-qPfr.mjs.map +1 -0
  83. package/dist/inspect-live-schema-BQe5i4YE.mjs +90 -0
  84. package/dist/inspect-live-schema-BQe5i4YE.mjs.map +1 -0
  85. package/dist/migration-command-scaffold-SLrjcKXS.mjs +104 -0
  86. package/dist/migration-command-scaffold-SLrjcKXS.mjs.map +1 -0
  87. package/dist/migration-status-B7OVZ-Ka.mjs +1576 -0
  88. package/dist/migration-status-B7OVZ-Ka.mjs.map +1 -0
  89. package/dist/migrations-Db_ea9eE.mjs +173 -0
  90. package/dist/migrations-Db_ea9eE.mjs.map +1 -0
  91. package/dist/progress-adapter-DRNe2idZ.mjs +43 -0
  92. package/dist/progress-adapter-DRNe2idZ.mjs.map +1 -0
  93. package/dist/terminal-ui-DAcMBRKf.mjs +980 -0
  94. package/dist/terminal-ui-DAcMBRKf.mjs.map +1 -0
  95. package/dist/verify-DXKxBFvU.mjs +385 -0
  96. package/dist/verify-DXKxBFvU.mjs.map +1 -0
  97. package/package.json +85 -40
  98. package/src/cli.ts +109 -58
  99. package/src/commands/contract-emit.ts +236 -143
  100. package/src/commands/contract-infer-paths.ts +32 -0
  101. package/src/commands/contract-infer.ts +131 -0
  102. package/src/commands/db-init.ts +211 -425
  103. package/src/commands/db-schema.ts +77 -0
  104. package/src/commands/db-sign.ts +207 -228
  105. package/src/commands/db-update.ts +236 -0
  106. package/src/commands/db-verify.ts +484 -186
  107. package/src/commands/inspect-live-schema.ts +171 -0
  108. package/src/commands/migration-apply.ts +416 -0
  109. package/src/commands/migration-plan.ts +451 -0
  110. package/src/commands/migration-ref.ts +305 -0
  111. package/src/commands/migration-show.ts +246 -0
  112. package/src/commands/migration-status.ts +838 -0
  113. package/src/commands/migration-verify.ts +134 -0
  114. package/src/config-loader.ts +13 -3
  115. package/src/control-api/client.ts +614 -0
  116. package/src/control-api/contract-enrichment.ts +135 -0
  117. package/src/control-api/errors.ts +9 -0
  118. package/src/control-api/operations/contract-emit.ts +173 -0
  119. package/src/control-api/operations/db-init.ts +286 -0
  120. package/src/control-api/operations/db-update.ts +221 -0
  121. package/src/control-api/operations/extract-sql-ddl.ts +47 -0
  122. package/src/control-api/operations/migration-apply.ts +194 -0
  123. package/src/control-api/operations/migration-helpers.ts +49 -0
  124. package/src/control-api/types.ts +683 -0
  125. package/src/exports/config-types.ts +4 -3
  126. package/src/exports/control-api.ts +56 -0
  127. package/src/load-ts-contract.ts +16 -11
  128. package/src/utils/cli-errors.ts +5 -2
  129. package/src/utils/command-helpers.ts +293 -3
  130. package/src/utils/formatters/emit.ts +67 -0
  131. package/src/utils/formatters/errors.ts +82 -0
  132. package/src/utils/formatters/graph-migration-mapper.ts +220 -0
  133. package/src/utils/formatters/graph-render.ts +1317 -0
  134. package/src/utils/formatters/graph-types.ts +114 -0
  135. package/src/utils/formatters/help.ts +380 -0
  136. package/src/utils/formatters/helpers.ts +28 -0
  137. package/src/utils/formatters/migrations.ts +346 -0
  138. package/src/utils/formatters/styled.ts +212 -0
  139. package/src/utils/formatters/verify.ts +620 -0
  140. package/src/utils/global-flags.ts +41 -23
  141. package/src/utils/migration-command-scaffold.ts +187 -0
  142. package/src/utils/migration-types.ts +12 -0
  143. package/src/utils/progress-adapter.ts +75 -0
  144. package/src/utils/result-handler.ts +12 -13
  145. package/src/utils/shutdown.ts +92 -0
  146. package/src/utils/suggest-command.ts +31 -0
  147. package/src/utils/terminal-ui.ts +276 -0
  148. package/dist/chunk-BZMBKEEQ.js +0 -997
  149. package/dist/chunk-BZMBKEEQ.js.map +0 -1
  150. package/dist/chunk-CVNWLFXO.js +0 -91
  151. package/dist/chunk-CVNWLFXO.js.map +0 -1
  152. package/dist/chunk-HWYQOCAJ.js +0 -47
  153. package/dist/chunk-HWYQOCAJ.js.map +0 -1
  154. package/dist/chunk-QUPBU4KV.js +0 -131
  155. package/dist/chunk-QUPBU4KV.js.map +0 -1
  156. package/dist/cli.d.ts +0 -2
  157. package/dist/cli.d.ts.map +0 -1
  158. package/dist/cli.js.map +0 -1
  159. package/dist/commands/contract-emit.d.ts +0 -3
  160. package/dist/commands/contract-emit.d.ts.map +0 -1
  161. package/dist/commands/contract-emit.js +0 -9
  162. package/dist/commands/contract-emit.js.map +0 -1
  163. package/dist/commands/db-init.d.ts +0 -3
  164. package/dist/commands/db-init.d.ts.map +0 -1
  165. package/dist/commands/db-init.js +0 -337
  166. package/dist/commands/db-init.js.map +0 -1
  167. package/dist/commands/db-introspect.d.ts +0 -3
  168. package/dist/commands/db-introspect.d.ts.map +0 -1
  169. package/dist/commands/db-introspect.js +0 -186
  170. package/dist/commands/db-introspect.js.map +0 -1
  171. package/dist/commands/db-schema-verify.d.ts +0 -3
  172. package/dist/commands/db-schema-verify.d.ts.map +0 -1
  173. package/dist/commands/db-schema-verify.js +0 -160
  174. package/dist/commands/db-schema-verify.js.map +0 -1
  175. package/dist/commands/db-sign.d.ts +0 -3
  176. package/dist/commands/db-sign.d.ts.map +0 -1
  177. package/dist/commands/db-sign.js +0 -195
  178. package/dist/commands/db-sign.js.map +0 -1
  179. package/dist/commands/db-verify.d.ts +0 -3
  180. package/dist/commands/db-verify.d.ts.map +0 -1
  181. package/dist/commands/db-verify.js +0 -169
  182. package/dist/commands/db-verify.js.map +0 -1
  183. package/dist/config-loader.d.ts.map +0 -1
  184. package/dist/config-loader.js +0 -7
  185. package/dist/config-loader.js.map +0 -1
  186. package/dist/exports/config-types.d.ts +0 -3
  187. package/dist/exports/config-types.d.ts.map +0 -1
  188. package/dist/exports/config-types.js +0 -6
  189. package/dist/exports/config-types.js.map +0 -1
  190. package/dist/exports/index.d.ts +0 -4
  191. package/dist/exports/index.d.ts.map +0 -1
  192. package/dist/exports/index.js +0 -175
  193. package/dist/exports/index.js.map +0 -1
  194. package/dist/load-ts-contract.d.ts.map +0 -1
  195. package/dist/utils/action.d.ts +0 -16
  196. package/dist/utils/action.d.ts.map +0 -1
  197. package/dist/utils/cli-errors.d.ts +0 -7
  198. package/dist/utils/cli-errors.d.ts.map +0 -1
  199. package/dist/utils/command-helpers.d.ts +0 -12
  200. package/dist/utils/command-helpers.d.ts.map +0 -1
  201. package/dist/utils/framework-components.d.ts +0 -70
  202. package/dist/utils/framework-components.d.ts.map +0 -1
  203. package/dist/utils/global-flags.d.ts +0 -25
  204. package/dist/utils/global-flags.d.ts.map +0 -1
  205. package/dist/utils/output.d.ts +0 -142
  206. package/dist/utils/output.d.ts.map +0 -1
  207. package/dist/utils/result-handler.d.ts +0 -15
  208. package/dist/utils/result-handler.d.ts.map +0 -1
  209. package/dist/utils/spinner.d.ts +0 -29
  210. package/dist/utils/spinner.d.ts.map +0 -1
  211. package/src/commands/db-introspect.ts +0 -256
  212. package/src/commands/db-schema-verify.ts +0 -232
  213. package/src/utils/action.ts +0 -43
  214. package/src/utils/output.ts +0 -1471
  215. package/src/utils/spinner.ts +0 -67
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma-next/cli",
3
- "version": "0.3.0-dev.12",
3
+ "version": "0.3.0-dev.123",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -11,79 +11,124 @@
11
11
  "prisma-next": "./dist/cli.js"
12
12
  },
13
13
  "dependencies": {
14
+ "@clack/prompts": "^1.1.0",
15
+ "@dagrejs/dagre": "^3.0.0",
14
16
  "arktype": "^2.0.0",
15
17
  "c12": "^3.3.2",
18
+ "closest-match": "^1.3.3",
16
19
  "colorette": "^2.0.20",
17
20
  "commander": "^12.0.0",
18
- "esbuild": "^0.19.0",
19
- "ora": "^8.1.1",
20
- "string-width": "^7.2.0",
21
+ "esbuild": "^0.25.11",
22
+ "pathe": "^2.0.3",
23
+ "string-width": "^8.2.0",
21
24
  "strip-ansi": "^7.1.2",
22
- "wrap-ansi": "^9.0.2",
23
- "@prisma-next/contract": "0.3.0-dev.12",
24
- "@prisma-next/core-control-plane": "0.3.0-dev.12",
25
- "@prisma-next/emitter": "0.3.0-dev.12",
26
- "@prisma-next/utils": "0.3.0-dev.12"
25
+ "wrap-ansi": "^10.0.0",
26
+ "@prisma-next/config": "0.3.0-dev.123",
27
+ "@prisma-next/contract": "0.3.0-dev.123",
28
+ "@prisma-next/core-control-plane": "0.3.0-dev.123",
29
+ "@prisma-next/emitter": "0.3.0-dev.123",
30
+ "@prisma-next/psl-printer": "0.3.0-dev.123",
31
+ "@prisma-next/migration-tools": "0.3.0-dev.123",
32
+ "@prisma-next/utils": "0.3.0-dev.123"
27
33
  },
28
34
  "devDependencies": {
29
35
  "@types/node": "24.10.4",
30
- "@vitest/coverage-v8": "4.0.16",
31
- "tsup": "8.5.1",
36
+ "tsdown": "0.18.4",
32
37
  "typescript": "5.9.3",
33
- "vitest": "4.0.16",
34
- "@prisma-next/sql-contract": "0.3.0-dev.12",
35
- "@prisma-next/sql-contract-emitter": "0.3.0-dev.12",
36
- "@prisma-next/sql-contract-ts": "0.3.0-dev.12",
37
- "@prisma-next/sql-operations": "0.3.0-dev.12",
38
- "@prisma-next/sql-runtime": "0.3.0-dev.12",
39
- "@prisma-next/test-utils": "0.0.1"
38
+ "vitest": "4.0.17",
39
+ "@prisma-next/sql-contract": "0.3.0-dev.123",
40
+ "@prisma-next/sql-contract-emitter": "0.3.0-dev.123",
41
+ "@prisma-next/sql-contract-ts": "0.3.0-dev.123",
42
+ "@prisma-next/sql-operations": "0.3.0-dev.123",
43
+ "@prisma-next/test-utils": "0.0.1",
44
+ "@prisma-next/tsconfig": "0.0.0",
45
+ "@prisma-next/tsdown": "0.0.0",
46
+ "@prisma-next/sql-runtime": "0.3.0-dev.123"
40
47
  },
41
48
  "exports": {
42
49
  ".": {
43
- "types": "./dist/exports/index.d.ts",
44
- "import": "./dist/exports/index.js"
50
+ "types": "./dist/exports/index.d.mts",
51
+ "import": "./dist/exports/index.mjs"
45
52
  },
46
53
  "./config-types": {
47
- "types": "./dist/exports/config-types.d.ts",
48
- "import": "./dist/exports/config-types.js"
54
+ "types": "./dist/exports/config-types.d.mts",
55
+ "import": "./dist/exports/config-types.mjs"
49
56
  },
50
57
  "./commands/db-init": {
51
- "types": "./dist/commands/db-init.d.ts",
52
- "import": "./dist/commands/db-init.js"
58
+ "types": "./dist/commands/db-init.d.mts",
59
+ "import": "./dist/commands/db-init.mjs"
53
60
  },
54
- "./commands/db-introspect": {
55
- "types": "./dist/commands/db-introspect.d.ts",
56
- "import": "./dist/commands/db-introspect.js"
61
+ "./commands/db-update": {
62
+ "types": "./dist/commands/db-update.d.mts",
63
+ "import": "./dist/commands/db-update.mjs"
57
64
  },
58
- "./commands/db-schema-verify": {
59
- "types": "./dist/commands/db-schema-verify.d.ts",
60
- "import": "./dist/commands/db-schema-verify.js"
65
+ "./commands/db-schema": {
66
+ "types": "./dist/commands/db-schema.d.mts",
67
+ "import": "./dist/commands/db-schema.mjs"
61
68
  },
62
69
  "./commands/db-sign": {
63
- "types": "./dist/commands/db-sign.d.ts",
64
- "import": "./dist/commands/db-sign.js"
70
+ "types": "./dist/commands/db-sign.d.mts",
71
+ "import": "./dist/commands/db-sign.mjs"
65
72
  },
66
73
  "./commands/db-verify": {
67
- "types": "./dist/commands/db-verify.d.ts",
68
- "import": "./dist/commands/db-verify.js"
74
+ "types": "./dist/commands/db-verify.d.mts",
75
+ "import": "./dist/commands/db-verify.mjs"
69
76
  },
70
77
  "./commands/contract-emit": {
71
- "types": "./dist/commands/contract-emit.d.ts",
72
- "import": "./dist/commands/contract-emit.js"
78
+ "types": "./dist/commands/contract-emit.d.mts",
79
+ "import": "./dist/commands/contract-emit.mjs"
80
+ },
81
+ "./commands/contract-infer": {
82
+ "types": "./dist/commands/contract-infer.d.mts",
83
+ "import": "./dist/commands/contract-infer.mjs"
84
+ },
85
+ "./commands/migration-plan": {
86
+ "types": "./dist/commands/migration-plan.d.mts",
87
+ "import": "./dist/commands/migration-plan.mjs"
88
+ },
89
+ "./commands/migration-show": {
90
+ "types": "./dist/commands/migration-show.d.mts",
91
+ "import": "./dist/commands/migration-show.mjs"
92
+ },
93
+ "./commands/migration-status": {
94
+ "types": "./dist/commands/migration-status.d.mts",
95
+ "import": "./dist/commands/migration-status.mjs"
96
+ },
97
+ "./commands/migration-verify": {
98
+ "types": "./dist/commands/migration-verify.d.mts",
99
+ "import": "./dist/commands/migration-verify.mjs"
100
+ },
101
+ "./commands/migration-apply": {
102
+ "types": "./dist/commands/migration-apply.d.mts",
103
+ "import": "./dist/commands/migration-apply.mjs"
104
+ },
105
+ "./commands/migration-ref": {
106
+ "types": "./dist/commands/migration-ref.d.mts",
107
+ "import": "./dist/commands/migration-ref.mjs"
73
108
  },
74
109
  "./config-loader": {
75
- "types": "./dist/config-loader.d.ts",
76
- "import": "./dist/config-loader.js"
110
+ "types": "./dist/config-loader.d.mts",
111
+ "import": "./dist/config-loader.mjs"
112
+ },
113
+ "./control-api": {
114
+ "types": "./dist/exports/control-api.d.mts",
115
+ "import": "./dist/exports/control-api.mjs"
77
116
  }
78
117
  },
118
+ "repository": {
119
+ "type": "git",
120
+ "url": "https://github.com/prisma/prisma-next.git",
121
+ "directory": "packages/1-framework/3-tooling/cli"
122
+ },
79
123
  "scripts": {
80
- "build": "tsup --config tsup.config.ts && tsc --project tsconfig.build.json",
124
+ "build": "tsdown && node ./scripts/write-cli-js-compat.mjs",
81
125
  "test": "vitest run",
82
126
  "test:coverage": "vitest run --coverage",
83
127
  "typecheck": "tsc --project tsconfig.json --noEmit",
84
128
  "lint": "biome check . --error-on-warnings",
85
129
  "lint:fix": "biome check --write .",
86
130
  "lint:fix:unsafe": "biome check --write --unsafe .",
87
- "clean": "node ../../../../scripts/clean.mjs"
131
+ "record": "tsx scripts/record.ts",
132
+ "clean": "rm -rf dist dist-tsc dist-tsc-prod coverage .tmp-output"
88
133
  }
89
134
  }
package/src/cli.ts CHANGED
@@ -1,13 +1,39 @@
1
1
  import { Command } from 'commander';
2
2
  import { createContractEmitCommand } from './commands/contract-emit';
3
+ import { createContractInferCommand } from './commands/contract-infer';
4
+ import { installShutdownHandlers } from './utils/shutdown';
5
+
6
+ // Install SIGINT/SIGTERM handlers before anything else
7
+ installShutdownHandlers();
8
+
3
9
  import { createDbInitCommand } from './commands/db-init';
4
- import { createDbIntrospectCommand } from './commands/db-introspect';
5
- import { createDbSchemaVerifyCommand } from './commands/db-schema-verify';
10
+ import { createDbSchemaCommand } from './commands/db-schema';
6
11
  import { createDbSignCommand } from './commands/db-sign';
12
+ import { createDbUpdateCommand } from './commands/db-update';
7
13
  import { createDbVerifyCommand } from './commands/db-verify';
14
+ import { createMigrationApplyCommand } from './commands/migration-apply';
15
+ import { createMigrationPlanCommand } from './commands/migration-plan';
16
+ import { createMigrationRefCommand } from './commands/migration-ref';
17
+ import { createMigrationShowCommand } from './commands/migration-show';
18
+ import { createMigrationStatusCommand } from './commands/migration-status';
19
+ import { createMigrationVerifyCommand } from './commands/migration-verify';
8
20
  import { setCommandDescriptions } from './utils/command-helpers';
21
+ import { formatCommandHelp, formatRootHelp } from './utils/formatters/help';
9
22
  import { parseGlobalFlags } from './utils/global-flags';
10
- import { formatCommandHelp, formatRootHelp } from './utils/output';
23
+ import { suggestCommands } from './utils/suggest-command';
24
+
25
+ /**
26
+ * Formats the "Did you mean ...?" hint for an unknown command.
27
+ */
28
+ function formatSuggestion(input: string, candidates: readonly string[]): string {
29
+ const suggestions = suggestCommands(
30
+ input,
31
+ candidates.map((c) => c),
32
+ );
33
+ if (suggestions.length === 0) return '';
34
+ if (suggestions.length === 1) return `\nDid you mean ${suggestions[0]}?\n`;
35
+ return `\nDid you mean one of these?\n${suggestions.map((s) => ` ${s}`).join('\n')}\n`;
36
+ }
11
37
 
12
38
  const program = new Command();
13
39
 
@@ -43,14 +69,11 @@ program.configureHelp({
43
69
  // Commands handle structured errors themselves via process.exit()
44
70
  program.exitOverride((err) => {
45
71
  if (err) {
46
- // Help requests are not errors - allow Commander to output help and exit normally
47
- // Commander throws errors with codes like 'commander.help', 'commander.helpDisplayed', or 'outputHelp'
48
72
  const errorCode = (err as { code?: string }).code;
49
73
  const errorMessage = String(err.message ?? '');
50
74
  const errorName = err.name ?? '';
51
75
 
52
- // Check for unknown command errors first (before other checks)
53
- // Commander.js uses code 'commander.unknownCommand' or error message contains 'unknown command'
76
+ // Unknown command/argument exit 2 (CLI usage error)
54
77
  const isUnknownCommandError =
55
78
  errorCode === 'commander.unknownCommand' ||
56
79
  errorCode === 'commander.unknownArgument' ||
@@ -58,40 +81,34 @@ program.exitOverride((err) => {
58
81
  (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));
59
82
  if (isUnknownCommandError) {
60
83
  const flags = parseGlobalFlags({});
61
- // Extract the command/subcommand name from the error message
62
- // Error message format: "unknown command 'command-name'"
63
84
  const match = errorMessage.match(/unknown command ['"]([^'"]+)['"]/);
64
85
  const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';
65
86
 
66
- // Determine which command context we're in
67
- // Check if the first argument is a recognized parent command
68
87
  const firstArg = process.argv[2];
69
88
  const parentCommand = firstArg
70
89
  ? program.commands.find((cmd) => cmd.name() === firstArg)
71
90
  : undefined;
72
91
 
73
92
  if (parentCommand && commandName !== firstArg) {
74
- // Unrecognized subcommand - show parent command help
75
- // eslint-disable-next-line no-console
76
- console.error(`Unknown command: ${commandName}`);
77
- // eslint-disable-next-line no-console
78
- console.error('');
93
+ const subNames = parentCommand.commands.map((c) => c.name());
94
+ process.stderr.write(
95
+ `Unknown command: ${commandName}${formatSuggestion(commandName!, subNames)}\n`,
96
+ );
79
97
  const helpText = formatCommandHelp({ command: parentCommand, flags });
80
- // eslint-disable-next-line no-console
81
- console.log(helpText);
98
+ process.stderr.write(`${helpText}\n`);
82
99
  } else {
83
- // Unrecognized top-level command - show root help
84
- // eslint-disable-next-line no-console
85
- console.error(`Unknown command: ${commandName}`);
86
- // eslint-disable-next-line no-console
87
- console.error('');
100
+ const topNames = program.commands.map((c) => c.name());
101
+ process.stderr.write(
102
+ `Unknown command: ${commandName}${formatSuggestion(commandName!, topNames)}\n`,
103
+ );
88
104
  const helpText = formatRootHelp({ program, flags });
89
- // eslint-disable-next-line no-console
90
- console.log(helpText);
105
+ process.stderr.write(`${helpText}\n`);
91
106
  }
92
- process.exit(1);
107
+ process.exit(2);
93
108
  return;
94
109
  }
110
+
111
+ // Help requests → exit 0
95
112
  const isHelpError =
96
113
  errorCode === 'commander.help' ||
97
114
  errorCode === 'commander.helpDisplayed' ||
@@ -103,25 +120,22 @@ program.exitOverride((err) => {
103
120
  process.exit(0);
104
121
  return;
105
122
  }
106
- // Missing required arguments/subcommands - show help and exit with 0
107
- // Commander throws errors with code 'commander.missingArgument' or 'commander.missingMandatoryOptionValue'
108
- // or when a command with subcommands is called without a subcommand
123
+
124
+ // Missing required arguments exit 2 (CLI usage error)
109
125
  const isMissingArgumentError =
110
126
  errorCode === 'commander.missingArgument' ||
111
127
  errorCode === 'commander.missingMandatoryOptionValue' ||
112
128
  (errorName === 'CommanderError' &&
113
129
  (errorMessage.includes('missing') || errorMessage.includes('required')));
114
130
  if (isMissingArgumentError) {
115
- // Help was already displayed by Commander.js, just exit with 0
116
- process.exit(0);
131
+ process.exit(2);
117
132
  return;
118
133
  }
119
- // Unhandled error - fail fast with exit code 1
120
- // eslint-disable-next-line no-console
121
- console.error(`Unhandled error: ${err.message}`);
134
+
135
+ // Unhandled error → exit 1
136
+ process.stderr.write(`Unhandled error: ${err.message}\n`);
122
137
  if (err.stack) {
123
- // eslint-disable-next-line no-console
124
- console.error(err.stack);
138
+ process.stderr.write(`${err.stack}\n`);
125
139
  }
126
140
  process.exit(1);
127
141
  }
@@ -148,6 +162,10 @@ contractCommand.configureHelp({
148
162
  const contractEmitCommand = createContractEmitCommand();
149
163
  contractCommand.addCommand(contractEmitCommand);
150
164
 
165
+ // Add infer subcommand to contract
166
+ const contractInferCommand = createContractInferCommand();
167
+ contractCommand.addCommand(contractInferCommand);
168
+
151
169
  // Register contract command
152
170
  program.addCommand(contractCommand);
153
171
 
@@ -175,13 +193,13 @@ dbCommand.addCommand(dbVerifyCommand);
175
193
  const dbInitCommand = createDbInitCommand();
176
194
  dbCommand.addCommand(dbInitCommand);
177
195
 
178
- // Add introspect subcommand to db
179
- const dbIntrospectCommand = createDbIntrospectCommand();
180
- dbCommand.addCommand(dbIntrospectCommand);
196
+ // Add update subcommand to db
197
+ const dbUpdateCommand = createDbUpdateCommand();
198
+ dbCommand.addCommand(dbUpdateCommand);
181
199
 
182
- // Add schema-verify subcommand to db
183
- const dbSchemaVerifyCommand = createDbSchemaVerifyCommand();
184
- dbCommand.addCommand(dbSchemaVerifyCommand);
200
+ // Add schema subcommand to db
201
+ const dbSchemaCommand = createDbSchemaCommand();
202
+ dbCommand.addCommand(dbSchemaCommand);
185
203
 
186
204
  // Add sign subcommand to db
187
205
  const dbSignCommand = createDbSignCommand();
@@ -190,6 +208,42 @@ dbCommand.addCommand(dbSignCommand);
190
208
  // Register db command
191
209
  program.addCommand(dbCommand);
192
210
 
211
+ // Register migration subcommand
212
+ const migrationCommand = new Command('migration');
213
+ setCommandDescriptions(
214
+ migrationCommand,
215
+ 'On-disk migration management commands',
216
+ 'Plan, apply, verify, and scaffold on-disk migration packages. Migrations are\n' +
217
+ 'contract-to-contract edges stored as versioned directories under migrations/.',
218
+ );
219
+ migrationCommand.configureHelp({
220
+ formatHelp: (cmd) => {
221
+ const flags = parseGlobalFlags({});
222
+ return formatCommandHelp({ command: cmd, flags });
223
+ },
224
+ subcommandDescription: () => '',
225
+ });
226
+
227
+ const migrationPlanCommand = createMigrationPlanCommand();
228
+ migrationCommand.addCommand(migrationPlanCommand);
229
+
230
+ const migrationShowCommand = createMigrationShowCommand();
231
+ migrationCommand.addCommand(migrationShowCommand);
232
+
233
+ const migrationStatusCommand = createMigrationStatusCommand();
234
+ migrationCommand.addCommand(migrationStatusCommand);
235
+
236
+ const migrationVerifyCommand = createMigrationVerifyCommand();
237
+ migrationCommand.addCommand(migrationVerifyCommand);
238
+
239
+ const migrationApplyCommand = createMigrationApplyCommand();
240
+ migrationCommand.addCommand(migrationApplyCommand);
241
+
242
+ const migrationRefCommand = createMigrationRefCommand();
243
+ migrationCommand.addCommand(migrationRefCommand);
244
+
245
+ program.addCommand(migrationCommand);
246
+
193
247
  // Create help command
194
248
  const helpCommand = new Command('help')
195
249
  .description('Show usage instructions')
@@ -202,8 +256,8 @@ const helpCommand = new Command('help')
202
256
  .action(() => {
203
257
  const flags = parseGlobalFlags({});
204
258
  const helpText = formatRootHelp({ program, flags });
205
- // eslint-disable-next-line no-console
206
- console.log(helpText);
259
+ // Help is decoration → stderr
260
+ process.stderr.write(`${helpText}\n`);
207
261
  process.exit(0);
208
262
  });
209
263
 
@@ -213,8 +267,7 @@ program.addCommand(helpCommand);
213
267
  program.action(() => {
214
268
  const flags = parseGlobalFlags({});
215
269
  const helpText = formatRootHelp({ program, flags });
216
- // eslint-disable-next-line no-console
217
- console.log(helpText);
270
+ process.stderr.write(`${helpText}\n`);
218
271
  process.exit(0);
219
272
  });
220
273
 
@@ -225,8 +278,8 @@ if (args.length > 0) {
225
278
  const commandName = args[0];
226
279
  // Handle version option explicitly since we suppress default output
227
280
  if (commandName === '--version' || commandName === '-V') {
228
- // eslint-disable-next-line no-console
229
- console.log(program.version());
281
+ // Version is data → stdout
282
+ process.stdout.write(`${program.version()}\n`);
230
283
  process.exit(0);
231
284
  }
232
285
  // Skip command check for global options like --help, -h
@@ -236,22 +289,20 @@ if (args.length > 0) {
236
289
  const command = program.commands.find((cmd) => cmd.name() === commandName);
237
290
 
238
291
  if (!command) {
239
- // Unrecognized command - show error message and usage
292
+ // Unrecognized command exit 2 (CLI usage error)
240
293
  const flags = parseGlobalFlags({});
241
- // eslint-disable-next-line no-console
242
- console.error(`Unknown command: ${commandName}`);
243
- // eslint-disable-next-line no-console
244
- console.error('');
294
+ const topNames = program.commands.map((c) => c.name());
295
+ process.stderr.write(
296
+ `Unknown command: ${commandName}${formatSuggestion(commandName!, topNames)}\n`,
297
+ );
245
298
  const helpText = formatRootHelp({ program, flags });
246
- // eslint-disable-next-line no-console
247
- console.log(helpText);
248
- process.exit(1);
299
+ process.stderr.write(`${helpText}\n`);
300
+ process.exit(2);
249
301
  } else if (command.commands.length > 0 && args.length === 1) {
250
302
  // Parent command called with no subcommand - show help and exit with 0
251
303
  const flags = parseGlobalFlags({});
252
304
  const helpText = formatCommandHelp({ command, flags });
253
- // eslint-disable-next-line no-console
254
- console.log(helpText);
305
+ process.stderr.write(`${helpText}\n`);
255
306
  process.exit(0);
256
307
  }
257
308
  }