@prisma-next/cli 0.3.0-dev.55 → 0.3.0-dev.63

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 (88) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +145 -6
  3. package/dist/cli-errors-JlPTsazx.mjs +3 -0
  4. package/dist/cli.mjs +29 -2
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{client-B7f4PZZ1.mjs → client-PimzSD1f.mjs} +155 -82
  7. package/dist/client-PimzSD1f.mjs.map +1 -0
  8. package/dist/commands/contract-emit.mjs +5 -3
  9. package/dist/commands/contract-emit.mjs.map +1 -1
  10. package/dist/commands/db-init.mjs +5 -4
  11. package/dist/commands/db-init.mjs.map +1 -1
  12. package/dist/commands/db-introspect.mjs +5 -3
  13. package/dist/commands/db-introspect.mjs.map +1 -1
  14. package/dist/commands/db-schema-verify.d.mts.map +1 -1
  15. package/dist/commands/db-schema-verify.mjs +6 -4
  16. package/dist/commands/db-schema-verify.mjs.map +1 -1
  17. package/dist/commands/db-sign.d.mts.map +1 -1
  18. package/dist/commands/db-sign.mjs +6 -4
  19. package/dist/commands/db-sign.mjs.map +1 -1
  20. package/dist/commands/db-update.mjs +5 -4
  21. package/dist/commands/db-update.mjs.map +1 -1
  22. package/dist/commands/db-verify.d.mts.map +1 -1
  23. package/dist/commands/db-verify.mjs +6 -4
  24. package/dist/commands/db-verify.mjs.map +1 -1
  25. package/dist/commands/migration-apply.d.mts +23 -0
  26. package/dist/commands/migration-apply.d.mts.map +1 -0
  27. package/dist/commands/migration-apply.mjs +249 -0
  28. package/dist/commands/migration-apply.mjs.map +1 -0
  29. package/dist/commands/migration-plan.d.mts +25 -0
  30. package/dist/commands/migration-plan.d.mts.map +1 -0
  31. package/dist/commands/migration-plan.mjs +266 -0
  32. package/dist/commands/migration-plan.mjs.map +1 -0
  33. package/dist/commands/migration-show.d.mts +28 -0
  34. package/dist/commands/migration-show.d.mts.map +1 -0
  35. package/dist/commands/migration-show.mjs +138 -0
  36. package/dist/commands/migration-show.mjs.map +1 -0
  37. package/dist/commands/migration-status.d.mts +35 -0
  38. package/dist/commands/migration-status.d.mts.map +1 -0
  39. package/dist/commands/migration-status.mjs +259 -0
  40. package/dist/commands/migration-status.mjs.map +1 -0
  41. package/dist/commands/migration-verify.d.mts +16 -0
  42. package/dist/commands/migration-verify.d.mts.map +1 -0
  43. package/dist/commands/migration-verify.mjs +86 -0
  44. package/dist/commands/migration-verify.mjs.map +1 -0
  45. package/dist/{config-loader-DqKf1qSa.mjs → config-loader-PPf4CtDj.mjs} +4 -3
  46. package/dist/config-loader-PPf4CtDj.mjs.map +1 -0
  47. package/dist/config-loader.d.mts +1 -1
  48. package/dist/config-loader.d.mts.map +1 -1
  49. package/dist/config-loader.mjs +1 -1
  50. package/dist/exports/config-types.d.mts +1 -1
  51. package/dist/exports/config-types.mjs +1 -1
  52. package/dist/exports/control-api.d.mts +100 -2
  53. package/dist/exports/control-api.d.mts.map +1 -1
  54. package/dist/exports/control-api.mjs +3 -2
  55. package/dist/exports/control-api.mjs.map +1 -1
  56. package/dist/exports/index.mjs +1 -1
  57. package/dist/extract-sql-ddl-BmlKvk4o.mjs +26 -0
  58. package/dist/extract-sql-ddl-BmlKvk4o.mjs.map +1 -0
  59. package/dist/framework-components-CjV_jD8f.mjs +59 -0
  60. package/dist/framework-components-CjV_jD8f.mjs.map +1 -0
  61. package/dist/{migration-command-scaffold-BELw_do2.mjs → migration-command-scaffold-DfY_F3ev.mjs} +7 -5
  62. package/dist/migration-command-scaffold-DfY_F3ev.mjs.map +1 -0
  63. package/dist/progress-adapter-DENrzF6I.mjs +49 -0
  64. package/dist/progress-adapter-DENrzF6I.mjs.map +1 -0
  65. package/dist/{result-handler-BhmrXIvT.mjs → result-handler-iA9JtUC7.mjs} +158 -51
  66. package/dist/result-handler-iA9JtUC7.mjs.map +1 -0
  67. package/package.json +34 -12
  68. package/src/cli.ts +38 -0
  69. package/src/commands/db-schema-verify.ts +6 -4
  70. package/src/commands/db-sign.ts +6 -4
  71. package/src/commands/db-verify.ts +6 -4
  72. package/src/commands/migration-apply.ts +431 -0
  73. package/src/commands/migration-plan.ts +446 -0
  74. package/src/commands/migration-show.ts +255 -0
  75. package/src/commands/migration-status.ts +436 -0
  76. package/src/commands/migration-verify.ts +151 -0
  77. package/src/config-loader.ts +13 -3
  78. package/src/control-api/client.ts +31 -0
  79. package/src/control-api/operations/migration-apply.ts +195 -0
  80. package/src/control-api/types.ts +113 -1
  81. package/src/exports/config-types.ts +3 -3
  82. package/src/utils/command-helpers.ts +11 -0
  83. package/src/utils/migration-command-scaffold.ts +7 -6
  84. package/src/utils/output.ts +305 -3
  85. package/dist/client-B7f4PZZ1.mjs.map +0 -1
  86. package/dist/config-loader-DqKf1qSa.mjs.map +0 -1
  87. package/dist/migration-command-scaffold-BELw_do2.mjs.map +0 -1
  88. package/dist/result-handler-BhmrXIvT.mjs.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [2026] [Prisma Data, Inc]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md CHANGED
