@prisma-next/cli 0.2.0 → 0.3.0-dev.10
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/README.md +83 -56
- package/dist/{chunk-C7QQMZ3I.js → chunk-CVNWLFXO.js} +6 -9
- package/dist/chunk-CVNWLFXO.js.map +1 -0
- package/dist/{chunk-464LNZCE.js → chunk-QUPBU4KV.js} +5 -8
- package/dist/chunk-QUPBU4KV.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +34 -60
- package/dist/cli.js.map +1 -1
- package/dist/commands/contract-emit.d.ts +2 -4
- package/dist/commands/contract-emit.d.ts.map +1 -0
- package/dist/commands/contract-emit.js +1 -1
- package/dist/commands/db-init.d.ts +2 -4
- package/dist/commands/db-init.d.ts.map +1 -0
- package/dist/commands/db-init.js +6 -10
- package/dist/commands/db-init.js.map +1 -1
- package/dist/commands/db-introspect.d.ts +2 -4
- package/dist/commands/db-introspect.d.ts.map +1 -0
- package/dist/commands/db-introspect.js +6 -10
- package/dist/commands/db-introspect.js.map +1 -1
- package/dist/commands/db-schema-verify.d.ts +2 -4
- package/dist/commands/db-schema-verify.d.ts.map +1 -0
- package/dist/commands/db-schema-verify.js +6 -10
- package/dist/commands/db-schema-verify.js.map +1 -1
- package/dist/commands/db-sign.d.ts +2 -4
- package/dist/commands/db-sign.d.ts.map +1 -0
- package/dist/commands/db-sign.js +6 -10
- package/dist/commands/db-sign.js.map +1 -1
- package/dist/commands/db-verify.d.ts +2 -4
- package/dist/commands/db-verify.d.ts.map +1 -0
- package/dist/commands/db-verify.js +6 -10
- package/dist/commands/db-verify.js.map +1 -1
- package/dist/config-loader.d.ts +3 -5
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/exports/config-types.d.ts +3 -0
- package/dist/exports/config-types.d.ts.map +1 -0
- package/dist/exports/config-types.js.map +1 -0
- package/dist/exports/index.d.ts +4 -0
- package/dist/exports/index.d.ts.map +1 -0
- package/dist/{index.js → exports/index.js} +3 -3
- package/dist/exports/index.js.map +1 -0
- package/dist/{index.d.ts → load-ts-contract.d.ts} +4 -8
- package/dist/load-ts-contract.d.ts.map +1 -0
- package/dist/utils/action.d.ts +16 -0
- package/dist/utils/action.d.ts.map +1 -0
- package/dist/utils/cli-errors.d.ts +7 -0
- package/dist/utils/cli-errors.d.ts.map +1 -0
- package/dist/utils/command-helpers.d.ts +12 -0
- package/dist/utils/command-helpers.d.ts.map +1 -0
- package/dist/utils/framework-components.d.ts +70 -0
- package/dist/utils/framework-components.d.ts.map +1 -0
- package/dist/utils/global-flags.d.ts +25 -0
- package/dist/utils/global-flags.d.ts.map +1 -0
- package/dist/utils/output.d.ts +142 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/result-handler.d.ts +15 -0
- package/dist/utils/result-handler.d.ts.map +1 -0
- package/dist/utils/spinner.d.ts +29 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/package.json +22 -22
- package/src/cli.ts +260 -0
- package/src/commands/contract-emit.ts +182 -0
- package/src/commands/db-init.ts +452 -0
- package/src/commands/db-introspect.ts +256 -0
- package/src/commands/db-schema-verify.ts +232 -0
- package/src/commands/db-sign.ts +273 -0
- package/src/commands/db-verify.ts +229 -0
- package/src/config-loader.ts +76 -0
- package/src/exports/config-types.ts +6 -0
- package/src/exports/index.ts +4 -0
- package/src/load-ts-contract.ts +217 -0
- package/src/utils/action.ts +43 -0
- package/src/utils/cli-errors.ts +26 -0
- package/src/utils/command-helpers.ts +26 -0
- package/src/utils/framework-components.ts +177 -0
- package/src/utils/global-flags.ts +75 -0
- package/src/utils/output.ts +1471 -0
- package/src/utils/result-handler.ts +44 -0
- package/src/utils/spinner.ts +67 -0
- package/dist/chunk-464LNZCE.js.map +0 -1
- package/dist/chunk-C7QQMZ3I.js.map +0 -1
- package/dist/config-types.d.ts +0 -1
- package/dist/config-types.js.map +0 -1
- package/dist/index.js.map +0 -1
- /package/dist/{config-types.js → exports/config-types.js} +0 -0
package/README.md
CHANGED
|
@@ -23,6 +23,20 @@ Provide a command-line interface that:
|
|
|
23
23
|
- **Help Output Formatting**: Custom styled help output with command trees and formatted descriptions
|
|
24
24
|
- **Config Management**: Load and validate `prisma-next.config.ts` files using Arktype validation
|
|
25
25
|
|
|
26
|
+
### Wiring validation
|
|
27
|
+
|
|
28
|
+
The CLI performs **wiring validation** at the composition boundary: it ensures the emitted contract artifacts are compatible with the descriptors wired in `prisma-next.config.ts`.
|
|
29
|
+
|
|
30
|
+
This prevents runtime mismatches (for example: a contract that declares extension packs, but a config that doesn’t provide the matching descriptors).
|
|
31
|
+
|
|
32
|
+
Commands that enforce wiring validation:
|
|
33
|
+
- **`db verify`**
|
|
34
|
+
- **`db introspect`** (when a contract is provided)
|
|
35
|
+
- **`db sign`**
|
|
36
|
+
- **`db init`**
|
|
37
|
+
|
|
38
|
+
If you hit a wiring validation error: add the required descriptors to `config.extensionPacks` (matched by descriptor `id`) and re-run the command.
|
|
39
|
+
|
|
26
40
|
**Note**: Control plane domain actions (database verification, contract emission) are implemented in `@prisma-next/core-control-plane`. The CLI uses the control plane domain actions programmatically but does not define control plane types itself.
|
|
27
41
|
|
|
28
42
|
## Command Descriptions
|
|
@@ -32,7 +46,7 @@ Commands use separate short and long descriptions via `setCommandDescriptions()`
|
|
|
32
46
|
- **Short description**: One-liner used in command trees and headers (e.g., "Emit signed contract artifacts")
|
|
33
47
|
- **Long description**: Multiline text shown at the bottom of help output with detailed context
|
|
34
48
|
|
|
35
|
-
See
|
|
49
|
+
See `src/utils/command-helpers.ts` for `setCommandDescriptions()` and `getLongDescription()`.
|
|
36
50
|
|
|
37
51
|
## Commands
|
|
38
52
|
|
|
@@ -102,7 +116,7 @@ prisma-next db verify [--db <url>] [--config <path>] [--json] [-v] [-q] [--times
|
|
|
102
116
|
```
|
|
103
117
|
|
|
104
118
|
Options:
|
|
105
|
-
- `--db <url>`: Database connection string (optional
|
|
119
|
+
- `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
|
|
106
120
|
- `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
|
|
107
121
|
- `--json`: Output as JSON object
|
|
108
122
|
- `-q, --quiet`: Quiet mode (errors only)
|
|
@@ -159,7 +173,7 @@ export default defineConfig({
|
|
|
159
173
|
|
|
160
174
|
1. **Load Contract**: Reads the emitted `contract.json` from `config.contract.output`
|
|
161
175
|
2. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
|
|
162
|
-
3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and extensions to create a family instance
|
|
176
|
+
3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`) to create a family instance
|
|
163
177
|
4. **Verify**: Calls `familyInstance.verify()` which:
|
|
164
178
|
- Reads the contract marker from the database
|
|
165
179
|
- Compares marker presence: Returns `PN-RTM-3001` if marker is missing
|
|
@@ -256,7 +270,7 @@ prisma-next db introspect [--db <url>] [--config <path>] [--json] [-v] [-q] [--t
|
|
|
256
270
|
```
|
|
257
271
|
|
|
258
272
|
Options:
|
|
259
|
-
- `--db <url>`: Database connection string (optional
|
|
273
|
+
- `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
|
|
260
274
|
- `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
|
|
261
275
|
- `--json`: Output as JSON object
|
|
262
276
|
- `-q, --quiet`: Quiet mode (errors only)
|
|
@@ -306,7 +320,7 @@ export default defineConfig({
|
|
|
306
320
|
**Introspection Process:**
|
|
307
321
|
|
|
308
322
|
1. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
|
|
309
|
-
2. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and extensions to create a family instance
|
|
323
|
+
2. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`) to create a family instance
|
|
310
324
|
3. **Introspect**: Calls `familyInstance.introspect()` which:
|
|
311
325
|
- Queries the database catalog to discover schema structure
|
|
312
326
|
- Returns a family-specific schema IR (e.g., `SqlSchemaIR` for SQL family)
|
|
@@ -373,7 +387,7 @@ sql schema (tables: 2)
|
|
|
373
387
|
|
|
374
388
|
**Error Codes:**
|
|
375
389
|
- `PN-CLI-4010`: Missing driver in config — provide a driver descriptor
|
|
376
|
-
- `PN-CLI-
|
|
390
|
+
- `PN-CLI-4005`: Missing database URL — provide `--db <url>` or set `db.url` in config
|
|
377
391
|
|
|
378
392
|
**Family Requirements:**
|
|
379
393
|
|
|
@@ -407,7 +421,7 @@ prisma-next db sign [--db <url>] [--config <path>] [--json] [-v] [-q] [--timesta
|
|
|
407
421
|
```
|
|
408
422
|
|
|
409
423
|
Options:
|
|
410
|
-
- `--db <url>`: Database connection string (optional
|
|
424
|
+
- `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
|
|
411
425
|
- `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
|
|
412
426
|
- `--json`: Output as JSON object
|
|
413
427
|
- `-q, --quiet`: Quiet mode (errors only)
|
|
@@ -464,7 +478,7 @@ export default defineConfig({
|
|
|
464
478
|
|
|
465
479
|
1. **Load Contract**: Reads the emitted `contract.json` from `config.contract.output`
|
|
466
480
|
2. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
|
|
467
|
-
3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and extensions to create a family instance
|
|
481
|
+
3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`) to create a family instance
|
|
468
482
|
4. **Schema Verification (Precondition)**: Calls `familyInstance.schemaVerify()` to verify the database schema matches the contract:
|
|
469
483
|
- If verification fails: Prints schema verification output and exits with code 1 (marker is not written)
|
|
470
484
|
- If verification passes: Proceeds to marker signing
|
|
@@ -570,7 +584,7 @@ For updated markers:
|
|
|
570
584
|
|
|
571
585
|
**Error Codes:**
|
|
572
586
|
- `PN-CLI-4010`: Missing driver in config — provide a driver descriptor
|
|
573
|
-
- `PN-CLI-
|
|
587
|
+
- `PN-CLI-4005`: Missing database URL — provide `--db <url>` or set `db.url` in config
|
|
574
588
|
- Exit code 1: Schema verification failed — database schema does not match contract (marker is not written)
|
|
575
589
|
|
|
576
590
|
**Relationship to Other Commands:**
|
|
@@ -609,7 +623,7 @@ The SQL family provides this via `@prisma-next/family-sql/control`. The `sign()`
|
|
|
609
623
|
|
|
610
624
|
### `prisma-next db init`
|
|
611
625
|
|
|
612
|
-
Initialize a database schema from the contract. This command
|
|
626
|
+
Initialize a database schema from the contract. This command plans and applies **additive-only** operations (create missing tables/columns/constraints/indexes) until the database satisfies the contract, then writes the contract marker.
|
|
613
627
|
|
|
614
628
|
**Command:**
|
|
615
629
|
```bash
|
|
@@ -617,10 +631,10 @@ prisma-next db init [--db <url>] [--config <path>] [--plan] [--json] [-v] [-q] [
|
|
|
617
631
|
```
|
|
618
632
|
|
|
619
633
|
Options:
|
|
620
|
-
- `--db <url>`: Database connection string (optional
|
|
634
|
+
- `--db <url>`: Database connection string (optional; defaults to `config.db.url` if set)
|
|
621
635
|
- `--config <path>`: Optional. Path to `prisma-next.config.ts` (defaults to `./prisma-next.config.ts` if present)
|
|
622
636
|
- `--plan`: Only show the migration plan, do not apply it
|
|
623
|
-
- `--json`: Output as JSON object
|
|
637
|
+
- `--json [format]`: Output as JSON (`object` only; `ndjson` is not supported for this command)
|
|
624
638
|
- `-q, --quiet`: Quiet mode (errors only)
|
|
625
639
|
- `-v, --verbose`: Verbose output (debug info, timings)
|
|
626
640
|
- `-vv, --trace`: Trace output (deep internals, stack traces)
|
|
@@ -675,51 +689,56 @@ export default defineConfig({
|
|
|
675
689
|
|
|
676
690
|
1. **Load Contract**: Reads the emitted `contract.json` from `config.contract.output`
|
|
677
691
|
2. **Connect to Database**: Uses `config.driver.create(url)` to create a driver
|
|
678
|
-
3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and extensions
|
|
692
|
+
3. **Create Family Instance**: Calls `config.family.create()` with target, adapter, driver, and `extensionPacks` (passed as `extensions`)
|
|
679
693
|
4. **Introspect Schema**: Calls `familyInstance.introspect()` to get the current database schema IR
|
|
680
|
-
5. **
|
|
681
|
-
|
|
694
|
+
5. **Validate wiring**: Ensures the contract is compatible with the CLI config:
|
|
695
|
+
- `contract.targetFamily` matches `config.family.familyId`
|
|
696
|
+
- `contract.target` matches `config.target.targetId`
|
|
697
|
+
- `contract.extensionPacks` (if present) are provided by `config.extensionPacks` (matched by descriptor `id`)
|
|
698
|
+
6. **Create Planner/Runner**: Uses `config.target.migrations.createPlanner()` and `config.target.migrations.createRunner()`
|
|
699
|
+
7. **Plan Migration**: Calls `planner.plan()` with the contract IR, schema IR, additive-only policy, and `frameworkComponents` (the active target/adapter/extension descriptors)
|
|
682
700
|
- On conflict: Returns a structured failure with conflict list
|
|
683
701
|
- On success: Returns a migration plan with operations
|
|
684
|
-
|
|
702
|
+
8. **Apply Migration** (if not `--plan`):
|
|
685
703
|
- Calls `runner.execute()` to apply the plan
|
|
686
|
-
- Runner executes pre/post checks for each operation
|
|
687
704
|
- After execution, verifies schema matches contract
|
|
688
|
-
- Writes contract marker and ledger entry
|
|
705
|
+
- Writes contract marker (and records a ledger entry via the target runner)
|
|
689
706
|
|
|
690
707
|
**Output Format (TTY - Plan Mode):**
|
|
691
708
|
|
|
692
709
|
```
|
|
693
|
-
prisma-next db init ➜
|
|
710
|
+
prisma-next db init ➜ Bootstrap a database to match the current contract
|
|
694
711
|
config: prisma-next.config.ts
|
|
695
712
|
contract: src/prisma/contract.json
|
|
696
|
-
|
|
713
|
+
mode: plan (dry run)
|
|
697
714
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
├─ Create table
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
└─
|
|
715
|
+
✔ Planned 4 operation(s)
|
|
716
|
+
│
|
|
717
|
+
├─ Create table user [additive]
|
|
718
|
+
├─ Add unique constraint user_email_key on user [additive]
|
|
719
|
+
├─ Create index user_email_idx on user [additive]
|
|
720
|
+
└─ Add foreign key post_userId_fkey on post [additive]
|
|
704
721
|
|
|
705
|
-
|
|
722
|
+
Destination hash: sha256:abc123...
|
|
723
|
+
|
|
724
|
+
This is a dry run. No changes were applied.
|
|
725
|
+
Run without --plan to apply changes.
|
|
706
726
|
```
|
|
707
727
|
|
|
708
728
|
**Output Format (TTY - Apply Mode):**
|
|
709
729
|
|
|
710
730
|
```
|
|
711
|
-
prisma-next db init ➜
|
|
731
|
+
prisma-next db init ➜ Bootstrap a database to match the current contract
|
|
712
732
|
config: prisma-next.config.ts
|
|
713
733
|
contract: src/prisma/contract.json
|
|
714
|
-
database: localhost:5432/mydb
|
|
715
734
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
735
|
+
Applying migration plan and verifying schema...
|
|
736
|
+
→ Create table user...
|
|
737
|
+
→ Add unique constraint user_email_key on user...
|
|
738
|
+
→ Create index user_email_idx on user...
|
|
739
|
+
→ Add foreign key post_userId_fkey on post...
|
|
740
|
+
✔ Applied 4 operation(s)
|
|
741
|
+
Marker written: sha256:abc123...
|
|
723
742
|
```
|
|
724
743
|
|
|
725
744
|
**Output Format (JSON):**
|
|
@@ -729,33 +748,41 @@ prisma-next db init ➜ Initialize database schema from contract
|
|
|
729
748
|
"ok": true,
|
|
730
749
|
"mode": "apply",
|
|
731
750
|
"plan": {
|
|
732
|
-
"
|
|
733
|
-
"
|
|
751
|
+
"targetId": "postgres",
|
|
752
|
+
"destination": {
|
|
753
|
+
"coreHash": "sha256:abc123..."
|
|
754
|
+
},
|
|
755
|
+
"operations": [
|
|
756
|
+
{
|
|
757
|
+
"id": "table.user",
|
|
758
|
+
"label": "Create table user",
|
|
759
|
+
"operationClass": "additive"
|
|
760
|
+
}
|
|
761
|
+
]
|
|
734
762
|
},
|
|
735
763
|
"execution": {
|
|
736
|
-
"
|
|
737
|
-
"
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
"ledger": {
|
|
742
|
-
"id": "ledger-entry-uuid",
|
|
743
|
-
"createdAt": "2025-01-01T00:00:00Z"
|
|
744
|
-
}
|
|
764
|
+
"operationsPlanned": 4,
|
|
765
|
+
"operationsExecuted": 4
|
|
766
|
+
},
|
|
767
|
+
"marker": {
|
|
768
|
+
"coreHash": "sha256:abc123..."
|
|
745
769
|
}
|
|
746
770
|
}
|
|
747
771
|
```
|
|
748
772
|
|
|
749
773
|
**Error Codes:**
|
|
750
|
-
- `PN-CLI-
|
|
751
|
-
- `PN-CLI-
|
|
752
|
-
- `PN-CLI-
|
|
753
|
-
- `PN-CLI-
|
|
774
|
+
- `PN-CLI-4004`: Contract file not found
|
|
775
|
+
- `PN-CLI-4005`: Missing database URL
|
|
776
|
+
- `PN-CLI-4008`: Unsupported JSON format (`--json ndjson` is rejected for `db init`)
|
|
777
|
+
- `PN-CLI-4010`: Missing driver in config
|
|
778
|
+
- `PN-CLI-4020`: Migration planning failed (conflicts)
|
|
779
|
+
- `PN-CLI-4021`: Target does not support migrations
|
|
780
|
+
- `PN-RTM-3000`: Runtime error (includes marker mismatch failures)
|
|
781
|
+
|
|
782
|
+
**Behavior Notes:**
|
|
754
783
|
|
|
755
|
-
|
|
756
|
-
-
|
|
757
|
-
- Non-empty databases result in a planning failure with conflict details
|
|
758
|
-
- Future `db update` command will support additive changes to existing schemas
|
|
784
|
+
- If the database already has a marker that matches the destination contract, `db init` succeeds as a noop (0 operations planned/executed).
|
|
785
|
+
- If the database has a marker that does **not** match the destination contract, `db init` fails (including in `--plan` mode). Use `db init` for bootstrapping; use your migration workflow to reconcile existing databases.
|
|
759
786
|
|
|
760
787
|
**Config File (`prisma-next.config.ts`):**
|
|
761
788
|
|
|
@@ -838,7 +865,7 @@ See `.cursor/rules/config-validation-and-normalization.mdc` for detailed pattern
|
|
|
838
865
|
- **Error Handling**: Uses `exitOverride()` to catch unhandled errors (non-structured errors that fail fast) and print stack traces. Commands handle structured errors themselves via `process.exit()`.
|
|
839
866
|
- **Command Taxonomy**: Groups commands by domain/plane (e.g., `contract emit`)
|
|
840
867
|
- **Help Formatting**: Uses `configureHelp()` to customize help output with styled format matching normal command output. Root help shows "prisma-next" title with command tree; command help shows "prisma-next <command> ➜ <description>" with options and docs URLs. See `utils/output.ts` for help formatters.
|
|
841
|
-
- **Command Descriptions**:
|
|
868
|
+
- **Command Descriptions**: See the “Command Descriptions” section above for `setCommandDescriptions()` usage.
|
|
842
869
|
|
|
843
870
|
### Contract Emit Command (`commands/contract-emit.ts`)
|
|
844
871
|
- Canonical command implementation using commander
|
|
@@ -54,19 +54,16 @@ function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId,
|
|
|
54
54
|
}
|
|
55
55
|
function assertContractRequirementsSatisfied({
|
|
56
56
|
contract,
|
|
57
|
-
|
|
58
|
-
target,
|
|
59
|
-
adapter,
|
|
60
|
-
extensionPacks
|
|
57
|
+
stack
|
|
61
58
|
}) {
|
|
62
|
-
const providedComponentIds = /* @__PURE__ */ new Set([target.id, adapter.id]);
|
|
63
|
-
for (const extension of extensionPacks
|
|
59
|
+
const providedComponentIds = /* @__PURE__ */ new Set([stack.target.id, stack.adapter.id]);
|
|
60
|
+
for (const extension of stack.extensionPacks) {
|
|
64
61
|
providedComponentIds.add(extension.id);
|
|
65
62
|
}
|
|
66
63
|
const result = checkContractComponentRequirements({
|
|
67
64
|
contract,
|
|
68
|
-
expectedTargetFamily:
|
|
69
|
-
expectedTargetId: target.targetId,
|
|
65
|
+
expectedTargetFamily: stack.target.familyId,
|
|
66
|
+
expectedTargetId: stack.target.targetId,
|
|
70
67
|
providedComponentIds
|
|
71
68
|
});
|
|
72
69
|
if (result.familyMismatch) {
|
|
@@ -91,4 +88,4 @@ export {
|
|
|
91
88
|
assertFrameworkComponentsCompatible,
|
|
92
89
|
assertContractRequirementsSatisfied
|
|
93
90
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
91
|
+
//# sourceMappingURL=chunk-CVNWLFXO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/framework-components.ts"],"sourcesContent":["import {\n checkContractComponentRequirements,\n type TargetBoundComponentDescriptor,\n} from '@prisma-next/contract/framework-components';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport type { ControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { errorConfigValidation, errorContractMissingExtensionPacks } from './cli-errors';\n\n/**\n * Asserts that all framework components are compatible with the expected family and target.\n *\n * This function validates that each component in the framework components array:\n * - Has kind 'target', 'adapter', 'extension', or 'driver'\n * - Has familyId matching expectedFamilyId\n * - Has targetId matching expectedTargetId\n *\n * This validation happens at the CLI composition boundary, before passing components\n * to typed planner/runner instances. It fills the gap between runtime validation\n * (via `validateConfig()`) and compile-time type enforcement.\n *\n * @param expectedFamilyId - The expected family ID (e.g., 'sql')\n * @param expectedTargetId - The expected target ID (e.g., 'postgres')\n * @param frameworkComponents - Array of framework components to validate\n * @returns The same array typed as TargetBoundComponentDescriptor\n * @throws CliStructuredError if any component is incompatible\n *\n * @example\n * ```ts\n * const config = await loadConfig();\n * const frameworkComponents = [config.target, config.adapter, ...(config.extensionPacks ?? [])];\n *\n * // Validate and type-narrow components before passing to planner\n * const typedComponents = assertFrameworkComponentsCompatible(\n * config.family.familyId,\n * config.target.targetId,\n * frameworkComponents\n * );\n *\n * const planner = target.migrations.createPlanner(familyInstance);\n * planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });\n * ```\n */\nexport function assertFrameworkComponentsCompatible<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n expectedFamilyId: TFamilyId,\n expectedTargetId: TTargetId,\n frameworkComponents: ReadonlyArray<unknown>,\n): ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>> {\n for (let i = 0; i < frameworkComponents.length; i++) {\n const component = frameworkComponents[i];\n\n // Check that component is an object\n if (typeof component !== 'object' || component === null) {\n throw errorConfigValidation('frameworkComponents[]', {\n why: `Framework component at index ${i} must be an object`,\n });\n }\n\n const record = component as Record<string, unknown>;\n\n // Check kind\n if (!Object.hasOwn(record, 'kind')) {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} must have 'kind' property`,\n });\n }\n\n const kind = record['kind'];\n if (kind !== 'target' && kind !== 'adapter' && kind !== 'extension' && kind !== 'driver') {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`,\n });\n }\n\n // Check familyId\n if (!Object.hasOwn(record, 'familyId')) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`,\n });\n }\n\n const familyId = record['familyId'];\n if (familyId !== expectedFamilyId) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`,\n });\n }\n\n // Check targetId\n if (!Object.hasOwn(record, 'targetId')) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`,\n });\n }\n\n const targetId = record['targetId'];\n if (targetId !== expectedTargetId) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`,\n });\n }\n }\n\n // Type assertion is safe because we've validated all components above\n return frameworkComponents as ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n}\n\n/**\n * Validates that a contract is compatible with the configured target, adapter,\n * and extension packs. Throws on family/target mismatches or missing extension packs.\n *\n * This check ensures the emitted contract matches the CLI config before running\n * commands that depend on the contract (e.g., db verify, db sign).\n *\n * @param contract - The contract IR to validate (must include targetFamily, target, extensionPacks).\n * @param stack - The control plane stack (target, adapter, driver, extensionPacks).\n *\n * @throws {CliStructuredError} errorConfigValidation when contract.targetFamily or contract.target\n * doesn't match the configured family/target.\n * @throws {CliStructuredError} errorContractMissingExtensionPacks when the contract requires\n * extension packs that are not provided in the config (includes all missing packs in error.meta).\n *\n * @example\n * ```ts\n * import { assertContractRequirementsSatisfied } from './framework-components';\n *\n * const config = await loadConfig();\n * const contractIR = await loadContractJson(config.contract.output);\n * const stack = createControlPlaneStack({ target: config.target, adapter: config.adapter, ... });\n *\n * // Throws if contract is incompatible with config\n * assertContractRequirementsSatisfied({ contract: contractIR, stack });\n * ```\n */\nexport function assertContractRequirementsSatisfied<\n TFamilyId extends string,\n TTargetId extends string,\n>({\n contract,\n stack,\n}: {\n readonly contract: Pick<ContractIR, 'targetFamily' | 'target' | 'extensionPacks'>;\n readonly stack: ControlPlaneStack<TFamilyId, TTargetId>;\n}): void {\n const providedComponentIds = new Set<string>([stack.target.id, stack.adapter.id]);\n for (const extension of stack.extensionPacks) {\n providedComponentIds.add(extension.id);\n }\n\n const result = checkContractComponentRequirements({\n contract,\n expectedTargetFamily: stack.target.familyId,\n expectedTargetId: stack.target.targetId,\n providedComponentIds,\n });\n\n if (result.familyMismatch) {\n throw errorConfigValidation('contract.targetFamily', {\n why: `Contract was emitted for family '${result.familyMismatch.actual}' but CLI config is wired to '${result.familyMismatch.expected}'.`,\n });\n }\n\n if (result.targetMismatch) {\n throw errorConfigValidation('contract.target', {\n why: `Contract target '${result.targetMismatch.actual}' does not match CLI target '${result.targetMismatch.expected}'.`,\n });\n }\n\n if (result.missingExtensionPackIds.length > 0) {\n throw errorContractMissingExtensionPacks({\n missingExtensionPacks: result.missingExtensionPackIds,\n providedComponentIds: [...providedComponentIds],\n });\n }\n}\n"],"mappings":";;;;;;AAAA;AAAA,EACE;AAAA,OAEK;AAuCA,SAAS,oCAId,kBACA,kBACA,qBACqE;AACrE,WAAS,IAAI,GAAG,IAAI,oBAAoB,QAAQ,KAAK;AACnD,UAAM,YAAY,oBAAoB,CAAC;AAGvC,QAAI,OAAO,cAAc,YAAY,cAAc,MAAM;AACvD,YAAM,sBAAsB,yBAAyB;AAAA,QACnD,KAAK,gCAAgC,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAEA,UAAM,SAAS;AAGf,QAAI,CAAC,OAAO,OAAO,QAAQ,MAAM,GAAG;AAClC,YAAM,sBAAsB,8BAA8B;AAAA,QACxD,KAAK,gCAAgC,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAEA,UAAM,OAAO,OAAO,MAAM;AAC1B,QAAI,SAAS,YAAY,SAAS,aAAa,SAAS,eAAe,SAAS,UAAU;AACxF,YAAM,sBAAsB,8BAA8B;AAAA,QACxD,KAAK,gCAAgC,CAAC,sBAAsB,OAAO,IAAI,CAAC;AAAA,MAC1E,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,GAAG;AACtC,YAAM,sBAAsB,kCAAkC;AAAA,QAC5D,KAAK,gCAAgC,CAAC,WAAW,OAAO,IAAI,CAAC;AAAA,MAC/D,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,OAAO,UAAU;AAClC,QAAI,aAAa,kBAAkB;AACjC,YAAM,sBAAsB,kCAAkC;AAAA,QAC5D,KAAK,gCAAgC,CAAC,WAAW,OAAO,IAAI,CAAC,mBAAmB,OAAO,QAAQ,CAAC,mBAAmB,gBAAgB;AAAA,MACrI,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,GAAG;AACtC,YAAM,sBAAsB,kCAAkC;AAAA,QAC5D,KAAK,gCAAgC,CAAC,WAAW,OAAO,IAAI,CAAC;AAAA,MAC/D,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,OAAO,UAAU;AAClC,QAAI,aAAa,kBAAkB;AACjC,YAAM,sBAAsB,kCAAkC;AAAA,QAC5D,KAAK,gCAAgC,CAAC,WAAW,OAAO,IAAI,CAAC,mBAAmB,OAAO,QAAQ,CAAC,mBAAmB,gBAAgB;AAAA,MACrI,CAAC;AAAA,IACH;AAAA,EACF;AAGA,SAAO;AACT;AA6BO,SAAS,oCAGd;AAAA,EACA;AAAA,EACA;AACF,GAGS;AACP,QAAM,uBAAuB,oBAAI,IAAY,CAAC,MAAM,OAAO,IAAI,MAAM,QAAQ,EAAE,CAAC;AAChF,aAAW,aAAa,MAAM,gBAAgB;AAC5C,yBAAqB,IAAI,UAAU,EAAE;AAAA,EACvC;AAEA,QAAM,SAAS,mCAAmC;AAAA,IAChD;AAAA,IACA,sBAAsB,MAAM,OAAO;AAAA,IACnC,kBAAkB,MAAM,OAAO;AAAA,IAC/B;AAAA,EACF,CAAC;AAED,MAAI,OAAO,gBAAgB;AACzB,UAAM,sBAAsB,yBAAyB;AAAA,MACnD,KAAK,oCAAoC,OAAO,eAAe,MAAM,iCAAiC,OAAO,eAAe,QAAQ;AAAA,IACtI,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,gBAAgB;AACzB,UAAM,sBAAsB,mBAAmB;AAAA,MAC7C,KAAK,oBAAoB,OAAO,eAAe,MAAM,gCAAgC,OAAO,eAAe,QAAQ;AAAA,IACrH,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,wBAAwB,SAAS,GAAG;AAC7C,UAAM,mCAAmC;AAAA,MACvC,uBAAuB,OAAO;AAAA,MAC9B,sBAAsB,CAAC,GAAG,oBAAoB;AAAA,IAChD,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
import { mkdirSync, writeFileSync } from "fs";
|
|
19
19
|
import { dirname, relative, resolve } from "path";
|
|
20
20
|
import { errorContractConfigMissing } from "@prisma-next/core-control-plane/errors";
|
|
21
|
+
import { createControlPlaneStack } from "@prisma-next/core-control-plane/types";
|
|
21
22
|
import { Command } from "commander";
|
|
22
23
|
function createContractEmitCommand() {
|
|
23
24
|
const command = new Command("emit");
|
|
@@ -65,17 +66,13 @@ function createContractEmitCommand() {
|
|
|
65
66
|
});
|
|
66
67
|
console.log(header);
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
throw errorContractConfigMissing({
|
|
70
|
-
why: "Config.driver is required. Even though emit does not use the driver, it is required by ControlFamilyDescriptor.create()"
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
const familyInstance = config.family.create({
|
|
69
|
+
const stack = createControlPlaneStack({
|
|
74
70
|
target: config.target,
|
|
75
71
|
adapter: config.adapter,
|
|
76
72
|
driver: config.driver,
|
|
77
|
-
extensionPacks: config.extensionPacks
|
|
73
|
+
extensionPacks: config.extensionPacks
|
|
78
74
|
});
|
|
75
|
+
const familyInstance = config.family.create(stack);
|
|
79
76
|
let contractRaw;
|
|
80
77
|
if (typeof contractConfig.source === "function") {
|
|
81
78
|
contractRaw = await contractConfig.source();
|
|
@@ -131,4 +128,4 @@ function createContractEmitCommand() {
|
|
|
131
128
|
export {
|
|
132
129
|
createContractEmitCommand
|
|
133
130
|
};
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
131
|
+
//# sourceMappingURL=chunk-QUPBU4KV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/contract-emit.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, relative, resolve } from 'node:path';\nimport { errorContractConfigMissing } from '@prisma-next/core-control-plane/errors';\nimport { createControlPlaneStack } from '@prisma-next/core-control-plane/types';\nimport { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { performAction } from '../utils/action';\nimport { setCommandDescriptions } from '../utils/command-helpers';\nimport { parseGlobalFlags } from '../utils/global-flags';\nimport {\n formatCommandHelp,\n formatEmitJson,\n formatEmitOutput,\n formatStyledHeader,\n formatSuccessMessage,\n} from '../utils/output';\nimport { handleResult } from '../utils/result-handler';\nimport { withSpinner } from '../utils/spinner';\n\ninterface ContractEmitOptions {\n readonly config?: string;\n readonly json?: string | boolean;\n readonly quiet?: boolean;\n readonly q?: boolean;\n readonly verbose?: boolean;\n readonly v?: boolean;\n readonly vv?: boolean;\n readonly trace?: boolean;\n readonly timestamps?: boolean;\n readonly color?: boolean;\n readonly 'no-color'?: boolean;\n}\n\nexport function createContractEmitCommand(): Command {\n const command = new Command('emit');\n setCommandDescriptions(\n command,\n 'Write your contract to JSON and sign it',\n 'Reads your contract source (TypeScript or Prisma schema) and emits contract.json and\\n' +\n 'contract.d.ts. The contract.json contains the canonical contract structure, and\\n' +\n 'contract.d.ts provides TypeScript types for type-safe query building.',\n );\n command\n .configureHelp({\n formatHelp: (cmd) => {\n const flags = parseGlobalFlags({});\n return formatCommandHelp({ command: cmd, flags });\n },\n })\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--json [format]', 'Output as JSON (object or ndjson)', false)\n .option('-q, --quiet', 'Quiet mode: errors only')\n .option('-v, --verbose', 'Verbose output: debug info, timings')\n .option('-vv, --trace', 'Trace output: deep internals, stack traces')\n .option('--timestamps', 'Add timestamps to output')\n .option('--color', 'Force color output')\n .option('--no-color', 'Disable color output')\n .action(async (options: ContractEmitOptions) => {\n const flags = parseGlobalFlags(options);\n\n const result = await performAction(async () => {\n // Load config\n const config = await loadConfig(options.config);\n\n // Resolve contract from config\n if (!config.contract) {\n throw errorContractConfigMissing({\n why: 'Config.contract is required for emit. Define it in your config: contract: { source: ..., output: ..., types: ... }',\n });\n }\n\n // Contract config is already normalized by defineConfig() with defaults applied\n const contractConfig = config.contract;\n\n // Resolve artifact paths from config (already normalized by defineConfig() with defaults)\n if (!contractConfig.output || !contractConfig.types) {\n throw errorContractConfigMissing({\n why: 'Contract config must have output and types paths. This should not happen if defineConfig() was used.',\n });\n }\n const outputJsonPath = resolve(contractConfig.output);\n const outputDtsPath = resolve(contractConfig.types);\n\n // Output header (only for human-readable output)\n if (flags.json !== 'object' && !flags.quiet) {\n // Normalize config path for display (match contract path format - no ./ prefix)\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n // Convert absolute paths to relative paths for display\n const contractPath = relative(process.cwd(), outputJsonPath);\n const typesPath = relative(process.cwd(), outputDtsPath);\n const header = formatStyledHeader({\n command: 'contract emit',\n description: 'Write your contract to JSON and sign it',\n url: 'https://pris.ly/contract-emit',\n details: [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'types', value: typesPath },\n ],\n flags,\n });\n console.log(header);\n }\n\n const stack = createControlPlaneStack({\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks,\n });\n const familyInstance = config.family.create(stack);\n\n // Resolve contract source from config (user's config handles loading)\n let contractRaw: unknown;\n if (typeof contractConfig.source === 'function') {\n contractRaw = await contractConfig.source();\n } else {\n contractRaw = contractConfig.source;\n }\n\n // Call emitContract on family instance (handles stripping mappings and validation internally)\n const emitResult = await withSpinner(\n () => familyInstance.emitContract({ contractIR: contractRaw }),\n {\n message: 'Emitting contract...',\n flags,\n },\n );\n\n // Create directories if needed\n mkdirSync(dirname(outputJsonPath), { recursive: true });\n mkdirSync(dirname(outputDtsPath), { recursive: true });\n\n // Write the results to files\n writeFileSync(outputJsonPath, emitResult.contractJson, 'utf-8');\n writeFileSync(outputDtsPath, emitResult.contractDts, 'utf-8');\n\n // Add blank line after all async operations if spinners were shown\n if (!flags.quiet && flags.json !== 'object' && process.stdout.isTTY) {\n console.log('');\n }\n\n // Return result with file paths for output formatting\n return {\n coreHash: emitResult.coreHash,\n profileHash: emitResult.profileHash,\n outDir: dirname(outputJsonPath),\n files: {\n json: outputJsonPath,\n dts: outputDtsPath,\n },\n timings: {\n total: 0, // Timing is handled by emitContract internally if needed\n },\n };\n });\n\n // Handle result - formats output and returns exit code\n const exitCode = handleResult(result, flags, (emitResult) => {\n // Output based on flags\n if (flags.json === 'object') {\n // JSON output to stdout\n console.log(formatEmitJson(emitResult));\n } else {\n // Human-readable output to stdout\n const output = formatEmitOutput(emitResult, flags);\n if (output) {\n console.log(output);\n }\n // Output success message\n if (!flags.quiet) {\n console.log(formatSuccessMessage(flags));\n }\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ import { Command as Command7 } from "commander";
|
|
|
7
7
|
import { mkdirSync, writeFileSync } from "fs";
|
|
8
8
|
import { dirname as dirname2, relative as relative2, resolve as resolve2 } from "path";
|
|
9
9
|
import { errorContractConfigMissing as errorContractConfigMissing2 } from "@prisma-next/core-control-plane/errors";
|
|
10
|
+
import { createControlPlaneStack } from "@prisma-next/core-control-plane/types";
|
|
10
11
|
import { Command } from "commander";
|
|
11
12
|
|
|
12
13
|
// src/config-loader.ts
|
|
@@ -1129,17 +1130,13 @@ function createContractEmitCommand() {
|
|
|
1129
1130
|
});
|
|
1130
1131
|
console.log(header);
|
|
1131
1132
|
}
|
|
1132
|
-
|
|
1133
|
-
throw errorContractConfigMissing2({
|
|
1134
|
-
why: "Config.driver is required. Even though emit does not use the driver, it is required by ControlFamilyDescriptor.create()"
|
|
1135
|
-
});
|
|
1136
|
-
}
|
|
1137
|
-
const familyInstance = config.family.create({
|
|
1133
|
+
const stack = createControlPlaneStack({
|
|
1138
1134
|
target: config.target,
|
|
1139
1135
|
adapter: config.adapter,
|
|
1140
1136
|
driver: config.driver,
|
|
1141
|
-
extensionPacks: config.extensionPacks
|
|
1137
|
+
extensionPacks: config.extensionPacks
|
|
1142
1138
|
});
|
|
1139
|
+
const familyInstance = config.family.create(stack);
|
|
1143
1140
|
let contractRaw;
|
|
1144
1141
|
if (typeof contractConfig.source === "function") {
|
|
1145
1142
|
contractRaw = await contractConfig.source();
|
|
@@ -1195,6 +1192,7 @@ function createContractEmitCommand() {
|
|
|
1195
1192
|
// src/commands/db-init.ts
|
|
1196
1193
|
import { readFile } from "fs/promises";
|
|
1197
1194
|
import { relative as relative3, resolve as resolve3 } from "path";
|
|
1195
|
+
import { createControlPlaneStack as createControlPlaneStack2 } from "@prisma-next/core-control-plane/types";
|
|
1198
1196
|
import { redactDatabaseUrl } from "@prisma-next/utils/redact-db-url";
|
|
1199
1197
|
import { Command as Command2 } from "commander";
|
|
1200
1198
|
|
|
@@ -1249,19 +1247,16 @@ function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId,
|
|
|
1249
1247
|
}
|
|
1250
1248
|
function assertContractRequirementsSatisfied({
|
|
1251
1249
|
contract,
|
|
1252
|
-
|
|
1253
|
-
target,
|
|
1254
|
-
adapter,
|
|
1255
|
-
extensionPacks
|
|
1250
|
+
stack
|
|
1256
1251
|
}) {
|
|
1257
|
-
const providedComponentIds = /* @__PURE__ */ new Set([target.id, adapter.id]);
|
|
1258
|
-
for (const extension of extensionPacks
|
|
1252
|
+
const providedComponentIds = /* @__PURE__ */ new Set([stack.target.id, stack.adapter.id]);
|
|
1253
|
+
for (const extension of stack.extensionPacks) {
|
|
1259
1254
|
providedComponentIds.add(extension.id);
|
|
1260
1255
|
}
|
|
1261
1256
|
const result = checkContractComponentRequirements({
|
|
1262
1257
|
contract,
|
|
1263
|
-
expectedTargetFamily:
|
|
1264
|
-
expectedTargetId: target.targetId,
|
|
1258
|
+
expectedTargetFamily: stack.target.familyId,
|
|
1259
|
+
expectedTargetId: stack.target.targetId,
|
|
1265
1260
|
providedComponentIds
|
|
1266
1261
|
});
|
|
1267
1262
|
if (result.familyMismatch) {
|
|
@@ -1389,12 +1384,13 @@ function createDbInitCommand() {
|
|
|
1389
1384
|
});
|
|
1390
1385
|
}
|
|
1391
1386
|
try {
|
|
1392
|
-
const
|
|
1387
|
+
const stack = createControlPlaneStack2({
|
|
1393
1388
|
target: config.target,
|
|
1394
1389
|
adapter: config.adapter,
|
|
1395
1390
|
driver: driverDescriptor,
|
|
1396
|
-
extensionPacks: config.extensionPacks
|
|
1391
|
+
extensionPacks: config.extensionPacks
|
|
1397
1392
|
});
|
|
1393
|
+
const familyInstance = config.family.create(stack);
|
|
1398
1394
|
const rawComponents = [config.target, config.adapter, ...config.extensionPacks ?? []];
|
|
1399
1395
|
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
1400
1396
|
config.family.familyId,
|
|
@@ -1402,13 +1398,7 @@ function createDbInitCommand() {
|
|
|
1402
1398
|
rawComponents
|
|
1403
1399
|
);
|
|
1404
1400
|
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1405
|
-
assertContractRequirementsSatisfied({
|
|
1406
|
-
contract: contractIR,
|
|
1407
|
-
family: config.family,
|
|
1408
|
-
target: config.target,
|
|
1409
|
-
adapter: config.adapter,
|
|
1410
|
-
extensionPacks: config.extensionPacks
|
|
1411
|
-
});
|
|
1401
|
+
assertContractRequirementsSatisfied({ contract: contractIR, stack });
|
|
1412
1402
|
const planner = migrations.createPlanner(familyInstance);
|
|
1413
1403
|
const runner = migrations.createRunner(familyInstance);
|
|
1414
1404
|
const schemaIR = await withSpinner(() => familyInstance.introspect({ driver }), {
|
|
@@ -1596,6 +1586,7 @@ import {
|
|
|
1596
1586
|
errorRuntime as errorRuntime2,
|
|
1597
1587
|
errorUnexpected as errorUnexpected3
|
|
1598
1588
|
} from "@prisma-next/core-control-plane/errors";
|
|
1589
|
+
import { createControlPlaneStack as createControlPlaneStack3 } from "@prisma-next/core-control-plane/types";
|
|
1599
1590
|
import { Command as Command3 } from "commander";
|
|
1600
1591
|
function createDbIntrospectCommand() {
|
|
1601
1592
|
const command = new Command3("introspect");
|
|
@@ -1662,21 +1653,16 @@ function createDbIntrospectCommand() {
|
|
|
1662
1653
|
flags
|
|
1663
1654
|
});
|
|
1664
1655
|
try {
|
|
1665
|
-
const
|
|
1656
|
+
const stack = createControlPlaneStack3({
|
|
1666
1657
|
target: config.target,
|
|
1667
1658
|
adapter: config.adapter,
|
|
1668
1659
|
driver: driverDescriptor,
|
|
1669
|
-
extensionPacks: config.extensionPacks
|
|
1660
|
+
extensionPacks: config.extensionPacks
|
|
1670
1661
|
});
|
|
1662
|
+
const familyInstance = config.family.create(stack);
|
|
1671
1663
|
if (contractIR) {
|
|
1672
1664
|
const validatedContract = familyInstance.validateContractIR(contractIR);
|
|
1673
|
-
assertContractRequirementsSatisfied({
|
|
1674
|
-
contract: validatedContract,
|
|
1675
|
-
family: config.family,
|
|
1676
|
-
target: config.target,
|
|
1677
|
-
adapter: config.adapter,
|
|
1678
|
-
extensionPacks: config.extensionPacks
|
|
1679
|
-
});
|
|
1665
|
+
assertContractRequirementsSatisfied({ contract: validatedContract, stack });
|
|
1680
1666
|
contractIR = validatedContract;
|
|
1681
1667
|
}
|
|
1682
1668
|
let schemaIR;
|
|
@@ -1766,6 +1752,7 @@ import {
|
|
|
1766
1752
|
errorRuntime as errorRuntime3,
|
|
1767
1753
|
errorUnexpected as errorUnexpected4
|
|
1768
1754
|
} from "@prisma-next/core-control-plane/errors";
|
|
1755
|
+
import { createControlPlaneStack as createControlPlaneStack4 } from "@prisma-next/core-control-plane/types";
|
|
1769
1756
|
import { Command as Command4 } from "commander";
|
|
1770
1757
|
function createDbSchemaVerifyCommand() {
|
|
1771
1758
|
const command = new Command4("schema-verify");
|
|
@@ -1821,20 +1808,15 @@ function createDbSchemaVerifyCommand() {
|
|
|
1821
1808
|
throw errorDriverRequired3();
|
|
1822
1809
|
}
|
|
1823
1810
|
const driverDescriptor = config.driver;
|
|
1824
|
-
const
|
|
1811
|
+
const stack = createControlPlaneStack4({
|
|
1825
1812
|
target: config.target,
|
|
1826
1813
|
adapter: config.adapter,
|
|
1827
1814
|
driver: driverDescriptor,
|
|
1828
|
-
extensionPacks: config.extensionPacks ?? []
|
|
1829
|
-
});
|
|
1830
|
-
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1831
|
-
assertContractRequirementsSatisfied({
|
|
1832
|
-
contract: contractIR,
|
|
1833
|
-
family: config.family,
|
|
1834
|
-
target: config.target,
|
|
1835
|
-
adapter: config.adapter,
|
|
1836
1815
|
extensionPacks: config.extensionPacks
|
|
1837
1816
|
});
|
|
1817
|
+
const familyInstance = config.family.create(stack);
|
|
1818
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1819
|
+
assertContractRequirementsSatisfied({ contract: contractIR, stack });
|
|
1838
1820
|
const dbUrl = options.db ?? config.db?.url;
|
|
1839
1821
|
if (!dbUrl) {
|
|
1840
1822
|
throw errorDatabaseUrlRequired3();
|
|
@@ -1908,6 +1890,7 @@ import {
|
|
|
1908
1890
|
errorRuntime as errorRuntime4,
|
|
1909
1891
|
errorUnexpected as errorUnexpected5
|
|
1910
1892
|
} from "@prisma-next/core-control-plane/errors";
|
|
1893
|
+
import { createControlPlaneStack as createControlPlaneStack5 } from "@prisma-next/core-control-plane/types";
|
|
1911
1894
|
import { Command as Command5 } from "commander";
|
|
1912
1895
|
function createDbSignCommand() {
|
|
1913
1896
|
const command = new Command5("sign");
|
|
@@ -1967,20 +1950,15 @@ function createDbSignCommand() {
|
|
|
1967
1950
|
throw errorDriverRequired4();
|
|
1968
1951
|
}
|
|
1969
1952
|
const driverDescriptor = config.driver;
|
|
1970
|
-
const
|
|
1953
|
+
const stack = createControlPlaneStack5({
|
|
1971
1954
|
target: config.target,
|
|
1972
1955
|
adapter: config.adapter,
|
|
1973
1956
|
driver: driverDescriptor,
|
|
1974
|
-
extensionPacks: config.extensionPacks ?? []
|
|
1975
|
-
});
|
|
1976
|
-
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1977
|
-
assertContractRequirementsSatisfied({
|
|
1978
|
-
contract: contractIR,
|
|
1979
|
-
family: config.family,
|
|
1980
|
-
target: config.target,
|
|
1981
|
-
adapter: config.adapter,
|
|
1982
1957
|
extensionPacks: config.extensionPacks
|
|
1983
1958
|
});
|
|
1959
|
+
const familyInstance = config.family.create(stack);
|
|
1960
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
1961
|
+
assertContractRequirementsSatisfied({ contract: contractIR, stack });
|
|
1984
1962
|
const rawComponents = [config.target, config.adapter, ...config.extensionPacks ?? []];
|
|
1985
1963
|
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
1986
1964
|
config.family.familyId,
|
|
@@ -2086,6 +2064,7 @@ import {
|
|
|
2086
2064
|
errorTargetMismatch as errorTargetMismatch2,
|
|
2087
2065
|
errorUnexpected as errorUnexpected6
|
|
2088
2066
|
} from "@prisma-next/core-control-plane/errors";
|
|
2067
|
+
import { createControlPlaneStack as createControlPlaneStack6 } from "@prisma-next/core-control-plane/types";
|
|
2089
2068
|
import { Command as Command6 } from "commander";
|
|
2090
2069
|
function createDbVerifyCommand() {
|
|
2091
2070
|
const command = new Command6("verify");
|
|
@@ -2150,20 +2129,15 @@ function createDbVerifyCommand() {
|
|
|
2150
2129
|
flags
|
|
2151
2130
|
});
|
|
2152
2131
|
try {
|
|
2153
|
-
const
|
|
2132
|
+
const stack = createControlPlaneStack6({
|
|
2154
2133
|
target: config.target,
|
|
2155
2134
|
adapter: config.adapter,
|
|
2156
2135
|
driver: driverDescriptor,
|
|
2157
|
-
extensionPacks: config.extensionPacks ?? []
|
|
2158
|
-
});
|
|
2159
|
-
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
2160
|
-
assertContractRequirementsSatisfied({
|
|
2161
|
-
contract: contractIR,
|
|
2162
|
-
family: config.family,
|
|
2163
|
-
target: config.target,
|
|
2164
|
-
adapter: config.adapter,
|
|
2165
2136
|
extensionPacks: config.extensionPacks
|
|
2166
2137
|
});
|
|
2138
|
+
const familyInstance = config.family.create(stack);
|
|
2139
|
+
const contractIR = familyInstance.validateContractIR(contractJson);
|
|
2140
|
+
assertContractRequirementsSatisfied({ contract: contractIR, stack });
|
|
2167
2141
|
let verifyResult;
|
|
2168
2142
|
try {
|
|
2169
2143
|
verifyResult = await withSpinner(
|