@prisma-next/cli 0.5.0-dev.4 → 0.5.0-dev.40
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 +56 -21
- package/dist/agent-skill-mongo.md +63 -31
- package/dist/agent-skill-postgres.md +1 -1
- package/dist/cli-errors-By1iVE3z.mjs +34 -0
- package/dist/cli-errors-By1iVE3z.mjs.map +1 -0
- package/dist/{cli-errors-C0JhVj0c.d.mts → cli-errors-DDeVsP2Y.d.mts} +1 -0
- package/dist/cli.mjs +123 -15
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-TG7rbCWT.mjs → client-1JqqkiC7.mjs} +45 -20
- package/dist/client-1JqqkiC7.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +2 -2
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +2 -2
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +10 -9
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +5 -5
- package/dist/commands/db-sign.mjs +7 -7
- package/dist/commands/db-update.mjs +9 -9
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +9 -9
- package/dist/commands/migration-apply.d.mts +5 -2
- package/dist/commands/migration-apply.d.mts.map +1 -1
- package/dist/commands/migration-apply.mjs +55 -56
- package/dist/commands/migration-apply.mjs.map +1 -1
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +26 -32
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +14 -5
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +45 -48
- package/dist/commands/migration-plan.mjs.map +1 -1
- package/dist/commands/migration-ref.d.mts +1 -1
- package/dist/commands/migration-ref.d.mts.map +1 -1
- package/dist/commands/migration-ref.mjs +6 -10
- package/dist/commands/migration-ref.mjs.map +1 -1
- package/dist/commands/migration-show.d.mts +13 -7
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +27 -29
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +23 -5
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +3 -3
- package/dist/{config-loader-_W4T21X1.mjs → config-loader-ih8ViDb_.mjs} +2 -2
- package/dist/config-loader-ih8ViDb_.mjs.map +1 -0
- package/dist/config-loader.mjs +1 -1
- package/dist/contract-emit-LjzCoicC.mjs +4 -0
- package/dist/contract-emit-RZBWzkop.mjs +329 -0
- package/dist/contract-emit-RZBWzkop.mjs.map +1 -0
- package/dist/contract-emit-rt_Nmdwq.mjs +150 -0
- package/dist/contract-emit-rt_Nmdwq.mjs.map +1 -0
- package/dist/{contract-enrichment-CGW6mm-E.mjs → contract-enrichment-4Ptgw3Pe.mjs} +1 -1
- package/dist/{contract-enrichment-CGW6mm-E.mjs.map → contract-enrichment-4Ptgw3Pe.mjs.map} +1 -1
- package/dist/{contract-infer-BS4kIX9c.mjs → contract-infer-Cf5J2wVg.mjs} +11 -19
- package/dist/contract-infer-Cf5J2wVg.mjs.map +1 -0
- package/dist/exports/control-api.d.mts +86 -21
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +5 -5
- package/dist/exports/index.mjs +3 -3
- package/dist/exports/init-output.d.mts +39 -0
- package/dist/exports/init-output.d.mts.map +1 -0
- package/dist/exports/init-output.mjs +3 -0
- package/dist/{framework-components-DfZKQBQ2.mjs → framework-components-Bgcre3Z6.mjs} +2 -2
- package/dist/{framework-components-DfZKQBQ2.mjs.map → framework-components-Bgcre3Z6.mjs.map} +1 -1
- package/dist/init-C7dE9KOJ.mjs +2062 -0
- package/dist/init-C7dE9KOJ.mjs.map +1 -0
- package/dist/{inspect-live-schema-BsoFVoS1.mjs → inspect-live-schema-LWtXfxm_.mjs} +9 -9
- package/dist/inspect-live-schema-LWtXfxm_.mjs.map +1 -0
- package/dist/migration-cli.d.mts +41 -11
- package/dist/migration-cli.d.mts.map +1 -1
- package/dist/migration-cli.mjs +308 -84
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-DOXnheFa.mjs → migration-command-scaffold-CU452v9h.mjs} +7 -7
- package/dist/{migration-command-scaffold-DOXnheFa.mjs.map → migration-command-scaffold-CU452v9h.mjs.map} +1 -1
- package/dist/{migration-status-Ry3TnEya.mjs → migration-status-DoPrFIOQ.mjs} +114 -57
- package/dist/migration-status-DoPrFIOQ.mjs.map +1 -0
- package/dist/{migrations-fU0xoKjS.mjs → migrations-MEoKMiV5.mjs} +42 -21
- package/dist/migrations-MEoKMiV5.mjs.map +1 -0
- package/dist/output-BpcQrnnq.mjs +103 -0
- package/dist/output-BpcQrnnq.mjs.map +1 -0
- package/dist/{progress-adapter-B-YvmcDu.mjs → progress-adapter-DgRGldpT.mjs} +1 -1
- package/dist/{progress-adapter-B-YvmcDu.mjs.map → progress-adapter-DgRGldpT.mjs.map} +1 -1
- package/dist/quick-reference-mongo.md +34 -13
- package/dist/quick-reference-postgres.md +11 -9
- package/dist/{result-handler-BJwA7ufw.mjs → result-handler-Ch6hVnOo.mjs} +35 -93
- package/dist/result-handler-Ch6hVnOo.mjs.map +1 -0
- package/dist/{terminal-ui-C5k88MmW.mjs → terminal-ui-u2YgKghu.mjs} +76 -2
- package/dist/terminal-ui-u2YgKghu.mjs.map +1 -0
- package/dist/{verify-bl__PkXk.mjs → verify-BT9tgCOH.mjs} +2 -2
- package/dist/{verify-bl__PkXk.mjs.map → verify-BT9tgCOH.mjs.map} +1 -1
- package/package.json +23 -17
- package/src/cli.ts +32 -6
- package/src/commands/contract-emit.ts +67 -163
- package/src/commands/contract-infer.ts +7 -20
- package/src/commands/db-init.ts +1 -0
- package/src/commands/db-update.ts +1 -1
- package/src/commands/init/detect-pnpm-catalog.ts +141 -0
- package/src/commands/init/errors.ts +254 -0
- package/src/commands/init/exit-codes.ts +62 -0
- package/src/commands/init/hygiene-gitattributes.ts +97 -0
- package/src/commands/init/hygiene-gitignore.ts +48 -0
- package/src/commands/init/hygiene-package-scripts.ts +91 -0
- package/src/commands/init/index.ts +112 -7
- package/src/commands/init/init.ts +766 -144
- package/src/commands/init/inputs.ts +421 -0
- package/src/commands/init/output.ts +147 -0
- package/src/commands/init/probe-db.ts +308 -0
- package/src/commands/init/reinit-cleanup.ts +83 -0
- package/src/commands/init/templates/agent-skill-mongo.md +63 -31
- package/src/commands/init/templates/agent-skill-postgres.md +1 -1
- package/src/commands/init/templates/agent-skill.ts +25 -3
- package/src/commands/init/templates/code-templates.ts +125 -32
- package/src/commands/init/templates/env.ts +80 -0
- package/src/commands/init/templates/quick-reference-mongo.md +34 -13
- package/src/commands/init/templates/quick-reference-postgres.md +11 -9
- package/src/commands/init/templates/quick-reference.ts +42 -3
- package/src/commands/init/templates/tsconfig.ts +167 -5
- package/src/commands/inspect-live-schema.ts +10 -5
- package/src/commands/migration-apply.ts +84 -63
- package/src/commands/migration-new.ts +28 -34
- package/src/commands/migration-plan.ts +80 -56
- package/src/commands/migration-ref.ts +8 -7
- package/src/commands/migration-show.ts +53 -36
- package/src/commands/migration-status.ts +194 -58
- package/src/config-path-validation.ts +0 -1
- package/src/control-api/client.ts +21 -0
- package/src/control-api/operations/contract-emit.ts +198 -115
- package/src/control-api/operations/db-init.ts +10 -6
- package/src/control-api/operations/db-update.ts +10 -6
- package/src/control-api/operations/migration-apply.ts +30 -9
- package/src/control-api/types.ts +69 -7
- package/src/exports/control-api.ts +2 -1
- package/src/exports/init-output.ts +10 -0
- package/src/migration-cli.ts +445 -122
- package/src/utils/cli-errors.ts +49 -2
- package/src/utils/command-helpers.ts +45 -23
- package/src/utils/emit-queue.ts +26 -0
- package/src/utils/formatters/graph-migration-mapper.ts +7 -3
- package/src/utils/formatters/migrations.ts +62 -26
- package/src/utils/publish-contract-artifact-pair.ts +134 -0
- package/dist/cli-errors-DHq6GQGu.mjs +0 -5
- package/dist/client-TG7rbCWT.mjs.map +0 -1
- package/dist/config-loader-_W4T21X1.mjs.map +0 -1
- package/dist/contract-emit-CQfj7xJn.mjs +0 -122
- package/dist/contract-emit-CQfj7xJn.mjs.map +0 -1
- package/dist/contract-emit-DpPjuFy-.mjs +0 -195
- package/dist/contract-emit-DpPjuFy-.mjs.map +0 -1
- package/dist/contract-emit-fhNwwhkQ.mjs +0 -4
- package/dist/contract-infer-BS4kIX9c.mjs.map +0 -1
- package/dist/extract-operation-statements-DZUJNmL3.mjs +0 -13
- package/dist/extract-operation-statements-DZUJNmL3.mjs.map +0 -1
- package/dist/extract-sql-ddl-DDMX-9mz.mjs +0 -26
- package/dist/extract-sql-ddl-DDMX-9mz.mjs.map +0 -1
- package/dist/init-CQfo_4Ro.mjs +0 -430
- package/dist/init-CQfo_4Ro.mjs.map +0 -1
- package/dist/inspect-live-schema-BsoFVoS1.mjs.map +0 -1
- package/dist/migration-status-Ry3TnEya.mjs.map +0 -1
- package/dist/migrations-fU0xoKjS.mjs.map +0 -1
- package/dist/result-handler-BJwA7ufw.mjs.map +0 -1
- package/dist/terminal-ui-C5k88MmW.mjs.map +0 -1
- package/dist/validate-contract-deps-esa-VQ0h.mjs +0 -37
- package/dist/validate-contract-deps-esa-VQ0h.mjs.map +0 -1
- package/src/control-api/operations/extract-operation-statements.ts +0 -14
- package/src/control-api/operations/extract-sql-ddl.ts +0 -47
package/README.md
CHANGED
|
@@ -951,12 +951,12 @@ prisma-next migration plan [--config <path>] [--name <slug>] [--from <hash>] [--
|
|
|
951
951
|
2. Reads existing migrations from `config.migrations.dir` (default: `migrations/`)
|
|
952
952
|
3. Determines the starting point: `--from <hash>` if provided, otherwise the latest migration target
|
|
953
953
|
4. Diffs the starting contract against the new contract using the target's migration planner
|
|
954
|
-
5. Scaffolds a new migration package: `migration.ts` (containing `placeholder(...)` lambdas for any data transforms), `migration.json` (with a content-addressed `
|
|
955
|
-
6. If the plan has unfilled `placeholder(...)` slots, the command returns a successful `pendingPlaceholders` envelope (a warning, not a failure) asking the developer to fill in the slots before re-emitting. The on-disk `ops.json` is `[]` and `
|
|
954
|
+
5. Scaffolds a new migration package: `migration.ts` (containing `placeholder(...)` lambdas for any data transforms), `migration.json` (with a content-addressed `migrationHash` over the planned ops, or over `[]` when the planner could not lower any calls because of placeholders), `ops.json` (the planned ops, or `[]` in the placeholder-blocked case), and contract bookends. The package is **always** fully attested — there is no draft state on disk.
|
|
955
|
+
6. If the plan has unfilled `placeholder(...)` slots, the command returns a successful `pendingPlaceholders` envelope (a warning, not a failure) asking the developer to fill in the slots before re-emitting. The on-disk `ops.json` is `[]` and `migrationHash` is the hash of `(metadata, [])`, so applying the migration as-written will not advance the storage hash to the intended destination — the runner's destination-hash post-check surfaces this as a state mismatch. After filling in the placeholders, run `node migrations/<dir>/migration.ts` to re-emit `ops.json` and the corresponding `migrationHash`. `PN-MIG-2001` is raised only at self-emit time when a slot is still unfilled.
|
|
956
956
|
|
|
957
957
|
**Outputs:**
|
|
958
958
|
- `migrations/<dir>/migration.ts` — editable migration source (with `placeholder(...)` slots when the planner inserted them)
|
|
959
|
-
- `migrations/<dir>/migration.json` — fully attested
|
|
959
|
+
- `migrations/<dir>/migration.json` — fully attested metadata (`migrationHash: string`, never null)
|
|
960
960
|
- `migrations/<dir>/ops.json` — planned operations (empty list `[]` if placeholders blocked the planner)
|
|
961
961
|
- `migrations/<dir>/start-contract.{json,d.ts}` — bookend from the "from" side (when applicable)
|
|
962
962
|
- `migrations/<dir>/end-contract.{json,d.ts}` — bookend from the "to" side
|
|
@@ -965,14 +965,14 @@ prisma-next migration plan [--config <path>] [--name <slug>] [--from <hash>] [--
|
|
|
965
965
|
|
|
966
966
|
### `prisma-next migration show`
|
|
967
967
|
|
|
968
|
-
Display a migration package's operations, DDL preview, and metadata. Accepts a directory path, a hash prefix (git-style matching against `
|
|
968
|
+
Display a migration package's operations, DDL preview, and metadata. Accepts a directory path, a hash prefix (git-style matching against `migrationHash`), or defaults to the latest migration.
|
|
969
969
|
|
|
970
970
|
```bash
|
|
971
971
|
prisma-next migration show [target] [--config <path>] [--json] [-v] [-q] [--color/--no-color]
|
|
972
972
|
```
|
|
973
973
|
|
|
974
974
|
**Options:**
|
|
975
|
-
- `[target]`: Migration directory path or
|
|
975
|
+
- `[target]`: Migration directory path or `migrationHash` prefix (defaults to latest)
|
|
976
976
|
- `--config <path>`: Path to `prisma-next.config.ts`
|
|
977
977
|
- `--json`: Output as JSON object
|
|
978
978
|
- `-q, --quiet`: Quiet mode (errors only)
|
|
@@ -980,7 +980,7 @@ prisma-next migration show [target] [--config <path>] [--json] [-v] [-q] [--colo
|
|
|
980
980
|
|
|
981
981
|
**What it does:**
|
|
982
982
|
1. If `target` is a path (contains `/` or `\`), reads that directory directly
|
|
983
|
-
2. If `target` is a hash prefix, scans all attested migrations and matches against `
|
|
983
|
+
2. If `target` is a hash prefix, scans all attested migrations and matches against `migrationHash`
|
|
984
984
|
3. If no target, defaults to the latest migration
|
|
985
985
|
4. Displays operations with operation class badges, destructive warnings, and DDL preview
|
|
986
986
|
|
|
@@ -1034,15 +1034,14 @@ prisma-next migration apply [--db <url>] [--ref <name>] [--config <path>] [--jso
|
|
|
1034
1034
|
- `-v, --verbose`: Verbose output (debug info, timings)
|
|
1035
1035
|
|
|
1036
1036
|
**What it does:**
|
|
1037
|
-
1. Reads migration packages from `config.migrations.dir
|
|
1038
|
-
2.
|
|
1039
|
-
3.
|
|
1040
|
-
4.
|
|
1041
|
-
5.
|
|
1042
|
-
6.
|
|
1043
|
-
7.
|
|
1044
|
-
8.
|
|
1045
|
-
9. After each migration, the runner verifies the schema and updates the marker/ledger
|
|
1037
|
+
1. Reads migration packages from `config.migrations.dir`. Every package is attested — there is no on-disk draft state. The loader (`readMigrationPackage` in `@prisma-next/migration-tools/io`) rehashes `(metadata, ops)` for each `MigrationPackage` it returns and confirms the result matches the stored `migrationHash`. If a package has been hand-edited or partially written since emit, the load fails with `MIGRATION.HASH_MISMATCH` pointing at the offending directory and asks the developer to re-run `node migrations/<dir>/migration.ts` (or restore from version control).
|
|
1038
|
+
2. Reconstructs the migration graph from all loaded packages
|
|
1039
|
+
3. Determines the destination hash: from `--ref` (via `refs.json`) or from `contract.json`
|
|
1040
|
+
4. Connects to the database and reads the current marker hash
|
|
1041
|
+
5. Finds the shortest path from the marker hash to the destination using graph pathfinding
|
|
1042
|
+
6. Executes each pending migration in order using the target's `MigrationRunner`
|
|
1043
|
+
7. Each migration runs in its own transaction with prechecks, postchecks, and idempotency checks enabled
|
|
1044
|
+
8. After each migration, the runner verifies the schema and updates the marker/ledger
|
|
1046
1045
|
|
|
1047
1046
|
**Config requirements:** Requires `driver` and `db.connection` (or `--db`). `migrations.dir` is optional and defaults to `migrations/`.
|
|
1048
1047
|
|
|
@@ -1050,7 +1049,7 @@ prisma-next migration apply [--db <url>] [--ref <name>] [--config <path>] [--jso
|
|
|
1050
1049
|
|
|
1051
1050
|
**Ref-based routing:** With `--ref`, apply targets the ref's hash instead of the contract hash. This enables multi-environment workflows where staging and production track different points in the migration graph.
|
|
1052
1051
|
|
|
1053
|
-
### Emitting `ops.json` and computing `
|
|
1052
|
+
### Emitting `ops.json` and computing `migrationHash`
|
|
1054
1053
|
|
|
1055
1054
|
There is no dedicated CLI command for emitting a migration — migrations
|
|
1056
1055
|
self-emit. After scaffolding (via `migration plan` or `migration new`),
|
|
@@ -1061,7 +1060,9 @@ run `migration.ts` directly with Node to produce `ops.json` and attest
|
|
|
1061
1060
|
node migrations/<dir>/migration.ts
|
|
1062
1061
|
```
|
|
1063
1062
|
|
|
1064
|
-
The scaffolded `migration.ts` calls `MigrationCLI.run(import.meta.url, ...)` from `@prisma-next/cli/migration-cli` when invoked as the entrypoint. (Postgres scaffolds re-export `MigrationCLI` through `@prisma-next/target-postgres/migration` so a Postgres `migration.ts` only needs the single facade import; Mongo scaffolds still pull from `@prisma-next/cli/migration-cli` directly.) The CLI entrypoint loads `prisma-next.config.ts`, assembles a `ControlStack`, instantiates the migration with that stack (so `dataTransform` and other adapter-aware helpers can materialize a real adapter), and serializes operations to `ops.json` while writing the content-addressed `
|
|
1063
|
+
The scaffolded `migration.ts` calls `MigrationCLI.run(import.meta.url, ...)` from `@prisma-next/cli/migration-cli` when invoked as the entrypoint. (Postgres scaffolds re-export `MigrationCLI` through `@prisma-next/target-postgres/migration` so a Postgres `migration.ts` only needs the single facade import; Mongo scaffolds still pull from `@prisma-next/cli/migration-cli` directly.) The CLI entrypoint loads `prisma-next.config.ts`, assembles a `ControlStack`, instantiates the migration with that stack (so `dataTransform` and other adapter-aware helpers can materialize a real adapter), and serializes operations to `ops.json` while writing the content-addressed `migrationHash` into `migration.json`. If `migration.ts` contains unfilled `placeholder()` slots, the script exits with `PN-MIG-2001` and reports the slot to fill in.
|
|
1064
|
+
|
|
1065
|
+
`MigrationCLI.run` accepts an optional third argument `{ argv?, stdout?, stderr? }` for in-process testability (default: `process.argv` / `process.stdout` / `process.stderr`) and returns the exit code as a `Promise<number>`. The flag surface is `--help` / `--dry-run` / `--config <path>`, parsed by [`clipanion`](https://github.com/arcanis/clipanion). The main multi-command surface (`prisma-next contract emit`, `db verify`, etc.) uses Commander; the per-migration `MigrationCLI.run` entrypoint uses clipanion to keep authored migration files lightweight and in-process testable.
|
|
1065
1066
|
|
|
1066
1067
|
### `prisma-next migration ref`
|
|
1067
1068
|
|
|
@@ -1093,17 +1094,22 @@ flowchart TD
|
|
|
1093
1094
|
CMD_EMIT[Emit Command]
|
|
1094
1095
|
CMD_DB[DB Commands]
|
|
1095
1096
|
CMD_MIG[Migration Commands]
|
|
1096
|
-
|
|
1097
|
+
EXEC_EMIT[executeContractEmit]
|
|
1098
|
+
PUBLISH[publishContractArtifactPair]
|
|
1097
1099
|
EMIT[Emitter]
|
|
1098
1100
|
CTRL[Control Client]
|
|
1099
1101
|
MIG_TOOLS["@prisma-next/migration-tools"]
|
|
1100
1102
|
FS[File System]
|
|
1103
|
+
VITE["@prisma-next/vite-plugin-contract-emit"]
|
|
1101
1104
|
|
|
1102
1105
|
CLI --> CMD_EMIT
|
|
1103
1106
|
CLI --> CMD_DB
|
|
1104
1107
|
CLI --> CMD_MIG
|
|
1105
|
-
CMD_EMIT -->
|
|
1106
|
-
|
|
1108
|
+
CMD_EMIT --> EXEC_EMIT
|
|
1109
|
+
VITE --> EXEC_EMIT
|
|
1110
|
+
EXEC_EMIT --> EMIT
|
|
1111
|
+
EXEC_EMIT --> PUBLISH
|
|
1112
|
+
PUBLISH --> FS
|
|
1107
1113
|
CMD_DB --> CTRL
|
|
1108
1114
|
CMD_MIG --> CTRL
|
|
1109
1115
|
CMD_MIG --> MIG_TOOLS
|
|
@@ -1111,6 +1117,35 @@ flowchart TD
|
|
|
1111
1117
|
CTRL --> FS
|
|
1112
1118
|
```
|
|
1113
1119
|
|
|
1120
|
+
## Canonical Contract Emit Path
|
|
1121
|
+
|
|
1122
|
+
> **For agents/contributors**: `executeContractEmit` is the SINGLE publication path
|
|
1123
|
+
> for `contract.json` + `contract.d.ts`. The CLI command (`prisma-next contract
|
|
1124
|
+
> emit`) and the Vite plugin (`@prisma-next/vite-plugin-contract-emit`) both
|
|
1125
|
+
> call into it. Do NOT re-implement the load → emit → publish dance in a new
|
|
1126
|
+
> caller; if you need additional behavior, extend `ContractEmitOptions` /
|
|
1127
|
+
> `ContractEmitResult` and update `executeContractEmit` itself.
|
|
1128
|
+
|
|
1129
|
+
How it composes:
|
|
1130
|
+
|
|
1131
|
+
- The whole flow (load config → resolve source → emit bytes → publish) is
|
|
1132
|
+
serialized per output JSON path via `queueEmitByOutput`
|
|
1133
|
+
(`src/utils/emit-queue.ts`). Concurrent calls for the same output line up
|
|
1134
|
+
FIFO; concurrent calls for distinct outputs run in parallel. Last submission
|
|
1135
|
+
wins on disk.
|
|
1136
|
+
- Within a single emit, `publishContractArtifactPair`
|
|
1137
|
+
(`src/utils/publish-contract-artifact-pair.ts`) stages temp files, renames
|
|
1138
|
+
`contract.d.ts` before `contract.json`, and attempts to restore the previous
|
|
1139
|
+
pair if either rename fails — so type-only consumers never observe a
|
|
1140
|
+
mismatched pair.
|
|
1141
|
+
- Long-lived hosts (Vite dev server, watch CLIs) must call `disposeEmitQueue`
|
|
1142
|
+
on shutdown to drop the per-output queue state, otherwise the module-global
|
|
1143
|
+
queue map leaks one entry per unique output path.
|
|
1144
|
+
|
|
1145
|
+
The `validateContractDeps` warning is returned in `ContractEmitResult.validationWarning`
|
|
1146
|
+
rather than written to stderr by the operation — callers (CLI, Vite plugin) decide
|
|
1147
|
+
how to render it (`ui.warn`, plugin logger, etc.).
|
|
1148
|
+
|
|
1114
1149
|
## Config Validation and Normalization
|
|
1115
1150
|
|
|
1116
1151
|
The `defineConfig()` function validates and normalizes configs using Arktype:
|
|
@@ -1266,7 +1301,7 @@ export default defineConfig({
|
|
|
1266
1301
|
- **`commander`**: CLI argument parsing and command routing
|
|
1267
1302
|
- **`esbuild`**: Bundling TypeScript contract files with import allowlisting
|
|
1268
1303
|
- **`@prisma-next/emitter`**: Contract emission engine (returns strings)
|
|
1269
|
-
- **`@prisma-next/migration-tools`**: On-disk migration I/O,
|
|
1304
|
+
- **`@prisma-next/migration-tools`**: On-disk migration I/O, hash verification, and history reconstruction
|
|
1270
1305
|
- **`@prisma-next/framework-components`**: Control plane types, migration operation types, control stack (via `./control`)
|
|
1271
1306
|
- **`@prisma-next/errors`**: Error types and factories (via `./control`)
|
|
1272
1307
|
|
|
@@ -4,7 +4,7 @@ This project uses **Prisma Next** with **MongoDB** via `@prisma-next/mongo`. Pri
|
|
|
4
4
|
|
|
5
5
|
## Files
|
|
6
6
|
|
|
7
|
-
- **Contract**: `{{schemaPath}}` — the user's data models. Edit this to add or change models.
|
|
7
|
+
- **Contract**: `{{schemaPath}}` ({{authoringLabel}} authoring) — the user's data models. Edit this to add or change models.
|
|
8
8
|
- **Config**: `prisma-next.config.ts` — tells the CLI where the contract is and how to connect to the database. Loads `.env` via `dotenv/config`.
|
|
9
9
|
- **Database client**: `{{schemaDir}}/db.ts` — `import { db } from '{{dbImportPath}}'`. This is the entry point for all queries.
|
|
10
10
|
- **Generated files** (do not edit by hand):
|
|
@@ -23,71 +23,103 @@ This project uses **Prisma Next** with **MongoDB** via `@prisma-next/mongo`. Pri
|
|
|
23
23
|
|
|
24
24
|
## How to write queries
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Use the ORM (`db.orm`). Each root accessor is the lowercased plural form emitted by `prisma-next contract emit` (typically the `@@map`-ped collection name) — for `model User { @@map("users") }` use `db.orm.users`, for `model Post { @@map("posts") }` use `db.orm.posts`. The Mongo facade has no raw-SQL surface. Two escape hatches exist for cases the ORM can't express; both are covered under "Escape hatches" below.
|
|
27
27
|
|
|
28
28
|
```typescript
|
|
29
29
|
import { db } from '{{dbImportPath}}';
|
|
30
30
|
|
|
31
31
|
// Find one record
|
|
32
|
-
const user = await db.orm.
|
|
33
|
-
.where(
|
|
32
|
+
const user = await db.orm.users
|
|
33
|
+
.where({ email: 'alice@example.com' })
|
|
34
34
|
.first();
|
|
35
|
-
// Returns {
|
|
35
|
+
// Returns { _id: ObjectId; email: string; ... } | null
|
|
36
36
|
|
|
37
|
-
// Find multiple records
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
// Find multiple records — `.all()` returns an AsyncIterableResult, consume
|
|
38
|
+
// either as an async iterable (below) or by `await`ing it to materialise an Array.
|
|
39
|
+
for await (const user of db.orm.users
|
|
40
|
+
.select('_id', 'email')
|
|
40
41
|
.take(10)
|
|
41
|
-
.all()
|
|
42
|
-
//
|
|
42
|
+
.all()) {
|
|
43
|
+
// Each `user` is { _id: ObjectId; email: string }
|
|
44
|
+
}
|
|
45
|
+
// Returns AsyncIterableResult<{ _id: ObjectId; email: string }>
|
|
43
46
|
|
|
44
47
|
// Filter, order, limit
|
|
45
|
-
const recentPosts = await db.orm.
|
|
46
|
-
.where(
|
|
47
|
-
.orderBy(
|
|
48
|
-
.select('
|
|
48
|
+
const recentPosts = await db.orm.posts
|
|
49
|
+
.where({ authorId: userId })
|
|
50
|
+
.orderBy({ createdAt: -1 })
|
|
51
|
+
.select('_id', 'title', 'createdAt')
|
|
49
52
|
.take(50)
|
|
50
53
|
.all();
|
|
51
54
|
|
|
52
|
-
// Include relations
|
|
53
|
-
const usersWithPosts = await db.orm.
|
|
54
|
-
.select('
|
|
55
|
-
.include('posts'
|
|
56
|
-
post.select('id', 'title').orderBy(p => p.createdAt.desc()).take(5)
|
|
57
|
-
)
|
|
55
|
+
// Include relations (reference relations only — embedded relations come back automatically)
|
|
56
|
+
const usersWithPosts = await db.orm.users
|
|
57
|
+
.select('_id', 'email')
|
|
58
|
+
.include('posts')
|
|
58
59
|
.take(10)
|
|
59
60
|
.all();
|
|
60
61
|
```
|
|
61
62
|
|
|
62
63
|
### Key ORM methods
|
|
63
64
|
|
|
64
|
-
- `.where(
|
|
65
|
+
- `.where({ field: value, ... })` — filter records by an equality object. Pass a raw filter expression for `$gt`/`$in`/`$regex` etc.
|
|
65
66
|
- `.select('field1', 'field2', ...)` — pick which fields to return
|
|
66
|
-
- `.orderBy(
|
|
67
|
-
- `.take(n)` — limit
|
|
68
|
-
- `.all()` — execute and return all matching records as an
|
|
69
|
-
- `.first()` — execute and return the first matching
|
|
70
|
-
- `.
|
|
71
|
-
- `.
|
|
67
|
+
- `.orderBy({ field: 1 | -1 })` — sort results (1 = ascending, -1 = descending)
|
|
68
|
+
- `.take(n)` / `.skip(n)` — limit and offset
|
|
69
|
+
- `.all()` — execute and return all matching records as an `AsyncIterableResult`
|
|
70
|
+
- `.first()` — execute with limit 1 and return the first matching row, or `null`
|
|
71
|
+
- `.include('relationName')` — eager-load a reference relation (`$lookup`); embedded relations are already part of the row
|
|
72
|
+
- `.variant('VariantName')` — narrow a polymorphic collection to a discriminator value
|
|
73
|
+
|
|
74
|
+
## Escape hatches
|
|
75
|
+
|
|
76
|
+
The ORM covers the common cases. When you genuinely need something it can't express, prefer these — in order — over reaching for `db.runtime()` (which is an internal executor surface, not a `mongodb`-driver handle):
|
|
77
|
+
|
|
78
|
+
1. **Typed raw aggregations — `db.query`.** The facade exposes a `db.query` builder that runs aggregation pipelines through the same runtime + middleware + codec stack as `db.orm`, so results stay typed against the contract. Use this for `$lookup`/`$facet`/`$graphLookup`/window-function pipelines that the ORM doesn't surface.
|
|
79
|
+
|
|
80
|
+
2. **Direct `mongodb` driver control — `mongoClient` binding.** If you need a raw `MongoClient` (e.g. for transactions, change streams, sessions, or a driver feature Prisma Next doesn't expose), construct one yourself and pass it to `mongo({ mongoClient, dbName, contractJson })`. Your code keeps the `MongoClient` reference and uses it directly, while the same `db` object still gives you the typed ORM surface:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { MongoClient } from 'mongodb';
|
|
84
|
+
import mongo from '@prisma-next/mongo/runtime';
|
|
85
|
+
import type { Contract } from './contract.d';
|
|
86
|
+
import contractJson from './contract.json' with { type: 'json' };
|
|
87
|
+
|
|
88
|
+
const client = new MongoClient(process.env['DATABASE_URL']!);
|
|
89
|
+
await client.connect();
|
|
90
|
+
|
|
91
|
+
export const db = mongo<Contract>({ contractJson, mongoClient: client, dbName: 'mydb' });
|
|
92
|
+
|
|
93
|
+
const session = client.startSession();
|
|
94
|
+
try {
|
|
95
|
+
await session.withTransaction(async () => {
|
|
96
|
+
await db.orm.users.createAll([{ /* ... */ }]);
|
|
97
|
+
});
|
|
98
|
+
} finally {
|
|
99
|
+
await session.endSession();
|
|
100
|
+
}
|
|
101
|
+
```
|
|
72
102
|
|
|
73
103
|
## Rules
|
|
74
104
|
|
|
75
105
|
- **Never hand-edit** `contract.json` or `contract.d.ts`. Always regenerate them with `contract emit`.
|
|
76
106
|
- **Always emit after contract changes.** When you modify `{{schemaPath}}`, run `{{pkgRun}} contract emit` before writing any code that depends on the new or changed models.
|
|
77
|
-
- **Don't restructure `db.ts`.** It's scaffolded by init and works as-is.
|
|
78
|
-
- **Use `db.orm`
|
|
107
|
+
- **Don't restructure `db.ts`.** It's scaffolded by init and works as-is. `db` connects lazily on the first query — there is no `db.connect(...)` step.
|
|
108
|
+
- **Root accessors are emitter-driven.** Use the lowercased plural collection name (e.g. `db.orm.users`, `db.orm.posts`) — not the PascalCase model name. Re-run `{{pkgRun}} contract emit` if a new model's accessor isn't appearing on `db.orm`.
|
|
79
109
|
- **Connection string** is `DATABASE_URL` in `.env`. If the user reports connection errors, check this value and the `.env` file.
|
|
110
|
+
- **Transactions and change streams** require a MongoDB **replica set**. The Mongo facade does not yet expose `db.transaction(...)` — for now, use the `mongoClient` escape hatch above to drive transactions/sessions directly. See the quick reference for dev-environment options; the typed transaction API is tracked under [TML-2313](https://linear.app/prisma-company/issue/TML-2313/mongo-dev-replica-set-story-is-missing-transactions-change-streams).
|
|
111
|
+
- **Don't reach for `db.runtime()`** as an escape hatch. It returns the internal executor (`MongoRuntime`), not a `mongodb` `MongoClient` or `Db`. Use `db.query` for raw aggregations and the `mongoClient` binding for direct driver control.
|
|
80
112
|
|
|
81
113
|
## Workflow for common tasks
|
|
82
114
|
|
|
83
115
|
**User wants to add a new model or field:**
|
|
84
116
|
1. Edit `{{schemaPath}}`
|
|
85
117
|
2. Run `{{pkgRun}} contract emit`
|
|
86
|
-
3. Write query code using `db.orm
|
|
118
|
+
3. Write query code using `db.orm.<collection>` (lowercased plural, see Rules above)
|
|
87
119
|
|
|
88
120
|
**User wants to query data:**
|
|
89
121
|
1. Import `db` from `{{dbImportPath}}`
|
|
90
|
-
2. Use `db.orm
|
|
122
|
+
2. Use `db.orm.<collection>` with `.where()`, `.select()`, `.all()`, `.first()`, etc.
|
|
91
123
|
|
|
92
124
|
**User wants to set up or change the database connection:**
|
|
93
125
|
1. Edit `DATABASE_URL` in `.env`
|
|
@@ -4,7 +4,7 @@ This project uses **Prisma Next** with **PostgreSQL** via `@prisma-next/postgres
|
|
|
4
4
|
|
|
5
5
|
## Files
|
|
6
6
|
|
|
7
|
-
- **Contract**: `{{schemaPath}}` — the user's data models. Edit this to add or change models.
|
|
7
|
+
- **Contract**: `{{schemaPath}}` ({{authoringLabel}} authoring) — the user's data models. Edit this to add or change models.
|
|
8
8
|
- **Config**: `prisma-next.config.ts` — tells the CLI where the contract is and how to connect to the database. Loads `.env` via `dotenv/config`.
|
|
9
9
|
- **Database client**: `{{schemaDir}}/db.ts` — `import { db } from '{{dbImportPath}}'`. This is the entry point for all queries.
|
|
10
10
|
- **Generated files** (do not edit by hand):
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CliStructuredError as CliStructuredError$1, errorConfigValidation as errorConfigValidation$1, errorContractConfigMissing as errorContractConfigMissing$1, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDriverRequired, errorFileNotFound, errorMigrationPlanningFailed, errorTargetMigrationNotSupported, errorUnexpected as errorUnexpected$1 } from "@prisma-next/errors/control";
|
|
2
|
+
import { ERROR_CODE_DESTRUCTIVE_CHANGES, errorDestructiveChanges, errorHashMismatch, errorMarkerMissing, errorRunnerFailed, errorRuntime, errorRuntime as errorRuntime$1, errorTargetMismatch } from "@prisma-next/errors/execution";
|
|
3
|
+
import "@prisma-next/errors/migration";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/cli-errors.ts
|
|
6
|
+
/**
|
|
7
|
+
* Maps a `MigrationToolsError` raised by the migration-tools loader/graph
|
|
8
|
+
* surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,
|
|
9
|
+
* `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.
|
|
10
|
+
*
|
|
11
|
+
* The full `error.details` payload is forwarded into `meta` so machine
|
|
12
|
+
* consumers (`--json`) see structural fields like `dir`, `storedHash`,
|
|
13
|
+
* `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable
|
|
14
|
+
* `code`. The user-visible `summary`/`why`/`fix` text is unchanged.
|
|
15
|
+
*
|
|
16
|
+
* Callers are expected to gate on `MigrationToolsError.is(error)` first
|
|
17
|
+
* (mirroring the original inline pattern); non-`MigrationToolsError`
|
|
18
|
+
* values are caller-classified (rethrow, wrap with command-specific
|
|
19
|
+
* `errorUnexpected`, etc.).
|
|
20
|
+
*/
|
|
21
|
+
function mapMigrationToolsError(error) {
|
|
22
|
+
return errorRuntime(error.message, {
|
|
23
|
+
why: error.why,
|
|
24
|
+
fix: error.fix,
|
|
25
|
+
meta: {
|
|
26
|
+
code: error.code,
|
|
27
|
+
...error.details ?? {}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { errorUnexpected$1 as _, errorContractValidationFailed as a, errorDriverRequired as c, errorMarkerMissing as d, errorMigrationPlanningFailed as f, errorTargetMismatch as g, errorTargetMigrationNotSupported as h, errorContractConfigMissing$1 as i, errorFileNotFound as l, errorRuntime$1 as m, ERROR_CODE_DESTRUCTIVE_CHANGES as n, errorDatabaseConnectionRequired as o, errorRunnerFailed as p, errorConfigValidation$1 as r, errorDestructiveChanges as s, CliStructuredError$1 as t, errorHashMismatch as u, mapMigrationToolsError as v };
|
|
34
|
+
//# sourceMappingURL=cli-errors-By1iVE3z.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-errors-By1iVE3z.mjs","names":[],"sources":["../src/utils/cli-errors.ts"],"sourcesContent":["/**\n * Re-export all domain error factories from @prisma-next/errors for convenience.\n * CLI-specific errors (e.g., Commander argument validation in the main CLI, or\n * clipanion parse errors in the migration-file CLI) can be added here if needed.\n */\nexport type { CliErrorConflict, CliErrorEnvelope } from '@prisma-next/errors/control';\n\nimport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { errorRuntime } from '@prisma-next/errors/execution';\nimport type { MigrationToolsError } from '@prisma-next/migration-tools/errors';\n\nexport {\n CliStructuredError,\n errorConfigFileNotFound,\n errorConfigValidation,\n errorContractConfigMissing,\n errorContractMissingExtensionPacks,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFamilyReadMarkerSqlRequired,\n errorFileNotFound,\n errorMigrationCliInvalidConfigArg,\n errorMigrationCliUnknownFlag,\n errorMigrationPlanningFailed,\n errorQueryRunnerFactoryRequired,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n};\nexport {\n ERROR_CODE_DESTRUCTIVE_CHANGES,\n errorDestructiveChanges,\n errorHashMismatch,\n errorMarkerMissing,\n errorMarkerRequired,\n errorRunnerFailed,\n errorRuntime,\n errorSchemaVerificationFailed,\n errorTargetMismatch,\n} from '@prisma-next/errors/execution';\nexport {\n errorMigrationFileMissing,\n errorMigrationInvalidDefaultExport,\n errorMigrationPlanNotArray,\n errorUnfilledPlaceholder,\n placeholder,\n} from '@prisma-next/errors/migration';\n\n/**\n * Maps a `MigrationToolsError` raised by the migration-tools loader/graph\n * surface (`readMigrationPackage`, `readMigrationsDir`, `readRefs`,\n * `resolveRef`, `reconstructGraph`, ...) into a CLI `errorRuntime` envelope.\n *\n * The full `error.details` payload is forwarded into `meta` so machine\n * consumers (`--json`) see structural fields like `dir`, `storedHash`,\n * `computedHash` (for `MIGRATION.HASH_MISMATCH`) alongside the stable\n * `code`. The user-visible `summary`/`why`/`fix` text is unchanged.\n *\n * Callers are expected to gate on `MigrationToolsError.is(error)` first\n * (mirroring the original inline pattern); non-`MigrationToolsError`\n * values are caller-classified (rethrow, wrap with command-specific\n * `errorUnexpected`, etc.).\n */\nexport function mapMigrationToolsError(error: MigrationToolsError): CliStructuredError {\n return errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgFA,SAAgB,uBAAuB,OAAgD;AACrF,QAAO,aAAa,MAAM,SAAS;EACjC,KAAK,MAAM;EACX,KAAK,MAAM;EACX,MAAM;GAAE,MAAM,MAAM;GAAM,GAAI,MAAM,WAAW,EAAE;GAAG;EACrD,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CliStructuredError as CliStructuredError$1 } from "@prisma-next/errors/control";
|
|
2
2
|
import "@prisma-next/errors/execution";
|
|
3
3
|
import "@prisma-next/errors/migration";
|
|
4
|
+
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
4
5
|
export { CliStructuredError$1 as t };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import "./config-loader-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as createContractInferCommand } from "./contract-infer-
|
|
3
|
+
import "./config-loader-ih8ViDb_.mjs";
|
|
4
|
+
import { n as installShutdownHandlers } from "./terminal-ui-u2YgKghu.mjs";
|
|
5
|
+
import { _ as formatCommandHelp, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, n as addGlobalOptions, v as formatRootHelp } from "./result-handler-Ch6hVnOo.mjs";
|
|
6
|
+
import { t as createContractEmitCommand } from "./contract-emit-rt_Nmdwq.mjs";
|
|
7
|
+
import { t as createContractInferCommand } from "./contract-infer-Cf5J2wVg.mjs";
|
|
8
8
|
import { createDbInitCommand } from "./commands/db-init.mjs";
|
|
9
9
|
import { createDbSchemaCommand } from "./commands/db-schema.mjs";
|
|
10
10
|
import { createDbSignCommand } from "./commands/db-sign.mjs";
|
|
@@ -15,20 +15,126 @@ import { createMigrationNewCommand } from "./commands/migration-new.mjs";
|
|
|
15
15
|
import { createMigrationPlanCommand } from "./commands/migration-plan.mjs";
|
|
16
16
|
import { createMigrationRefCommand } from "./commands/migration-ref.mjs";
|
|
17
17
|
import { createMigrationShowCommand } from "./commands/migration-show.mjs";
|
|
18
|
-
import { t as createMigrationStatusCommand } from "./migration-status-
|
|
18
|
+
import { t as createMigrationStatusCommand } from "./migration-status-DoPrFIOQ.mjs";
|
|
19
19
|
import { Command } from "commander";
|
|
20
20
|
import { distance } from "closest-match";
|
|
21
21
|
|
|
22
|
+
//#region src/commands/init/exit-codes.ts
|
|
23
|
+
/**
|
|
24
|
+
* Stable exit codes for the `init` command.
|
|
25
|
+
*
|
|
26
|
+
* These are part of the command's public contract. AI agents and CI scripts
|
|
27
|
+
* branch on them (FR1.6), so the values must remain stable across versions.
|
|
28
|
+
*
|
|
29
|
+
* Codes 0–3 are the CLI-wide reserved values per the [CLI Style Guide
|
|
30
|
+
* Exit Codes section](../../../../../../../docs/CLI%20Style%20Guide.md#exit-codes):
|
|
31
|
+
* `OK = 0`, `INTERNAL_ERROR = 1`, `PRECONDITION = 2`, `USER_ABORTED = 3`.
|
|
32
|
+
* Codes 4 and 5 are command-specific outcomes for `init`'s two fallible
|
|
33
|
+
* side effects (install + emit). Documented in `--help` via
|
|
34
|
+
* `setCommandDescriptions` in `./index.ts`.
|
|
35
|
+
*/
|
|
36
|
+
const INIT_EXIT_OK = 0;
|
|
37
|
+
/**
|
|
38
|
+
* Anything we did not anticipate — a bug in prisma-next, not something
|
|
39
|
+
* the caller did wrong. Includes the structured error code `5009`
|
|
40
|
+
* (invalid output document) and any unrecognised internal error code,
|
|
41
|
+
* so callers can distinguish "tool is broken" from "your invocation
|
|
42
|
+
* was wrong" (`PRECONDITION = 2`). Maps to the generic "RUN" error
|
|
43
|
+
* domain.
|
|
44
|
+
*/
|
|
45
|
+
const INIT_EXIT_INTERNAL_ERROR = 1;
|
|
46
|
+
/**
|
|
47
|
+
* Preconditions not met. The caller asked for something we cannot do
|
|
48
|
+
* without more input or a different environment. Examples:
|
|
49
|
+
* - missing `package.json` / `deno.json`
|
|
50
|
+
* - non-interactive mode without enough flags to proceed
|
|
51
|
+
* - re-init without `--force` in non-interactive mode
|
|
52
|
+
*/
|
|
53
|
+
const INIT_EXIT_PRECONDITION = 2;
|
|
54
|
+
/**
|
|
55
|
+
* The user actively aborted an interactive prompt (Ctrl-C, declined the
|
|
56
|
+
* re-init confirmation, etc.). Distinct from PRECONDITION because the user
|
|
57
|
+
* was given the choice and made it; no diagnostic is needed.
|
|
58
|
+
*/
|
|
59
|
+
const INIT_EXIT_USER_ABORTED = 3;
|
|
60
|
+
/**
|
|
61
|
+
* Dependency installation step failed without a recoverable fallback.
|
|
62
|
+
* `init` automatically falls back from `pnpm` to `npm` on a recognised
|
|
63
|
+
* workspace/catalog leak (FR7.2); this code is returned only when the
|
|
64
|
+
* fallback also fails, or when the package manager is not pnpm and the
|
|
65
|
+
* single attempt failed. Files written before the install step (config,
|
|
66
|
+
* schema, db client, etc.) remain on disk so the user can fix the
|
|
67
|
+
* environment and re-run; the error envelope's `meta.filesWritten` lists
|
|
68
|
+
* them.
|
|
69
|
+
*/
|
|
70
|
+
const INIT_EXIT_INSTALL_FAILED = 4;
|
|
71
|
+
/**
|
|
72
|
+
* Contract emit step failed after a successful install. Files written
|
|
73
|
+
* before emit (including any installed dependencies) are still on disk;
|
|
74
|
+
* the user can fix the underlying issue (typically a contract syntax
|
|
75
|
+
* error or a missing extension pack) and re-run `prisma-next contract
|
|
76
|
+
* emit` manually.
|
|
77
|
+
*/
|
|
78
|
+
const INIT_EXIT_EMIT_FAILED = 5;
|
|
79
|
+
|
|
80
|
+
//#endregion
|
|
22
81
|
//#region src/commands/init/index.ts
|
|
23
82
|
function createInitCommand() {
|
|
24
83
|
const command = new Command("init");
|
|
25
|
-
setCommandDescriptions(command, "Initialize a new Prisma Next project",
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
84
|
+
setCommandDescriptions(command, "Initialize a new Prisma Next project", `Scaffolds config, schema, and runtime files, installs dependencies,
|
|
85
|
+
and emits the contract. Gets you from zero to typed queries in one step.
|
|
86
|
+
|
|
87
|
+
Run interactively for a guided experience, or supply --target / --authoring
|
|
88
|
+
and --yes for a fully scriptable run (CI, AI coding agents, automation).
|
|
89
|
+
|
|
90
|
+
Exit codes (see CLI Style Guide § Exit Codes):
|
|
91
|
+
${INIT_EXIT_OK} OK Init succeeded.\n ${INIT_EXIT_INTERNAL_ERROR} INTERNAL_ERROR Unexpected bug in prisma-next (please report).\n ${INIT_EXIT_PRECONDITION} PRECONDITION Bad flags / missing prerequisite (e.g. no package.json).\n ${INIT_EXIT_USER_ABORTED} USER_ABORTED User cancelled an interactive prompt.\n ${INIT_EXIT_INSTALL_FAILED} INSTALL_FAILED Dependency installation failed (init-specific).\n ${INIT_EXIT_EMIT_FAILED} EMIT_FAILED \`contract emit\` failed after install (init-specific).`);
|
|
92
|
+
setCommandExamples(command, [
|
|
93
|
+
"prisma-next init",
|
|
94
|
+
"prisma-next init --yes --target postgres --authoring psl",
|
|
95
|
+
"prisma-next init --yes --target mongodb --authoring typescript --json",
|
|
96
|
+
"prisma-next init --yes --force --target postgres --authoring psl # overwrite an existing scaffold",
|
|
97
|
+
"prisma-next init --no-install # skip pnpm/npm install + emit"
|
|
98
|
+
]);
|
|
99
|
+
return addGlobalOptions(command).option("--target <db>", "Database target: postgres or mongodb").option("--authoring <style>", "Schema authoring style: psl or typescript").option("--schema-path <path>", "Where to write the starter schema (default: prisma/contract.prisma)").option("--force", "Overwrite an existing scaffold without prompting").option("--write-env", "Write a .env file from .env.example (gitignored; default: only .env.example)").option("--probe-db", "Connect to DATABASE_URL once and check the server version against the target minimum (opt-in; off by default)").option("--strict-probe", "Treat a failed --probe-db as fatal (no-op without --probe-db; init is offline-by-default)").option("--no-install", "Skip dependency installation and contract emission").action(async (options) => {
|
|
100
|
+
const { runInit } = await import("./init-C7dE9KOJ.mjs");
|
|
101
|
+
const flags = parseGlobalFlags(options);
|
|
102
|
+
const canPrompt = deriveCanPrompt({
|
|
103
|
+
flagsInteractive: flags.interactive,
|
|
104
|
+
optionInteractive: options.interactive,
|
|
105
|
+
stdinIsTTY: Boolean(process.stdin.isTTY)
|
|
106
|
+
});
|
|
107
|
+
const exitCode = await runInit(process.cwd(), {
|
|
108
|
+
options,
|
|
109
|
+
flags,
|
|
110
|
+
canPrompt
|
|
111
|
+
});
|
|
112
|
+
process.exit(exitCode);
|
|
30
113
|
});
|
|
31
|
-
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Bridges the action handler's two TTY checks (stdout via `flags`, stdin
|
|
117
|
+
* via `process.stdin.isTTY`) into the `canPrompt` boolean `runInit`
|
|
118
|
+
* consumes.
|
|
119
|
+
*
|
|
120
|
+
* Per the [Style Guide § Interactivity](../../../../../../../docs/CLI%20Style%20Guide.md#interactivity):
|
|
121
|
+
*
|
|
122
|
+
* - `flags.interactive` governs *decoration* (TerminalUI, intro/outro,
|
|
123
|
+
* spinners) and is derived from stdout-TTY by `parseGlobalFlags`,
|
|
124
|
+
* honouring `--interactive` / `--no-interactive`.
|
|
125
|
+
* - Prompting additionally requires a stdin TTY — closing stdin is a
|
|
126
|
+
* common signal in CI / agent environments even when stdout stays
|
|
127
|
+
* attached.
|
|
128
|
+
* - `--interactive` is the explicit override: when the user passes it,
|
|
129
|
+
* we honour it (e.g. testing flows where stdin is stubbed).
|
|
130
|
+
*
|
|
131
|
+
* Exported so callers and tests can derive the same value without
|
|
132
|
+
* touching `process` globals — F14 of the M1/M2 review.
|
|
133
|
+
*/
|
|
134
|
+
function deriveCanPrompt(opts) {
|
|
135
|
+
if (opts.optionInteractive === true) return true;
|
|
136
|
+
if (opts.flagsInteractive === false) return false;
|
|
137
|
+
return opts.stdinIsTTY;
|
|
32
138
|
}
|
|
33
139
|
|
|
34
140
|
//#endregion
|
|
@@ -72,7 +178,9 @@ const versionOption = program.options.find((opt) => opt.flags.includes("--versio
|
|
|
72
178
|
if (versionOption) versionOption.description = "Output the version number";
|
|
73
179
|
program.configureOutput({
|
|
74
180
|
writeErr: () => {},
|
|
75
|
-
writeOut: () => {
|
|
181
|
+
writeOut: (str) => {
|
|
182
|
+
process.stdout.write(str);
|
|
183
|
+
}
|
|
76
184
|
});
|
|
77
185
|
const rootHelpFormatter = (cmd) => {
|
|
78
186
|
return formatRootHelp({
|
|
@@ -203,7 +311,7 @@ const helpCommand = new Command("help").description("Show usage instructions").c
|
|
|
203
311
|
program,
|
|
204
312
|
flags: parseGlobalFlags({})
|
|
205
313
|
});
|
|
206
|
-
process.
|
|
314
|
+
process.stdout.write(`${helpText}\n`);
|
|
207
315
|
process.exit(0);
|
|
208
316
|
});
|
|
209
317
|
program.addCommand(helpCommand);
|
|
@@ -247,5 +355,5 @@ if (args.length > 0) {
|
|
|
247
355
|
program.parse();
|
|
248
356
|
|
|
249
357
|
//#endregion
|
|
250
|
-
export {
|
|
358
|
+
export { INIT_EXIT_PRECONDITION as a, INIT_EXIT_OK as i, INIT_EXIT_INSTALL_FAILED as n, INIT_EXIT_USER_ABORTED as o, INIT_EXIT_INTERNAL_ERROR as r, INIT_EXIT_EMIT_FAILED as t };
|
|
251
359
|
//# sourceMappingURL=cli.mjs.map
|