@@ -32,7 +32,6 @@ This prevents runtime mismatches (for example: a contract that declares extensio
32
32
 
33
33
  Commands that enforce wiring validation:
34
34
  - **`db verify`**
35
- - **`db introspect`** (when a contract is provided)
36
35
  - **`db sign`**
37
36
  - **`db init`**
38
37
  - **`db update`**
@@ -838,21 +837,150 @@ The `contract.output` field specifies the path to `contract.json`. This is the c
838
837
  - `contract.json`: Includes `_generated` metadata field indicating it's a generated artifact (excluded from canonicalization/hashing)
839
838
  - `contract.d.ts`: Includes warning header comments indicating it's a generated file
840
839
 
840
+ ### `prisma-next migration plan`
841
+
842
+ Plan a migration from contract changes. Compares the emitted contract against the latest on-disk migration state and produces a new migration package with the required operations. No database connection is needed — fully offline.
843
+
844
+ ```bash
845
+ prisma-next migration plan [--config <path>] [--name <slug>] [--from <hash>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
846
+ ```
847
+
848
+ **Options:**
849
+ - `--config <path>`: Path to `prisma-next.config.ts`
850
+ - `--name <slug>`: Name slug for the migration directory (default: `migration`)
851
+ - `--from <hash>`: Explicit starting contract hash (overrides latest chain leaf detection)
852
+ - `--json`: Output as JSON object
853
+ - `-q, --quiet`: Quiet mode (errors only)
854
+ - `-v, --verbose`: Verbose output (debug info, timings)
855
+ - `--timestamps`: Add timestamps to output
856
+
857
+ **What it does:**
858
+ 1. Loads config and reads `contract.json` (the "to" contract)
859
+ 2. Reads existing migrations from `config.migrations.dir` (default: `migrations/`)
860
+ 3. Reconstructs the migration chain and finds the leaf (current state)
861
+ 4. Diffs the leaf contract against the new contract using the target's migration planner (same planner as `db init`)
862
+ 5. Writes a new migration package (`migration.json` + `ops.json`) and attests the `migrationId`
863
+
864
+ ### `prisma-next migration show`
865
+
866
+ Display a migration package's operations, DDL preview, and metadata. Accepts a directory path, a hash prefix (git-style matching against `migrationId`), or defaults to the latest migration.
867
+
868
+ ```bash
869
+ prisma-next migration show [target] [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
870
+ ```
871
+
872
+ **Options:**
873
+ - `[target]`: Migration directory path or migrationId hash prefix (defaults to latest)
874
+ - `--config <path>`: Path to `prisma-next.config.ts`
875
+ - `--json`: Output as JSON object
876
+ - `-q, --quiet`: Quiet mode (errors only)
877
+ - `-v, --verbose`: Verbose output
878
+ - `--timestamps`: Add timestamps to output
879
+
880
+ **What it does:**
881
+ 1. If `target` is a path (contains `/` or `\`), reads that directory directly
882
+ 2. If `target` is a hash prefix, scans all attested migrations and matches against `migrationId`
883
+ 3. If no target, defaults to the latest migration (chain leaf)
884
+ 4. Displays operations with operation class badges, destructive warnings, and DDL preview
885
+
886
+ **Destructive warnings:** When a migration contains destructive operations (e.g., `DROP TABLE`, `ALTER COLUMN TYPE`), the output includes a prominent `⚠` warning about potential data loss.
887
+
888
+ ### `prisma-next migration status`
889
+
890
+ Show the migration graph and applied status. Adapts based on context:
891
+
892
+ - **With DB connection**: Shows applied/pending markers and "you are here" indicators
893
+ - **Without DB connection**: Shows the graph structure from disk only
894
+
895
+ ```bash
896
+ prisma-next migration status [--db <url>] [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
897
+ ```
898
+
899
+ **Options:**
900
+ - `--db <url>`: Database connection string (enables online mode)
901
+ - `--config <path>`: Path to `prisma-next.config.ts`
902
+ - `--json`: Output as JSON object
903
+ - `-q, --quiet`: Quiet mode (errors only)
904
+ - `-v, --verbose`: Verbose output
905
+ - `--timestamps`: Add timestamps to output
906
+
907
+ **What it does:**
908
+ 1. Reads migration packages from disk and reconstructs the chain
909
+ 2. If a DB connection is available, reads the marker to determine applied/pending status
910
+ 3. Displays the graph as a linear chain with `◄ DB` and `◄ Contract` markers
911
+ 4. Shows operation summaries with destructive operation highlighting
912
+ 5. Falls back to offline mode if DB connection fails
913
+
914
+ **Known limitation:** Branched migration graphs (multiple leaves) produce an error. Only linear chains are visualized.
915
+
916
+ ### `prisma-next migration apply`
917
+
918
+ Apply planned migrations to the database. Executes previously planned migrations (created by `migration plan`). Compares the database marker against the migration chain to determine which migrations are pending, then executes them sequentially. Each migration runs in its own transaction. Does not plan new migrations — run `migration plan` first.
919
+
920
+ ```bash
921
+ prisma-next migration apply [--db <url>] [--config <path>] [--json] [-v] [-q] [--timestamps] [--color/--no-color]
922
+ ```
923
+
924
+ **Options:**
925
+ - `--db <url>`: Database connection string (optional; defaults to `config.db.connection`)
926
+ - `--config <path>`: Path to `prisma-next.config.ts`
927
+ - `--json`: Output as JSON object
928
+ - `-q, --quiet`: Quiet mode (errors only)
929
+ - `-v, --verbose`: Verbose output (debug info, timings)
930
+ - `--timestamps`: Add timestamps to output
931
+
932
+ **What it does:**
933
+ 1. Reads attested migration packages from `config.migrations.dir`
934
+ 2. Reconstructs the migration chain (skips drafts with `migrationId: null`)
935
+ 3. Reads the current contract hash from `contract.json`
936
+ 4. Connects to the database and reads the current marker hash
937
+ 5. Finds the path from the marker hash to the current contract hash
938
+ 6. Executes each pending migration in order using the target's `MigrationRunner`
939
+ 7. Each migration runs in its own transaction with prechecks, postchecks, and idempotency checks enabled
940
+ 8. After each migration, the runner verifies the schema and updates the marker/ledger
941
+
942
+ **Config requirements:** Requires `driver` and `db.connection` (or `--db`). `migrations.dir` is optional and defaults to `migrations/`.
943
+
944
+ **Resume semantics:** If a migration fails, previously applied migrations are preserved. Re-running `migration apply` resumes from the last successful migration.
945
+
946
+ **Planning requirement:** `migration apply` now requires the current contract hash to exist in attested on-disk migrations. If the contract has changed and no migration was planned, apply exits with an error and asks you to run `migration plan`.
947
+
948
+ ### `prisma-next migration verify`
949
+
950
+ Verify a migration package's integrity by recomputing the content-addressed `migrationId`.
951
+
952
+ ```bash
953
+ prisma-next migration verify --dir <path>
954
+ ```
955
+
956
+ - **Verified**: stored `migrationId` matches recomputed value
957
+ - **Draft**: `migrationId` is null — automatically attests the package
958
+ - **Mismatch**: package has been modified since attestation (command exits non-zero)
959
+
841
960
  ## Architecture
842
961
 
843
962
  ```mermaid
844
963
  flowchart TD
845
964
  CLI[CLI Entry Point]
846
- CMD[Emit Command]
965
+ CMD_EMIT[Emit Command]
966
+ CMD_DB[DB Commands]
967
+ CMD_MIG[Migration Commands]
847
968
  LOAD[TS Contract Loader]
848
969
  EMIT[Emitter]
970
+ CTRL[Control Client]
971
+ MIG_TOOLS["@prisma-next/migration-tools"]
849
972
  FS[File System]
850
973
 
851
- CLI --> CMD
852
- CMD --> LOAD
974
+ CLI --> CMD_EMIT
975
+ CLI --> CMD_DB
976
+ CLI --> CMD_MIG
977
+ CMD_EMIT --> LOAD
853
978
  LOAD --> EMIT
854
- EMIT --> CMD
855
- CMD --> FS
979
+ CMD_DB --> CTRL
980
+ CMD_MIG --> CTRL
981
+ CMD_MIG --> MIG_TOOLS
982
+ MIG_TOOLS --> FS
983
+ CTRL --> FS
856
984
  ```
857
985
 
858
986
  ## Config Validation and Normalization
@@ -1010,6 +1138,8 @@ export default defineConfig({
1010
1138
  - **`commander`**: CLI argument parsing and command routing
1011
1139
  - **`esbuild`**: Bundling TypeScript contract files with import allowlisting
1012
1140
  - **`@prisma-next/emitter`**: Contract emission engine (returns strings)
1141
+ - **`@prisma-next/migration-tools`**: On-disk migration I/O, attestation, and chain reconstruction
1142
+ - **`@prisma-next/core-control-plane`**: Config types, migration operation types, error types, control plane stack
1013
1143
 
1014
1144
  ## Design Decisions
1015
1145
 
@@ -1117,22 +1247,26 @@ try {
1117
1247
  |--------|-------------|
1118
1248
  | `connect(url)` | Establishes database connection |
1119
1249
  | `close()` | Closes connection (idempotent) |
1250
+ | `readMarker()` | Reads contract marker from database (null if none) |
1120
1251
  | `verify(options)` | Verifies database marker matches contract |
1121
1252
  | `schemaVerify(options)` | Verifies database schema satisfies contract |
1122
1253
  | `sign(options)` | Writes contract marker to database |
1123
1254
  | `dbInit(options)` | Initializes database schema from contract |
1124
1255
  | `dbUpdate(options)` | Updates database schema to match contract |
1256
+ | `migrationApply(options)` | Applies pre-planned migration edges to database |
1125
1257
  | `introspect(options)` | Introspects database schema |
1126
1258
 
1127
1259
  ### Result Types
1128
1260
 
1129
1261
  Operations return structured result types:
1130
1262
 
1263
+ - `readMarker()` → `ContractMarkerRecord | null`
1131
1264
  - `verify()` → `VerifyDatabaseResult`
1132
1265
  - `schemaVerify()` → `VerifyDatabaseSchemaResult`
1133
1266
  - `sign()` → `SignDatabaseResult`
1134
1267
  - `dbInit()` → `Result<DbInitSuccess, DbInitFailure>` (uses Result pattern)
1135
1268
  - `dbUpdate()` → `Result<DbUpdateSuccess, DbUpdateFailure>` (uses Result pattern)
1269
+ - `migrationApply()` → `Result<MigrationApplySuccess, MigrationApplyFailure>` (uses Result pattern)
1136
1270
  - `introspect()` → Schema IR (family-specific)
1137
1271
 
1138
1272
  ### Error Handling
@@ -1165,6 +1299,11 @@ The CLI package exports several subpaths for different use cases:
1165
1299
  - **`@prisma-next/cli/commands/db-sign`**: Exports `createDbSignCommand`
1166
1300
  - **`@prisma-next/cli/commands/db-verify`**: Exports `createDbVerifyCommand`
1167
1301
  - **`@prisma-next/cli/commands/contract-emit`**: Exports `createContractEmitCommand`
1302
+ - **`@prisma-next/cli/commands/migration-plan`**: Exports `createMigrationPlanCommand`
1303
+ - **`@prisma-next/cli/commands/migration-show`**: Exports `createMigrationShowCommand`
1304
+ - **`@prisma-next/cli/commands/migration-status`**: Exports `createMigrationStatusCommand`
1305
+ - **`@prisma-next/cli/commands/migration-apply`**: Exports `createMigrationApplyCommand`
1306
+ - **`@prisma-next/cli/commands/migration-verify`**: Exports `createMigrationVerifyCommand`
1168
1307
  - **`@prisma-next/cli/config-loader`**: Exports `loadConfig` function
1169
1308
 
1170
1309
  **Important**: `loadContractFromTs` is exported from the main package (`@prisma-next/cli`). See `.cursor/rules/cli-package-exports.mdc` for import patterns.
@@ -0,0 +1,3 @@
1
+ import { CliStructuredError, errorConfigValidation as errorConfigValidation$1, errorContractConfigMissing as errorContractConfigMissing$1, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDestructiveChanges, errorDriverRequired, errorFileNotFound, errorHashMismatch, errorJsonFormatNotSupported, errorMarkerMissing, errorMigrationPlanningFailed, errorRunnerFailed, errorRuntime, errorTargetMigrationNotSupported, errorTargetMismatch, errorUnexpected as errorUnexpected$1 } from "@prisma-next/core-control-plane/errors";
2
+
3
+ export { errorUnexpected$1 as _, errorDatabaseConnectionRequired as a, errorFileNotFound as c, errorMarkerMissing as d, errorMigrationPlanningFailed as f, errorTargetMismatch as g, errorTargetMigrationNotSupported as h, errorContractValidationFailed as i, errorHashMismatch as l, errorRuntime as m, errorConfigValidation$1 as n, errorDestructiveChanges as o, errorRunnerFailed as p, errorContractConfigMissing$1 as r, errorDriverRequired as s, CliStructuredError as t, errorJsonFormatNotSupported as u };
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import "./config-loader-DqKf1qSa.mjs";
4
- import { C as setCommandDescriptions, b as parseGlobalFlags, d as formatRootHelp, r as formatCommandHelp } from "./result-handler-BhmrXIvT.mjs";
3
+ import "./config-loader-PPf4CtDj.mjs";
4
+ import { C as parseGlobalFlags, D as setCommandDescriptions, m as formatRootHelp, n as formatCommandHelp } from "./result-handler-iA9JtUC7.mjs";
5
5
  import { createContractEmitCommand } from "./commands/contract-emit.mjs";
6
6
  import { createDbInitCommand } from "./commands/db-init.mjs";
7
7
  import { createDbIntrospectCommand } from "./commands/db-introspect.mjs";
@@ -9,6 +9,11 @@ import { createDbSchemaVerifyCommand } from "./commands/db-schema-verify.mjs";
9
9
  import { createDbSignCommand } from "./commands/db-sign.mjs";
10
10
  import { createDbUpdateCommand } from "./commands/db-update.mjs";
11
11
  import { createDbVerifyCommand } from "./commands/db-verify.mjs";
12
+ import { createMigrationApplyCommand } from "./commands/migration-apply.mjs";
13
+ import { createMigrationPlanCommand } from "./commands/migration-plan.mjs";
14
+ import { createMigrationShowCommand } from "./commands/migration-show.mjs";
15
+ import { createMigrationStatusCommand } from "./commands/migration-status.mjs";
16
+ import { createMigrationVerifyCommand } from "./commands/migration-verify.mjs";
12
17
  import { Command } from "commander";
13
18
 
14
19
  //#region src/cli.ts
@@ -113,6 +118,28 @@ dbCommand.addCommand(dbSchemaVerifyCommand);
113
118
  const dbSignCommand = createDbSignCommand();
114
119
  dbCommand.addCommand(dbSignCommand);
115
120
  program.addCommand(dbCommand);
121
+ const migrationCommand = new Command("migration");
122
+ setCommandDescriptions(migrationCommand, "On-disk migration management commands", "Plan, apply, verify, and scaffold on-disk migration packages. Migrations are\ncontract-to-contract edges stored as versioned directories under migrations/.");
123
+ migrationCommand.configureHelp({
124
+ formatHelp: (cmd) => {
125
+ return formatCommandHelp({
126
+ command: cmd,
127
+ flags: parseGlobalFlags({})
128
+ });
129
+ },
130
+ subcommandDescription: () => ""
131
+ });
132
+ const migrationPlanCommand = createMigrationPlanCommand();
133
+ migrationCommand.addCommand(migrationPlanCommand);
134
+ const migrationShowCommand = createMigrationShowCommand();
135
+ migrationCommand.addCommand(migrationShowCommand);
136
+ const migrationStatusCommand = createMigrationStatusCommand();
137
+ migrationCommand.addCommand(migrationStatusCommand);
138
+ const migrationVerifyCommand = createMigrationVerifyCommand();
139
+ migrationCommand.addCommand(migrationVerifyCommand);
140
+ const migrationApplyCommand = createMigrationApplyCommand();
141
+ migrationCommand.addCommand(migrationApplyCommand);
142
+ program.addCommand(migrationCommand);
116
143
  const helpCommand = new Command("help").description("Show usage instructions").configureHelp({ formatHelp: (cmd) => {
117
144
  return formatCommandHelp({
118
145
  command: cmd,
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createContractEmitCommand } from './commands/contract-emit';\nimport { createDbInitCommand } from './commands/db-init';\nimport { createDbIntrospectCommand } from './commands/db-introspect';\nimport { createDbSchemaVerifyCommand } from './commands/db-schema-verify';\nimport { createDbSignCommand } from './commands/db-sign';\nimport { createDbUpdateCommand } from './commands/db-update';\nimport { createDbVerifyCommand } from './commands/db-verify';\nimport { setCommandDescriptions } from './utils/command-helpers';\nimport { parseGlobalFlags } from './utils/global-flags';\nimport { formatCommandHelp, formatRootHelp } from './utils/output';\n\nconst program = new Command();\n\nprogram.name('prisma-next').description('Prisma Next CLI').version('0.0.1');\n\n// Override version option description to match capitalization style\nconst versionOption = program.options.find((opt) => opt.flags.includes('--version'));\nif (versionOption) {\n versionOption.description = 'Output the version number';\n}\n\nprogram.configureOutput({\n writeErr: () => {\n // Suppress all default error output - we handle errors in exitOverride\n },\n writeOut: () => {\n // Suppress all default output - our custom formatters handle everything\n },\n});\n\n// Customize root help output to use our styled format\nconst rootHelpFormatter = (cmd: Command) => {\n const flags = parseGlobalFlags({});\n return formatRootHelp({ program: cmd, flags });\n};\n\nprogram.configureHelp({\n formatHelp: rootHelpFormatter,\n subcommandDescription: () => '',\n});\n\n// Override exit to handle unhandled errors (fail fast cases)\n// Commands handle structured errors themselves via process.exit()\nprogram.exitOverride((err) => {\n if (err) {\n // Help requests are not errors - allow Commander to output help and exit normally\n // Commander throws errors with codes like 'commander.help', 'commander.helpDisplayed', or 'outputHelp'\n const errorCode = (err as { code?: string }).code;\n const errorMessage = String(err.message ?? '');\n const errorName = err.name ?? '';\n\n // Check for unknown command errors first (before other checks)\n // Commander.js uses code 'commander.unknownCommand' or error message contains 'unknown command'\n const isUnknownCommandError =\n errorCode === 'commander.unknownCommand' ||\n errorCode === 'commander.unknownArgument' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));\n if (isUnknownCommandError) {\n const flags = parseGlobalFlags({});\n // Extract the command/subcommand name from the error message\n // Error message format: \"unknown command 'command-name'\"\n const match = errorMessage.match(/unknown command ['\"]([^'\"]+)['\"]/);\n const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';\n\n // Determine which command context we're in\n // Check if the first argument is a recognized parent command\n const firstArg = process.argv[2];\n const parentCommand = firstArg\n ? program.commands.find((cmd) => cmd.name() === firstArg)\n : undefined;\n\n if (parentCommand && commandName !== firstArg) {\n // Unrecognized subcommand - show parent command help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatCommandHelp({ command: parentCommand, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n } else {\n // Unrecognized top-level command - show root help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n }\n process.exit(1);\n return;\n }\n const isHelpError =\n errorCode === 'commander.help' ||\n errorCode === 'commander.helpDisplayed' ||\n errorCode === 'outputHelp' ||\n errorMessage === '(outputHelp)' ||\n errorMessage.includes('outputHelp') ||\n (errorName === 'CommanderError' && errorMessage.includes('outputHelp'));\n if (isHelpError) {\n process.exit(0);\n return;\n }\n // Missing required arguments/subcommands - show help and exit with 0\n // Commander throws errors with code 'commander.missingArgument' or 'commander.missingMandatoryOptionValue'\n // or when a command with subcommands is called without a subcommand\n const isMissingArgumentError =\n errorCode === 'commander.missingArgument' ||\n errorCode === 'commander.missingMandatoryOptionValue' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('missing') || errorMessage.includes('required')));\n if (isMissingArgumentError) {\n // Help was already displayed by Commander.js, just exit with 0\n process.exit(0);\n return;\n }\n // Unhandled error - fail fast with exit code 1\n // eslint-disable-next-line no-console\n console.error(`Unhandled error: ${err.message}`);\n if (err.stack) {\n // eslint-disable-next-line no-console\n console.error(err.stack);\n }\n process.exit(1);\n }\n process.exit(0);\n});\n\n// Register contract subcommand\nconst contractCommand = new Command('contract');\nsetCommandDescriptions(\n contractCommand,\n 'Contract management commands',\n 'Define and emit your application data contract. The contract describes your schema as a\\n' +\n 'declarative data structure that can be signed and verified against your database.',\n);\ncontractCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add emit subcommand to contract\nconst contractEmitCommand = createContractEmitCommand();\ncontractCommand.addCommand(contractEmitCommand);\n\n// Register contract command\nprogram.addCommand(contractCommand);\n\n// Register db subcommand\nconst dbCommand = new Command('db');\nsetCommandDescriptions(\n dbCommand,\n 'Database management commands',\n 'Verify and sign your database with your contract. Ensure your database schema matches\\n' +\n 'your contract, and sign it to record the contract hash for future verification.',\n);\ndbCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add verify subcommand to db\nconst dbVerifyCommand = createDbVerifyCommand();\ndbCommand.addCommand(dbVerifyCommand);\n\n// Add init subcommand to db\nconst dbInitCommand = createDbInitCommand();\ndbCommand.addCommand(dbInitCommand);\n\n// Add update subcommand to db\nconst dbUpdateCommand = createDbUpdateCommand();\ndbCommand.addCommand(dbUpdateCommand);\n\n// Add introspect subcommand to db\nconst dbIntrospectCommand = createDbIntrospectCommand();\ndbCommand.addCommand(dbIntrospectCommand);\n\n// Add schema-verify subcommand to db\nconst dbSchemaVerifyCommand = createDbSchemaVerifyCommand();\ndbCommand.addCommand(dbSchemaVerifyCommand);\n\n// Add sign subcommand to db\nconst dbSignCommand = createDbSignCommand();\ndbCommand.addCommand(dbSignCommand);\n\n// Register db command\nprogram.addCommand(dbCommand);\n\n// Create help command\nconst helpCommand = new Command('help')\n .description('Show usage instructions')\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n });\n\nprogram.addCommand(helpCommand);\n\n// Set help as the default action when no command is provided\nprogram.action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n});\n\n// Check if a command was invoked with no arguments (just the command name)\n// or if an unrecognized command was provided\nconst args = process.argv.slice(2);\nif (args.length > 0) {\n const commandName = args[0];\n // Handle version option explicitly since we suppress default output\n if (commandName === '--version' || commandName === '-V') {\n // eslint-disable-next-line no-console\n console.log(program.version());\n process.exit(0);\n }\n // Skip command check for global options like --help, -h\n const isGlobalOption = commandName === '--help' || commandName === '-h';\n if (!isGlobalOption) {\n // Check if this is a recognized command\n const command = program.commands.find((cmd) => cmd.name() === commandName);\n\n if (!command) {\n // Unrecognized command - show error message and usage\n const flags = parseGlobalFlags({});\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(1);\n } else if (command.commands.length > 0 && args.length === 1) {\n // Parent command called with no subcommand - show help and exit with 0\n const flags = parseGlobalFlags({});\n const helpText = formatCommandHelp({ command, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n }\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createContractEmitCommand } from './commands/contract-emit';\nimport { createDbInitCommand } from './commands/db-init';\nimport { createDbIntrospectCommand } from './commands/db-introspect';\nimport { createDbSchemaVerifyCommand } from './commands/db-schema-verify';\nimport { createDbSignCommand } from './commands/db-sign';\nimport { createDbUpdateCommand } from './commands/db-update';\nimport { createDbVerifyCommand } from './commands/db-verify';\nimport { createMigrationApplyCommand } from './commands/migration-apply';\nimport { createMigrationPlanCommand } from './commands/migration-plan';\nimport { createMigrationShowCommand } from './commands/migration-show';\nimport { createMigrationStatusCommand } from './commands/migration-status';\nimport { createMigrationVerifyCommand } from './commands/migration-verify';\nimport { setCommandDescriptions } from './utils/command-helpers';\nimport { parseGlobalFlags } from './utils/global-flags';\nimport { formatCommandHelp, formatRootHelp } from './utils/output';\n\nconst program = new Command();\n\nprogram.name('prisma-next').description('Prisma Next CLI').version('0.0.1');\n\n// Override version option description to match capitalization style\nconst versionOption = program.options.find((opt) => opt.flags.includes('--version'));\nif (versionOption) {\n versionOption.description = 'Output the version number';\n}\n\nprogram.configureOutput({\n writeErr: () => {\n // Suppress all default error output - we handle errors in exitOverride\n },\n writeOut: () => {\n // Suppress all default output - our custom formatters handle everything\n },\n});\n\n// Customize root help output to use our styled format\nconst rootHelpFormatter = (cmd: Command) => {\n const flags = parseGlobalFlags({});\n return formatRootHelp({ program: cmd, flags });\n};\n\nprogram.configureHelp({\n formatHelp: rootHelpFormatter,\n subcommandDescription: () => '',\n});\n\n// Override exit to handle unhandled errors (fail fast cases)\n// Commands handle structured errors themselves via process.exit()\nprogram.exitOverride((err) => {\n if (err) {\n // Help requests are not errors - allow Commander to output help and exit normally\n // Commander throws errors with codes like 'commander.help', 'commander.helpDisplayed', or 'outputHelp'\n const errorCode = (err as { code?: string }).code;\n const errorMessage = String(err.message ?? '');\n const errorName = err.name ?? '';\n\n // Check for unknown command errors first (before other checks)\n // Commander.js uses code 'commander.unknownCommand' or error message contains 'unknown command'\n const isUnknownCommandError =\n errorCode === 'commander.unknownCommand' ||\n errorCode === 'commander.unknownArgument' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('unknown command') || errorMessage.includes('unknown argument')));\n if (isUnknownCommandError) {\n const flags = parseGlobalFlags({});\n // Extract the command/subcommand name from the error message\n // Error message format: \"unknown command 'command-name'\"\n const match = errorMessage.match(/unknown command ['\"]([^'\"]+)['\"]/);\n const commandName = match ? match[1] : process.argv[3] || process.argv[2] || 'unknown';\n\n // Determine which command context we're in\n // Check if the first argument is a recognized parent command\n const firstArg = process.argv[2];\n const parentCommand = firstArg\n ? program.commands.find((cmd) => cmd.name() === firstArg)\n : undefined;\n\n if (parentCommand && commandName !== firstArg) {\n // Unrecognized subcommand - show parent command help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatCommandHelp({ command: parentCommand, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n } else {\n // Unrecognized top-level command - show root help\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n }\n process.exit(1);\n return;\n }\n const isHelpError =\n errorCode === 'commander.help' ||\n errorCode === 'commander.helpDisplayed' ||\n errorCode === 'outputHelp' ||\n errorMessage === '(outputHelp)' ||\n errorMessage.includes('outputHelp') ||\n (errorName === 'CommanderError' && errorMessage.includes('outputHelp'));\n if (isHelpError) {\n process.exit(0);\n return;\n }\n // Missing required arguments/subcommands - show help and exit with 0\n // Commander throws errors with code 'commander.missingArgument' or 'commander.missingMandatoryOptionValue'\n // or when a command with subcommands is called without a subcommand\n const isMissingArgumentError =\n errorCode === 'commander.missingArgument' ||\n errorCode === 'commander.missingMandatoryOptionValue' ||\n (errorName === 'CommanderError' &&\n (errorMessage.includes('missing') || errorMessage.includes('required')));\n if (isMissingArgumentError) {\n // Help was already displayed by Commander.js, just exit with 0\n process.exit(0);\n return;\n }\n // Unhandled error - fail fast with exit code 1\n // eslint-disable-next-line no-console\n console.error(`Unhandled error: ${err.message}`);\n if (err.stack) {\n // eslint-disable-next-line no-console\n console.error(err.stack);\n }\n process.exit(1);\n }\n process.exit(0);\n});\n\n// Register contract subcommand\nconst contractCommand = new Command('contract');\nsetCommandDescriptions(\n contractCommand,\n 'Contract management commands',\n 'Define and emit your application data contract. The contract describes your schema as a\\n' +\n 'declarative data structure that can be signed and verified against your database.',\n);\ncontractCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add emit subcommand to contract\nconst contractEmitCommand = createContractEmitCommand();\ncontractCommand.addCommand(contractEmitCommand);\n\n// Register contract command\nprogram.addCommand(contractCommand);\n\n// Register db subcommand\nconst dbCommand = new Command('db');\nsetCommandDescriptions(\n dbCommand,\n 'Database management commands',\n 'Verify and sign your database with your contract. Ensure your database schema matches\\n' +\n 'your contract, and sign it to record the contract hash for future verification.',\n);\ndbCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\n// Add verify subcommand to db\nconst dbVerifyCommand = createDbVerifyCommand();\ndbCommand.addCommand(dbVerifyCommand);\n\n// Add init subcommand to db\nconst dbInitCommand = createDbInitCommand();\ndbCommand.addCommand(dbInitCommand);\n\n// Add update subcommand to db\nconst dbUpdateCommand = createDbUpdateCommand();\ndbCommand.addCommand(dbUpdateCommand);\n\n// Add introspect subcommand to db\nconst dbIntrospectCommand = createDbIntrospectCommand();\ndbCommand.addCommand(dbIntrospectCommand);\n\n// Add schema-verify subcommand to db\nconst dbSchemaVerifyCommand = createDbSchemaVerifyCommand();\ndbCommand.addCommand(dbSchemaVerifyCommand);\n\n// Add sign subcommand to db\nconst dbSignCommand = createDbSignCommand();\ndbCommand.addCommand(dbSignCommand);\n\n// Register db command\nprogram.addCommand(dbCommand);\n\n// Register migration subcommand\nconst migrationCommand = new Command('migration');\nsetCommandDescriptions(\n migrationCommand,\n 'On-disk migration management commands',\n 'Plan, apply, verify, and scaffold on-disk migration packages. Migrations are\\n' +\n 'contract-to-contract edges stored as versioned directories under migrations/.',\n);\nmigrationCommand.configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n subcommandDescription: () => '',\n});\n\nconst migrationPlanCommand = createMigrationPlanCommand();\nmigrationCommand.addCommand(migrationPlanCommand);\n\nconst migrationShowCommand = createMigrationShowCommand();\nmigrationCommand.addCommand(migrationShowCommand);\n\nconst migrationStatusCommand = createMigrationStatusCommand();\nmigrationCommand.addCommand(migrationStatusCommand);\n\nconst migrationVerifyCommand = createMigrationVerifyCommand();\nmigrationCommand.addCommand(migrationVerifyCommand);\n\nconst migrationApplyCommand = createMigrationApplyCommand();\nmigrationCommand.addCommand(migrationApplyCommand);\n\nprogram.addCommand(migrationCommand);\n\n// Create help command\nconst helpCommand = new Command('help')\n .description('Show usage instructions')\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n });\n\nprogram.addCommand(helpCommand);\n\n// Set help as the default action when no command is provided\nprogram.action(() => {\n const flags = parseGlobalFlags({});\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n});\n\n// Check if a command was invoked with no arguments (just the command name)\n// or if an unrecognized command was provided\nconst args = process.argv.slice(2);\nif (args.length > 0) {\n const commandName = args[0];\n // Handle version option explicitly since we suppress default output\n if (commandName === '--version' || commandName === '-V') {\n // eslint-disable-next-line no-console\n console.log(program.version());\n process.exit(0);\n }\n // Skip command check for global options like --help, -h\n const isGlobalOption = commandName === '--help' || commandName === '-h';\n if (!isGlobalOption) {\n // Check if this is a recognized command\n const command = program.commands.find((cmd) => cmd.name() === commandName);\n\n if (!command) {\n // Unrecognized command - show error message and usage\n const flags = parseGlobalFlags({});\n // eslint-disable-next-line no-console\n console.error(`Unknown command: ${commandName}`);\n // eslint-disable-next-line no-console\n console.error('');\n const helpText = formatRootHelp({ program, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(1);\n } else if (command.commands.length > 0 && args.length === 1) {\n // Parent command called with no subcommand - show help and exit with 0\n const flags = parseGlobalFlags({});\n const helpText = formatCommandHelp({ command, flags });\n // eslint-disable-next-line no-console\n console.log(helpText);\n process.exit(0);\n }\n }\n}\n\nprogram.parse();\n"],"mappings":"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"}