@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.
- package/LICENSE +201 -0
- package/README.md +145 -6
- package/dist/cli-errors-JlPTsazx.mjs +3 -0
- package/dist/cli.mjs +29 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-B7f4PZZ1.mjs → client-PimzSD1f.mjs} +155 -82
- package/dist/client-PimzSD1f.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +5 -3
- package/dist/commands/contract-emit.mjs.map +1 -1
- package/dist/commands/db-init.mjs +5 -4
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-introspect.mjs +5 -3
- package/dist/commands/db-introspect.mjs.map +1 -1
- package/dist/commands/db-schema-verify.d.mts.map +1 -1
- package/dist/commands/db-schema-verify.mjs +6 -4
- package/dist/commands/db-schema-verify.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +6 -4
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.mjs +5 -4
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +6 -4
- package/dist/commands/db-verify.mjs.map +1 -1
- package/dist/commands/migration-apply.d.mts +23 -0
- package/dist/commands/migration-apply.d.mts.map +1 -0
- package/dist/commands/migration-apply.mjs +249 -0
- package/dist/commands/migration-apply.mjs.map +1 -0
- package/dist/commands/migration-plan.d.mts +25 -0
- package/dist/commands/migration-plan.d.mts.map +1 -0
- package/dist/commands/migration-plan.mjs +266 -0
- package/dist/commands/migration-plan.mjs.map +1 -0
- package/dist/commands/migration-show.d.mts +28 -0
- package/dist/commands/migration-show.d.mts.map +1 -0
- package/dist/commands/migration-show.mjs +138 -0
- package/dist/commands/migration-show.mjs.map +1 -0
- package/dist/commands/migration-status.d.mts +35 -0
- package/dist/commands/migration-status.d.mts.map +1 -0
- package/dist/commands/migration-status.mjs +259 -0
- package/dist/commands/migration-status.mjs.map +1 -0
- package/dist/commands/migration-verify.d.mts +16 -0
- package/dist/commands/migration-verify.d.mts.map +1 -0
- package/dist/commands/migration-verify.mjs +86 -0
- package/dist/commands/migration-verify.mjs.map +1 -0
- package/dist/{config-loader-DqKf1qSa.mjs → config-loader-PPf4CtDj.mjs} +4 -3
- package/dist/config-loader-PPf4CtDj.mjs.map +1 -0
- package/dist/config-loader.d.mts +1 -1
- package/dist/config-loader.d.mts.map +1 -1
- package/dist/config-loader.mjs +1 -1
- package/dist/exports/config-types.d.mts +1 -1
- package/dist/exports/config-types.mjs +1 -1
- package/dist/exports/control-api.d.mts +100 -2
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -2
- package/dist/exports/control-api.mjs.map +1 -1
- package/dist/exports/index.mjs +1 -1
- package/dist/extract-sql-ddl-BmlKvk4o.mjs +26 -0
- package/dist/extract-sql-ddl-BmlKvk4o.mjs.map +1 -0
- package/dist/framework-components-CjV_jD8f.mjs +59 -0
- package/dist/framework-components-CjV_jD8f.mjs.map +1 -0
- package/dist/{migration-command-scaffold-BELw_do2.mjs → migration-command-scaffold-DfY_F3ev.mjs} +7 -5
- package/dist/migration-command-scaffold-DfY_F3ev.mjs.map +1 -0
- package/dist/progress-adapter-DENrzF6I.mjs +49 -0
- package/dist/progress-adapter-DENrzF6I.mjs.map +1 -0
- package/dist/{result-handler-BhmrXIvT.mjs → result-handler-iA9JtUC7.mjs} +158 -51
- package/dist/result-handler-iA9JtUC7.mjs.map +1 -0
- package/package.json +34 -12
- package/src/cli.ts +38 -0
- package/src/commands/db-schema-verify.ts +6 -4
- package/src/commands/db-sign.ts +6 -4
- package/src/commands/db-verify.ts +6 -4
- package/src/commands/migration-apply.ts +431 -0
- package/src/commands/migration-plan.ts +446 -0
- package/src/commands/migration-show.ts +255 -0
- package/src/commands/migration-status.ts +436 -0
- package/src/commands/migration-verify.ts +151 -0
- package/src/config-loader.ts +13 -3
- package/src/control-api/client.ts +31 -0
- package/src/control-api/operations/migration-apply.ts +195 -0
- package/src/control-api/types.ts +113 -1
- package/src/exports/config-types.ts +3 -3
- package/src/utils/command-helpers.ts +11 -0
- package/src/utils/migration-command-scaffold.ts +7 -6
- package/src/utils/output.ts +305 -3
- package/dist/client-B7f4PZZ1.mjs.map +0 -1
- package/dist/config-loader-DqKf1qSa.mjs.map +0 -1
- package/dist/migration-command-scaffold-BELw_do2.mjs.map +0 -1
- 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
|
-
|
|
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 -->
|
|
852
|
-
|
|
974
|
+
CLI --> CMD_EMIT
|
|
975
|
+
CLI --> CMD_DB
|
|
976
|
+
CLI --> CMD_MIG
|
|
977
|
+
CMD_EMIT --> LOAD
|
|
853
978
|
LOAD --> EMIT
|
|
854
|
-
|
|
855
|
-
|
|
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-
|
|
4
|
-
import { C as
|
|
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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"}
|