@prisma-next/cli 0.12.0-dev.9 → 0.13.0-dev.1
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 +2 -2
- package/dist/cli.mjs +180 -163
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-KgJorIvG.mjs → client-CJzuo5wX.mjs} +222 -107
- package/dist/client-CJzuo5wX.mjs.map +1 -0
- package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-DGMvGBeX.mjs} +318 -25
- package/dist/command-helpers-DGMvGBeX.mjs.map +1 -0
- package/dist/commands/contract-emit.d.mts.map +1 -1
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.d.mts.map +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.d.mts.map +1 -1
- package/dist/commands/db-init.mjs +4 -5
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.d.mts.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.d.mts.map +1 -1
- package/dist/commands/db-sign.mjs +6 -6
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +10 -7
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.d.mts.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +37 -3
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +298 -12
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +55 -13
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +3 -2
- package/dist/commands/migration-graph.d.mts +16 -25
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +185 -2
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +26 -27
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +2 -190
- package/dist/commands/migration-log.d.mts +9 -19
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -137
- package/dist/commands/migration-new.d.mts.map +1 -1
- package/dist/commands/migration-new.mjs +6 -5
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.d.mts +1 -1
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +17 -21
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +24 -36
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +42 -144
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +3 -759
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.d.mts.map +1 -1
- package/dist/commands/ref.mjs +4 -4
- package/dist/commands/ref.mjs.map +1 -1
- package/dist/commands/telemetry/index.d.mts +7 -0
- package/dist/commands/telemetry/index.d.mts.map +1 -0
- package/dist/commands/telemetry/index.mjs +2 -0
- package/dist/{config-loader-B6sJjXTv.mjs → config-loader-p9JMrekQ.mjs} +1 -1
- package/dist/{config-loader-B6sJjXTv.mjs.map → config-loader-p9JMrekQ.mjs.map} +1 -1
- package/dist/config-loader.mjs +1 -1
- package/dist/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-CFXsstzm.mjs} +2 -2
- package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-CFXsstzm.mjs.map} +1 -1
- package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-B_qriF8B.mjs} +5 -5
- package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-B_qriF8B.mjs.map} +1 -1
- package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-C8HmtboH.mjs} +12 -7
- package/dist/contract-emit-C8HmtboH.mjs.map +1 -0
- package/dist/{contract-enrichment-a0V5Y_mL.mjs → contract-enrichment-gn9sWbPw.mjs} +1 -1
- package/dist/{contract-enrichment-a0V5Y_mL.mjs.map → contract-enrichment-gn9sWbPw.mjs.map} +1 -1
- package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-BYT_ra_U.mjs} +5 -5
- package/dist/contract-infer-BYT_ra_U.mjs.map +1 -0
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-ClI1KN6d.mjs} +5 -5
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-ClI1KN6d.mjs.map} +1 -1
- package/dist/{db-verify-v_vUKXTU.mjs → db-verify-C24FKhb7.mjs} +6 -6
- package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-C24FKhb7.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +5 -3
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -3
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/exports/init-output.d.mts +1 -3
- package/dist/exports/init-output.d.mts.map +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{extension-pack-inputs-IDvjRCi3.mjs → extension-pack-inputs-1ySHqxKG.mjs} +1 -1
- package/dist/{extension-pack-inputs-IDvjRCi3.mjs.map → extension-pack-inputs-1ySHqxKG.mjs.map} +1 -1
- package/dist/{framework-components-fYXjz_in.mjs → framework-components-YVQHhPH7.mjs} +2 -2
- package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-YVQHhPH7.mjs.map} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-BpoOYtNZ.d.mts} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-BpoOYtNZ.d.mts.map} +1 -1
- package/dist/{init-Cv9UzWL5.mjs → init-0HwB-Vh8.mjs} +5 -58
- package/dist/init-0HwB-Vh8.mjs.map +1 -0
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-DF6IwcDl.mjs} +7 -5
- package/dist/inspect-live-schema-DF6IwcDl.mjs.map +1 -0
- package/dist/migration-check-soB5uZEQ.mjs +573 -0
- package/dist/migration-check-soB5uZEQ.mjs.map +1 -0
- package/dist/migration-cli.mjs +1 -1
- package/dist/migration-cli.mjs.map +1 -1
- package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-DA-Lhx6o.mjs} +5 -5
- package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-DA-Lhx6o.mjs.map} +1 -1
- package/dist/migration-graph-command-render-CEez7YUK.mjs +1960 -0
- package/dist/migration-graph-command-render-CEez7YUK.mjs.map +1 -0
- package/dist/migration-list-DlJJ_38Z.mjs +230 -0
- package/dist/migration-list-DlJJ_38Z.mjs.map +1 -0
- package/dist/migration-log-CG0qQAFm.mjs +222 -0
- package/dist/migration-log-CG0qQAFm.mjs.map +1 -0
- package/dist/migration-path-target-Ce6OZImp.mjs +38 -0
- package/dist/migration-path-target-Ce6OZImp.mjs.map +1 -0
- package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-z5Ing-TD.mjs} +9 -8
- package/dist/migration-plan-z5Ing-TD.mjs.map +1 -0
- package/dist/migration-status-CgWSoI_g.mjs +446 -0
- package/dist/migration-status-CgWSoI_g.mjs.map +1 -0
- package/dist/{output-B60Gw5fu.mjs → output-mEQ74_nd.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-mEQ74_nd.mjs.map} +1 -1
- package/dist/{progress-adapter-C644QK8l.mjs → progress-adapter-CjAeTxY_.mjs} +1 -1
- package/dist/{progress-adapter-C644QK8l.mjs.map → progress-adapter-CjAeTxY_.mjs.map} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-BkXlikCA.mjs} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-BkXlikCA.mjs.map} +1 -1
- package/dist/schemas-CeGMYFYX.d.mts +191 -0
- package/dist/schemas-CeGMYFYX.d.mts.map +1 -0
- package/dist/schemas-KhXMzNA_.mjs +112 -0
- package/dist/schemas-KhXMzNA_.mjs.map +1 -0
- package/dist/telemetry-BIM4beEO.mjs +122 -0
- package/dist/telemetry-BIM4beEO.mjs.map +1 -0
- package/dist/{terminal-ui-5Y6mrg93.d.mts → terminal-ui-DGRNFWna.d.mts} +1 -1
- package/dist/terminal-ui-DGRNFWna.d.mts.map +1 -0
- package/dist/{types-Dt_SfqFm.d.mts → types-C_tYiJYx.d.mts} +53 -31
- package/dist/types-C_tYiJYx.d.mts.map +1 -0
- package/dist/{verify-DCA9Sldu.mjs → verify-DcOYZ1tH.mjs} +2 -2
- package/dist/{verify-DCA9Sldu.mjs.map → verify-DcOYZ1tH.mjs.map} +1 -1
- package/package.json +26 -22
- package/src/cli.ts +5 -0
- package/src/commands/contract-infer.ts +2 -2
- package/src/commands/db-update.ts +7 -1
- package/src/commands/init/index.ts +6 -35
- package/src/commands/init/init.ts +1 -14
- package/src/commands/init/inputs.ts +0 -75
- package/src/commands/inspect-live-schema.ts +10 -0
- package/src/commands/json/schemas.ts +195 -0
- package/src/commands/migrate.ts +527 -8
- package/src/commands/migration-check.ts +469 -134
- package/src/commands/migration-graph.ts +151 -119
- package/src/commands/migration-list.ts +72 -39
- package/src/commands/migration-log.ts +52 -102
- package/src/commands/migration-new.ts +2 -1
- package/src/commands/migration-plan.ts +2 -1
- package/src/commands/migration-show.ts +31 -66
- package/src/commands/migration-status-overlay.ts +61 -0
- package/src/commands/migration-status.ts +458 -1066
- package/src/commands/telemetry/index.ts +107 -0
- package/src/commands/telemetry/status.ts +67 -0
- package/src/control-api/client.ts +70 -9
- package/src/control-api/operations/contract-emit.ts +22 -2
- package/src/control-api/operations/db-init.ts +6 -3
- package/src/control-api/operations/{db-apply.ts → db-run.ts} +55 -14
- package/src/control-api/operations/db-update.ts +7 -4
- package/src/control-api/operations/db-verify.ts +15 -5
- package/src/control-api/operations/{migration-apply.ts → migrate.ts} +181 -80
- package/src/control-api/operations/{apply.ts → run-migration.ts} +33 -27
- package/src/control-api/types.ts +56 -29
- package/src/utils/cli-errors.ts +70 -2
- package/src/utils/formatters/errors.ts +11 -0
- package/src/utils/formatters/migration-graph-command-render.ts +239 -0
- package/src/utils/formatters/migration-graph-grid-layout.ts +1134 -0
- package/src/utils/formatters/migration-graph-labels.ts +408 -0
- package/src/utils/formatters/migration-graph-model.ts +103 -0
- package/src/utils/formatters/migration-graph-occlusion-render.ts +258 -0
- package/src/utils/formatters/migration-graph-rows.ts +128 -15
- package/src/utils/formatters/migration-graph-space-render.ts +188 -0
- package/src/utils/formatters/migration-list-data-column.ts +4 -91
- package/src/utils/formatters/migration-list-graph-topology.ts +72 -94
- package/src/utils/formatters/migration-list-render.ts +135 -71
- package/src/utils/formatters/migration-list-styler.ts +46 -5
- package/src/utils/formatters/migration-list-types.ts +5 -21
- package/src/utils/formatters/migration-log-table.ts +205 -0
- package/src/utils/formatters/migrations.ts +33 -11
- package/src/utils/global-flags.ts +35 -0
- package/src/utils/integrity-violation-to-check-failure.ts +28 -19
- package/src/utils/legend.ts +38 -0
- package/src/utils/migration-path-target.ts +60 -0
- package/src/utils/telemetry.ts +68 -32
- package/dist/client-KgJorIvG.mjs.map +0 -1
- package/dist/command-helpers-Bbw1GbwL.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/commands/migration-log.mjs.map +0 -1
- package/dist/commands/migration-status.mjs.map +0 -1
- package/dist/contract-emit-D-4jrNve.mjs.map +0 -1
- package/dist/contract-infer-D8uEbJuu.mjs.map +0 -1
- package/dist/graph-render-rFAqZujX.mjs +0 -1081
- package/dist/graph-render-rFAqZujX.mjs.map +0 -1
- package/dist/init-Cv9UzWL5.mjs.map +0 -1
- package/dist/inspect-live-schema-C6ohV_oQ.mjs.map +0 -1
- package/dist/migration-check-BiBJoYYW.mjs +0 -341
- package/dist/migration-check-BiBJoYYW.mjs.map +0 -1
- package/dist/migration-graph-C9WC-7eO.mjs +0 -1478
- package/dist/migration-graph-C9WC-7eO.mjs.map +0 -1
- package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
- package/dist/migration-plan-9DJ7q7_z.mjs.map +0 -1
- package/dist/migration-types-D2FW63pr.d.mts +0 -15
- package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
- package/dist/migrations-Cv2jxNNK.mjs +0 -228
- package/dist/migrations-Cv2jxNNK.mjs.map +0 -1
- package/dist/terminal-ui-5Y6mrg93.d.mts.map +0 -1
- package/dist/types-Dt_SfqFm.d.mts.map +0 -1
- package/src/utils/formatters/graph-migration-mapper.ts +0 -235
- package/src/utils/formatters/graph-render.ts +0 -1323
- package/src/utils/formatters/graph-types.ts +0 -120
- package/src/utils/formatters/migration-graph-lane-colors.ts +0 -31
- package/src/utils/formatters/migration-graph-layout.ts +0 -1141
- package/src/utils/formatters/migration-graph-tree-render.ts +0 -768
package/src/control-api/types.ts
CHANGED
|
@@ -2,7 +2,12 @@ import type {
|
|
|
2
2
|
ContractSourceDiagnostics,
|
|
3
3
|
ContractSourceProvider,
|
|
4
4
|
} from '@prisma-next/config/config-types';
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
Contract,
|
|
7
|
+
ContractMarkerRecord,
|
|
8
|
+
LedgerEntryRecord,
|
|
9
|
+
} from '@prisma-next/contract/types';
|
|
10
|
+
import type { AuthoringPslBlockDescriptorNamespace } from '@prisma-next/framework-components/authoring';
|
|
6
11
|
import type {
|
|
7
12
|
ControlAdapterDescriptor,
|
|
8
13
|
ControlDriverDescriptor,
|
|
@@ -67,7 +72,7 @@ export type ControlActionName =
|
|
|
67
72
|
| 'dbInit'
|
|
68
73
|
| 'dbUpdate'
|
|
69
74
|
| 'dbVerify'
|
|
70
|
-
| '
|
|
75
|
+
| 'migrate'
|
|
71
76
|
| 'verify'
|
|
72
77
|
| 'schemaVerify'
|
|
73
78
|
| 'sign'
|
|
@@ -391,6 +396,7 @@ export interface DbInitSuccess {
|
|
|
391
396
|
*/
|
|
392
397
|
readonly perSpace?: ReadonlyArray<PerSpaceExecutionEntry>;
|
|
393
398
|
readonly summary: string;
|
|
399
|
+
readonly warnings?: ReadonlyArray<MigrationPlannerConflict>;
|
|
394
400
|
}
|
|
395
401
|
|
|
396
402
|
/**
|
|
@@ -406,6 +412,7 @@ export interface DbInitFailure {
|
|
|
406
412
|
readonly summary: string;
|
|
407
413
|
readonly why: string | undefined;
|
|
408
414
|
readonly conflicts: ReadonlyArray<MigrationPlannerConflict> | undefined;
|
|
415
|
+
readonly warnings?: ReadonlyArray<MigrationPlannerConflict>;
|
|
409
416
|
readonly meta: Record<string, unknown> | undefined;
|
|
410
417
|
readonly marker?: {
|
|
411
418
|
readonly storageHash?: string;
|
|
@@ -461,6 +468,7 @@ export interface DbUpdateSuccess {
|
|
|
461
468
|
*/
|
|
462
469
|
readonly perSpace?: ReadonlyArray<PerSpaceExecutionEntry>;
|
|
463
470
|
readonly summary: string;
|
|
471
|
+
readonly warnings?: ReadonlyArray<MigrationPlannerConflict>;
|
|
464
472
|
}
|
|
465
473
|
|
|
466
474
|
/**
|
|
@@ -476,6 +484,7 @@ export interface DbUpdateFailure {
|
|
|
476
484
|
readonly summary: string;
|
|
477
485
|
readonly why: string | undefined;
|
|
478
486
|
readonly conflicts: ReadonlyArray<MigrationPlannerConflict> | undefined;
|
|
487
|
+
readonly warnings?: ReadonlyArray<MigrationPlannerConflict>;
|
|
479
488
|
readonly meta: Record<string, unknown> | undefined;
|
|
480
489
|
}
|
|
481
490
|
|
|
@@ -532,17 +541,17 @@ export type EmitResult = Result<EmitSuccess, EmitFailure>;
|
|
|
532
541
|
// ============================================================================
|
|
533
542
|
|
|
534
543
|
/**
|
|
535
|
-
* Options for the aggregate-walking `
|
|
544
|
+
* Options for the aggregate-walking `migrate` operation.
|
|
536
545
|
*
|
|
537
546
|
* The control-api operation is responsible for: loading the
|
|
538
547
|
* contract-space aggregate, reading per-space marker rows from the
|
|
539
548
|
* live database, plotting per-space paths via `graphWalkStrategy`
|
|
540
549
|
* (replay-only — no synth, no introspection), and dispatching
|
|
541
|
-
* through the shared `
|
|
550
|
+
* through the shared `runMigration` primitive. The CLI command
|
|
542
551
|
* just resolves the descriptor surface (config, refs, contract
|
|
543
552
|
* envelope, app-space migration packages) and hands the inputs in.
|
|
544
553
|
*/
|
|
545
|
-
export interface
|
|
554
|
+
export interface MigrateOptions {
|
|
546
555
|
/** Already-validated app contract (the canonical "where we are heading" hash). */
|
|
547
556
|
readonly contract: unknown;
|
|
548
557
|
/** Migrations root directory (`migrations/` under the project). */
|
|
@@ -567,7 +576,7 @@ export interface MigrationApplyOptions {
|
|
|
567
576
|
*/
|
|
568
577
|
readonly refName?: string;
|
|
569
578
|
/**
|
|
570
|
-
* Database connection. If provided,
|
|
579
|
+
* Database connection. If provided, migrate will connect before executing.
|
|
571
580
|
* If omitted, the client must already be connected.
|
|
572
581
|
*/
|
|
573
582
|
readonly connection?: unknown;
|
|
@@ -611,7 +620,7 @@ export interface MigrationApplyStep {
|
|
|
611
620
|
* Per-space aggregate detail (markers, ops grouped by space) lives
|
|
612
621
|
* on `perSpace[]`; this list is the per-edge view.
|
|
613
622
|
*/
|
|
614
|
-
export interface
|
|
623
|
+
export interface MigrateRanEntry {
|
|
615
624
|
readonly spaceId: string;
|
|
616
625
|
readonly dirName: string;
|
|
617
626
|
readonly migrationHash: string;
|
|
@@ -621,13 +630,13 @@ export interface MigrationApplyAppliedEntry {
|
|
|
621
630
|
}
|
|
622
631
|
|
|
623
632
|
/**
|
|
624
|
-
* Successful
|
|
625
|
-
* (`markerHash` is the **app member's** post-
|
|
633
|
+
* Successful migrate result. Carries both the top-level fields
|
|
634
|
+
* (`markerHash` is the **app member's** post-migrate marker) and the
|
|
626
635
|
* per-space breakdown (`perSpace` — markers / operations in canonical
|
|
627
636
|
* schedule order).
|
|
628
637
|
*/
|
|
629
638
|
/**
|
|
630
|
-
* Path-decision summary for the **app member** post-
|
|
639
|
+
* Path-decision summary for the **app member** post-migrate. Surfaced
|
|
631
640
|
* at the top level (and consumed by the cli-journeys suite, which
|
|
632
641
|
* inspects `requiredInvariants`/`satisfiedInvariants`/
|
|
633
642
|
* `selectedPath` to validate invariant routing).
|
|
@@ -635,7 +644,7 @@ export interface MigrationApplyAppliedEntry {
|
|
|
635
644
|
* Per-space path decisions for extension members are not surfaced —
|
|
636
645
|
* extensions own their own ref/invariant control.
|
|
637
646
|
*/
|
|
638
|
-
export interface
|
|
647
|
+
export interface MigratePathDecision {
|
|
639
648
|
readonly fromHash: string;
|
|
640
649
|
readonly toHash: string;
|
|
641
650
|
readonly alternativeCount: number;
|
|
@@ -652,10 +661,10 @@ export interface MigrationApplyPathDecision {
|
|
|
652
661
|
}[];
|
|
653
662
|
}
|
|
654
663
|
|
|
655
|
-
export interface
|
|
664
|
+
export interface MigrateSuccess {
|
|
656
665
|
readonly migrationsApplied: number;
|
|
657
666
|
readonly markerHash: string;
|
|
658
|
-
readonly applied: readonly
|
|
667
|
+
readonly applied: readonly MigrateRanEntry[];
|
|
659
668
|
readonly summary: string;
|
|
660
669
|
/**
|
|
661
670
|
* Per-space breakdown in canonical schedule order (extensions
|
|
@@ -666,31 +675,31 @@ export interface MigrationApplySuccess {
|
|
|
666
675
|
/**
|
|
667
676
|
* Path-decision data for the app member. Present whenever the
|
|
668
677
|
* graph-walk strategy ran for the app (i.e. always for the
|
|
669
|
-
* aggregate-walking
|
|
678
|
+
* aggregate-walking migrate path). Absent only for the no-op
|
|
670
679
|
* "Already up to date" early return when the app has no plan.
|
|
671
680
|
*/
|
|
672
|
-
readonly pathDecision?:
|
|
681
|
+
readonly pathDecision?: MigratePathDecision;
|
|
673
682
|
}
|
|
674
683
|
|
|
675
684
|
/**
|
|
676
|
-
* Failure codes for
|
|
685
|
+
* Failure codes for migrate operation.
|
|
677
686
|
*/
|
|
678
|
-
export type
|
|
687
|
+
export type MigrateFailureCode = 'RUNNER_FAILED' | 'MIGRATION_PATH_NOT_FOUND';
|
|
679
688
|
|
|
680
689
|
/**
|
|
681
|
-
* Failure details for
|
|
690
|
+
* Failure details for migrate operation.
|
|
682
691
|
*/
|
|
683
|
-
export interface
|
|
684
|
-
readonly code:
|
|
692
|
+
export interface MigrateFailure {
|
|
693
|
+
readonly code: MigrateFailureCode;
|
|
685
694
|
readonly summary: string;
|
|
686
695
|
readonly why: string | undefined;
|
|
687
696
|
readonly meta: Record<string, unknown> | undefined;
|
|
688
697
|
}
|
|
689
698
|
|
|
690
699
|
/**
|
|
691
|
-
* Result type for
|
|
700
|
+
* Result type for migrate operation.
|
|
692
701
|
*/
|
|
693
|
-
export type
|
|
702
|
+
export type MigrateResult = Result<MigrateSuccess, MigrateFailure>;
|
|
694
703
|
|
|
695
704
|
// ============================================================================
|
|
696
705
|
// Standalone Contract Emit Types
|
|
@@ -877,17 +886,26 @@ export interface ControlClient {
|
|
|
877
886
|
readAllMarkers(): Promise<ReadonlyMap<string, ContractMarkerRecord>>;
|
|
878
887
|
|
|
879
888
|
/**
|
|
880
|
-
*
|
|
889
|
+
* Reads the per-migration ledger journal for `space` in apply order.
|
|
890
|
+
* Returns an empty array when the ledger store does not yet exist or
|
|
891
|
+
* has no rows for that space.
|
|
892
|
+
*/
|
|
893
|
+
readLedger(space?: string): Promise<readonly LedgerEntryRecord[]>;
|
|
894
|
+
|
|
895
|
+
/**
|
|
896
|
+
* Advances the database along the migration graph to the target contract.
|
|
881
897
|
* Each migration runs in its own transaction with full execution checks.
|
|
882
|
-
* Resume-safe: re-running after failure picks up from the last
|
|
898
|
+
* Resume-safe: re-running after failure picks up from the last run migration.
|
|
883
899
|
*
|
|
884
|
-
* @param options.
|
|
885
|
-
* @param options.
|
|
886
|
-
* @param options.
|
|
887
|
-
* @
|
|
900
|
+
* @param options.contract - The target contract to migrate to
|
|
901
|
+
* @param options.migrationsDir - Root migrations directory (`migrations/` under the project)
|
|
902
|
+
* @param options.refHash - Optional app-space ref override hash
|
|
903
|
+
* @param options.refInvariants - Required invariants on the user-supplied ref
|
|
904
|
+
* @param options.refName - Resolved name of the user-supplied app-space ref
|
|
905
|
+
* @returns Result pattern: Ok with migration details, NotOk with failure details
|
|
888
906
|
* @throws If not connected, target doesn't support migrations, or infrastructure failure
|
|
889
907
|
*/
|
|
890
|
-
|
|
908
|
+
migrate(options: MigrateOptions): Promise<MigrateResult>;
|
|
891
909
|
|
|
892
910
|
/**
|
|
893
911
|
* Introspects the database schema.
|
|
@@ -915,6 +933,15 @@ export interface ControlClient {
|
|
|
915
933
|
*/
|
|
916
934
|
inferPslContract(schemaIR: unknown): PslDocumentAst | undefined;
|
|
917
935
|
|
|
936
|
+
/**
|
|
937
|
+
* Returns the assembled PSL block descriptors from the control stack — the full
|
|
938
|
+
* set of extension-contributed top-level block descriptors. The CLI's
|
|
939
|
+
* `contract infer` command threads these through to `printPsl` so
|
|
940
|
+
* extension-contributed blocks in the inferred AST round-trip back to PSL
|
|
941
|
+
* source. Forces `init()` so the stack is built before access.
|
|
942
|
+
*/
|
|
943
|
+
getPslBlockDescriptors(): AuthoringPslBlockDescriptorNamespace;
|
|
944
|
+
|
|
918
945
|
/**
|
|
919
946
|
* Renders a textual preview of a migration plan's operations for the CLI's
|
|
920
947
|
* "DDL preview" output. Delegates to the family instance's
|
package/src/utils/cli-errors.ts
CHANGED
|
@@ -28,7 +28,8 @@ import {
|
|
|
28
28
|
import { errorRuntime } from '@prisma-next/errors/execution';
|
|
29
29
|
import type { MigrationToolsError } from '@prisma-next/migration-tools/errors';
|
|
30
30
|
import type { RefResolutionError } from '@prisma-next/migration-tools/ref-resolution';
|
|
31
|
-
import
|
|
31
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
32
|
+
import type { MigrateFailure } from '../control-api/types';
|
|
32
33
|
|
|
33
34
|
export {
|
|
34
35
|
ERROR_CODE_DESTRUCTIVE_CHANGES,
|
|
@@ -108,6 +109,23 @@ export function errorRefSetEmptySentinel(hash: string): CliStructuredError {
|
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
|
|
112
|
+
/**
|
|
113
|
+
* `--legend` was combined with a machine-readable or silent output flag.
|
|
114
|
+
* The legend is human-only decoration on stderr.
|
|
115
|
+
*/
|
|
116
|
+
export function errorLegendHumanOnly(
|
|
117
|
+
conflictingFlag: '--json' | '--dot' | '--quiet',
|
|
118
|
+
): CliStructuredError {
|
|
119
|
+
return errorRuntime('`--legend` is only available for human-readable output', {
|
|
120
|
+
why: `\`--legend\` prints a glyph key to stderr and cannot be combined with ${conflictingFlag}.`,
|
|
121
|
+
fix: `Omit ${conflictingFlag} to print the legend alongside the tree, or omit --legend when using ${conflictingFlag}.`,
|
|
122
|
+
meta: {
|
|
123
|
+
code: 'MIGRATION.LEGEND_HUMAN_ONLY',
|
|
124
|
+
conflictingFlag,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
/**
|
|
112
130
|
* `--space <id>` was given a value that doesn't satisfy the contract-space
|
|
113
131
|
* naming rule (`[a-z][a-z0-9_-]{0,63}` per `isValidSpaceId`). Fires before
|
|
@@ -250,7 +268,7 @@ export function errorMarkerMismatch(
|
|
|
250
268
|
});
|
|
251
269
|
}
|
|
252
270
|
|
|
253
|
-
export function errorPathUnreachable(failure:
|
|
271
|
+
export function errorPathUnreachable(failure: MigrateFailure): CliStructuredError {
|
|
254
272
|
const meta = failure.meta ?? {};
|
|
255
273
|
const fromHashMeta = typeof meta['fromHash'] === 'string' ? meta['fromHash'] : null;
|
|
256
274
|
// `buildPathNotFoundFailure` uses this sentinel in meta when the live marker is null.
|
|
@@ -325,10 +343,60 @@ export function mapMigrationToolsError(error: MigrationToolsError): CliStructure
|
|
|
325
343
|
});
|
|
326
344
|
}
|
|
327
345
|
|
|
346
|
+
/**
|
|
347
|
+
* Shared "needs a live database" precondition for read verbs that consult the
|
|
348
|
+
* marker/ledger (`migration log`, `migration status`). A command needs both a
|
|
349
|
+
* connection string and a control-plane driver; either missing yields the same
|
|
350
|
+
* `PN-CLI-4005` envelope with `meta.missingFlags` (canonical long-form flags
|
|
351
|
+
* per CLI Style Guide §Errors) so callers can react programmatically. Returns
|
|
352
|
+
* `null` when both are present.
|
|
353
|
+
*/
|
|
354
|
+
export function requireLiveDatabase(args: {
|
|
355
|
+
readonly dbConnection: unknown;
|
|
356
|
+
readonly hasDriver: boolean;
|
|
357
|
+
readonly why: string;
|
|
358
|
+
readonly commandName?: string;
|
|
359
|
+
readonly retryCommand?: string;
|
|
360
|
+
}): CliStructuredError | null {
|
|
361
|
+
if (args.dbConnection && args.hasDriver) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
const missingFlags = args.dbConnection ? [] : ['--db'];
|
|
365
|
+
return errorDatabaseConnectionRequired({
|
|
366
|
+
why: args.why,
|
|
367
|
+
missingFlags,
|
|
368
|
+
...ifDefined('commandName', args.commandName),
|
|
369
|
+
...ifDefined('retryCommand', args.retryCommand),
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
328
373
|
/**
|
|
329
374
|
* Maps a `RefResolutionError` from the contract/migration reference
|
|
330
375
|
* resolver into a CLI structured error envelope.
|
|
331
376
|
*/
|
|
377
|
+
/**
|
|
378
|
+
* A migration ref (dirName or hash-prefix) resolves in more than one contract
|
|
379
|
+
* space. The user must qualify with `--space <id>` to disambiguate.
|
|
380
|
+
*/
|
|
381
|
+
export function errorAmbiguousMigrationRef(
|
|
382
|
+
ref: string,
|
|
383
|
+
spaceIds: readonly string[],
|
|
384
|
+
): CliStructuredError {
|
|
385
|
+
const spaceList = spaceIds.join(', ');
|
|
386
|
+
return errorRuntime(
|
|
387
|
+
`Ambiguous migration reference: "${ref}" resolves in multiple spaces — qualify with --space <id>`,
|
|
388
|
+
{
|
|
389
|
+
why: `"${ref}" matches migrations in spaces: ${spaceList}.`,
|
|
390
|
+
fix: `Qualify with --space <id> to select one space. Available matching spaces: ${spaceList}.`,
|
|
391
|
+
meta: {
|
|
392
|
+
code: 'MIGRATION.AMBIGUOUS_MIGRATION_REF',
|
|
393
|
+
ref,
|
|
394
|
+
spaceIds: [...spaceIds],
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
332
400
|
export function mapRefResolutionError(error: RefResolutionError): CliStructuredError {
|
|
333
401
|
switch (error.kind) {
|
|
334
402
|
case 'not-found':
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { MigrationPlannerConflict } from '@prisma-next/framework-components/control';
|
|
2
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
1
3
|
import { red } from 'colorette';
|
|
2
4
|
|
|
3
5
|
import type { CliErrorConflict, CliErrorEnvelope } from '../cli-errors';
|
|
4
6
|
import type { GlobalFlags } from '../global-flags';
|
|
5
7
|
import { createColorFormatter, formatDim, isVerbose } from './helpers';
|
|
8
|
+
import { formatPlannerWarningsBlock } from './migrations';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Formats error output for human-readable display.
|
|
@@ -67,6 +70,14 @@ export function formatErrorOutput(error: CliErrorEnvelope, flags: GlobalFlags):
|
|
|
67
70
|
if (error.docsUrl && isVerbose(flags, 1)) {
|
|
68
71
|
lines.push(formatDimText(error.docsUrl));
|
|
69
72
|
}
|
|
73
|
+
const plannerWarnings = error.meta?.['plannerWarnings'];
|
|
74
|
+
if (Array.isArray(plannerWarnings) && plannerWarnings.length > 0) {
|
|
75
|
+
const typedWarnings = blindCast<
|
|
76
|
+
readonly MigrationPlannerConflict[],
|
|
77
|
+
'mapDbUpdateFailure (db-update.ts) writes meta.plannerWarnings as MigrationPlannerConflict[]; meta is typed Record<string, unknown> so the channel erases the element type'
|
|
78
|
+
>(plannerWarnings);
|
|
79
|
+
lines.push(...formatPlannerWarningsBlock(typedWarnings, useColor));
|
|
80
|
+
}
|
|
70
81
|
if (isVerbose(flags, 2) && error.meta) {
|
|
71
82
|
lines.push(`${formatDimText(` Meta: ${JSON.stringify(error.meta, null, 2)}`)}`);
|
|
72
83
|
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command graph renderer: composes the gutter (from the grid) with per-row labels.
|
|
3
|
+
*
|
|
4
|
+
* Pipeline: buildMigrationGraphRows → buildGrid → renderMigrationGraphCommand
|
|
5
|
+
*
|
|
6
|
+
* Each grid row is classified by its cells: a node row gets a contract label;
|
|
7
|
+
* a migration arrow row gets a migration label; connector rows get no label.
|
|
8
|
+
* Label format and styling live in `./migration-graph-labels`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { EMPTY_CONTRACT_HASH } from '@prisma-next/migration-tools/constants';
|
|
12
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
13
|
+
import stringWidth from 'string-width';
|
|
14
|
+
import type { GlyphMode } from '../glyph-mode';
|
|
15
|
+
import {
|
|
16
|
+
formatMigrationLabel,
|
|
17
|
+
formatNodeLabel,
|
|
18
|
+
type MigrationEdgeAnnotation,
|
|
19
|
+
type MigrationGraphLabelOptions,
|
|
20
|
+
} from './migration-graph-labels';
|
|
21
|
+
import type { Cell, CellLine, Grid } from './migration-graph-model';
|
|
22
|
+
import { renderGridRow } from './migration-graph-occlusion-render';
|
|
23
|
+
import type { ClassifiedEdge, MigrationGraphRowModel } from './migration-graph-rows';
|
|
24
|
+
import type { MigrationListStyler } from './migration-list-render';
|
|
25
|
+
|
|
26
|
+
const LABEL_GAP = 2;
|
|
27
|
+
const MIN_HASH_DATA_COLUMN = 25;
|
|
28
|
+
|
|
29
|
+
export interface RenderMigrationGraphCommandInput {
|
|
30
|
+
readonly grid: Grid;
|
|
31
|
+
readonly rowModel: MigrationGraphRowModel;
|
|
32
|
+
readonly colorize: boolean;
|
|
33
|
+
readonly glyphMode: GlyphMode;
|
|
34
|
+
readonly refsByHash?: ReadonlyMap<string, readonly string[]>;
|
|
35
|
+
readonly edgeAnnotationsByHash?: ReadonlyMap<string, MigrationEdgeAnnotation>;
|
|
36
|
+
readonly dbHash?: string;
|
|
37
|
+
readonly contractHash?: string;
|
|
38
|
+
readonly isAppSpace?: boolean;
|
|
39
|
+
readonly activeRefName?: string;
|
|
40
|
+
readonly styler?: MigrationListStyler;
|
|
41
|
+
/** Cross-space override for the gutter→label column (max gutter width). */
|
|
42
|
+
readonly globalLabelColumn?: number;
|
|
43
|
+
/** Cross-space override for the migration-name column width. */
|
|
44
|
+
readonly globalMaxDirNameWidth?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Row classification — derive each grid row's identity from its own cells.
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
type RowIdentity =
|
|
52
|
+
| { readonly kind: 'node'; readonly contractHash: string }
|
|
53
|
+
| { readonly kind: 'migration'; readonly edge: ClassifiedEdge; readonly lane: number }
|
|
54
|
+
| { readonly kind: 'none' };
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Classify a grid row by its own cells:
|
|
58
|
+
* - a cell carrying a NodeRef → node row (contract label);
|
|
59
|
+
* - a cell whose top line is an arrow ({up}/{down}/self-loop) → migration row;
|
|
60
|
+
* - otherwise → no label.
|
|
61
|
+
*
|
|
62
|
+
* A migration's arrow appears in exactly one grid row (the forward `↑` row, the
|
|
63
|
+
* adjacent-rollback `↓` row, or the self-loop `⟲` row), so each migration gets
|
|
64
|
+
* exactly one label, on the row that draws its arrow.
|
|
65
|
+
*
|
|
66
|
+
* Two distinct migrations with identical content (same from/to/ops) hash to the
|
|
67
|
+
* SAME migration hash, so the arrow line is matched on BOTH its hash and its
|
|
68
|
+
* `dirName` (which the LineRef carries per-row) — otherwise both rows would
|
|
69
|
+
* resolve to one edge and the other migration's name would be lost.
|
|
70
|
+
*/
|
|
71
|
+
function classifyRow(
|
|
72
|
+
row: readonly Cell[],
|
|
73
|
+
edgesByHash: ReadonlyMap<string, readonly ClassifiedEdge[]>,
|
|
74
|
+
): RowIdentity {
|
|
75
|
+
for (const cell of row) {
|
|
76
|
+
if (cell.node !== undefined) {
|
|
77
|
+
return { kind: 'node', contractHash: cell.node.contractHash };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (const cell of row) {
|
|
81
|
+
const arrow = arrowLine(cell);
|
|
82
|
+
if (arrow === undefined) continue;
|
|
83
|
+
const candidates = edgesByHash.get(arrow.line.migrationHash) ?? [];
|
|
84
|
+
const edge = candidates.find((e) => e.dirName === arrow.line.dirName) ?? candidates[0];
|
|
85
|
+
if (edge !== undefined) return { kind: 'migration', edge, lane: arrow.line.lane };
|
|
86
|
+
}
|
|
87
|
+
return { kind: 'none' };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Return the cell's arrow line if it carries one — a self-loop, or a line whose
|
|
92
|
+
* directions are exactly `{up}` or `{down}` (the migration-direction arrows).
|
|
93
|
+
* Connector/corner/vertical lines are not arrows and yield `undefined`.
|
|
94
|
+
*/
|
|
95
|
+
function arrowLine(cell: Cell): CellLine | undefined {
|
|
96
|
+
for (const line of cell.lines) {
|
|
97
|
+
if (line.selfLoop === true) return line;
|
|
98
|
+
if (line.landingArrow === true) continue;
|
|
99
|
+
const dirs = line.directions;
|
|
100
|
+
if (dirs.size !== 1) continue;
|
|
101
|
+
if (dirs.has('up') || dirs.has('down')) return line;
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Node path-highlight resolution (focus mode).
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolve each contract's path-highlight role from the edges incident on it.
|
|
112
|
+
* On-path wins: a contract touched by any on-path edge is on-path. Empty unless
|
|
113
|
+
* focus-mode annotations are present.
|
|
114
|
+
*/
|
|
115
|
+
function resolveNodeHighlights(
|
|
116
|
+
rowModel: MigrationGraphRowModel,
|
|
117
|
+
edgeAnnotationsByHash: ReadonlyMap<string, MigrationEdgeAnnotation> | undefined,
|
|
118
|
+
): Map<string, 'on-path' | 'off-path'> {
|
|
119
|
+
const result = new Map<string, 'on-path' | 'off-path'>();
|
|
120
|
+
if (edgeAnnotationsByHash === undefined) return result;
|
|
121
|
+
for (const edge of rowModel.edges) {
|
|
122
|
+
const highlight = edgeAnnotationsByHash.get(edge.migrationHash)?.pathHighlight;
|
|
123
|
+
if (highlight === undefined) continue;
|
|
124
|
+
for (const hash of [edge.from, edge.to]) {
|
|
125
|
+
if (hash === EMPTY_CONTRACT_HASH) continue;
|
|
126
|
+
if (result.get(hash) !== 'on-path') result.set(hash, highlight);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Width helpers
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
function maxDirNameLength(edges: readonly ClassifiedEdge[]): number {
|
|
137
|
+
let max = 0;
|
|
138
|
+
for (const edge of edges) max = Math.max(max, edge.dirName.length);
|
|
139
|
+
return max;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The label column for a render: the widest gutter (visible width) across every
|
|
144
|
+
* row, plus the label gap. Labels begin here so they line up regardless of how
|
|
145
|
+
* deep the lane structure runs on any one row. A cross-space override widens it
|
|
146
|
+
* so sibling space sections share one column.
|
|
147
|
+
*/
|
|
148
|
+
export function computeLabelColumn(grid: Grid, glyphMode: GlyphMode): number {
|
|
149
|
+
let maxGutter = 0;
|
|
150
|
+
for (const row of grid) {
|
|
151
|
+
const gutter = renderGridRow(row, { colorize: false, glyphMode });
|
|
152
|
+
maxGutter = Math.max(maxGutter, stringWidth(gutter));
|
|
153
|
+
}
|
|
154
|
+
return maxGutter + LABEL_GAP;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function computeMaxDirNameWidth(rowModel: MigrationGraphRowModel): number {
|
|
158
|
+
return maxDirNameLength(rowModel.edges);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function padVisible(text: string, targetWidth: number): string {
|
|
162
|
+
const padding = Math.max(0, targetWidth - stringWidth(text));
|
|
163
|
+
return text + ' '.repeat(padding);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const ANSI_ESCAPE = '\x1b';
|
|
167
|
+
|
|
168
|
+
function trimTrailingWhitespace(line: string): string {
|
|
169
|
+
const trailingSpaceBeforeReset = new RegExp(`[\\t ]+((?:${ANSI_ESCAPE}\\[[0-9;]*m)+)$`);
|
|
170
|
+
return line.replace(trailingSpaceBeforeReset, '$1').replace(/\s+$/, '');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Render
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
export function renderMigrationGraphCommand(input: RenderMigrationGraphCommandInput): string {
|
|
178
|
+
const { grid, rowModel } = input;
|
|
179
|
+
const glyphMode = input.glyphMode;
|
|
180
|
+
|
|
181
|
+
// Edges grouped by hash — a list, not a single entry, because two distinct
|
|
182
|
+
// migrations with identical content collide on one hash. classifyRow then
|
|
183
|
+
// disambiguates by the row's own dirName.
|
|
184
|
+
const edgesByHash = new Map<string, ClassifiedEdge[]>();
|
|
185
|
+
for (const edge of rowModel.edges) {
|
|
186
|
+
const bucket = edgesByHash.get(edge.migrationHash);
|
|
187
|
+
if (bucket) bucket.push(edge);
|
|
188
|
+
else edgesByHash.set(edge.migrationHash, [edge]);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const labelOpts: MigrationGraphLabelOptions = {
|
|
192
|
+
colorize: input.colorize,
|
|
193
|
+
glyphMode,
|
|
194
|
+
...ifDefined('refsByHash', input.refsByHash),
|
|
195
|
+
...ifDefined('edgeAnnotationsByHash', input.edgeAnnotationsByHash),
|
|
196
|
+
...ifDefined('dbHash', input.dbHash),
|
|
197
|
+
...ifDefined('contractHash', input.contractHash),
|
|
198
|
+
...ifDefined('isAppSpace', input.isAppSpace),
|
|
199
|
+
...ifDefined('activeRefName', input.activeRefName),
|
|
200
|
+
...ifDefined('styler', input.styler),
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const nodeHighlights = resolveNodeHighlights(rowModel, input.edgeAnnotationsByHash);
|
|
204
|
+
|
|
205
|
+
const labelColumn = input.globalLabelColumn ?? computeLabelColumn(grid, glyphMode);
|
|
206
|
+
const maxDirNameLen = input.globalMaxDirNameWidth ?? maxDirNameLength(rowModel.edges);
|
|
207
|
+
// The migration-name column is at least wide enough to push the `from → to`
|
|
208
|
+
// hash column to MIN_HASH_DATA_COLUMN, matching the historical layout.
|
|
209
|
+
const dirNameWidth = Math.max(maxDirNameLen + LABEL_GAP, MIN_HASH_DATA_COLUMN - labelColumn);
|
|
210
|
+
|
|
211
|
+
const lines: string[] = [];
|
|
212
|
+
for (const row of grid) {
|
|
213
|
+
const gutter = renderGridRow(row, { colorize: input.colorize, glyphMode });
|
|
214
|
+
const identity = classifyRow(row, edgesByHash);
|
|
215
|
+
|
|
216
|
+
if (identity.kind === 'none') {
|
|
217
|
+
// Connector / pass-through / back-arc rows carry no label. A wholly empty
|
|
218
|
+
// grid row (the blank line between disjoint components) renders as a blank.
|
|
219
|
+
lines.push(trimTrailingWhitespace(gutter));
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const gutterPad = padVisible(gutter, labelColumn);
|
|
224
|
+
if (identity.kind === 'node') {
|
|
225
|
+
const label = formatNodeLabel(
|
|
226
|
+
identity.contractHash,
|
|
227
|
+
labelOpts,
|
|
228
|
+
nodeHighlights.get(identity.contractHash),
|
|
229
|
+
);
|
|
230
|
+
lines.push(trimTrailingWhitespace(label.length === 0 ? gutter : `${gutterPad}${label}`));
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const label = formatMigrationLabel(identity.edge, dirNameWidth, labelOpts, identity.lane);
|
|
235
|
+
lines.push(trimTrailingWhitespace(`${gutterPad}${label}`));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return lines.join('\n');
|
|
239
|
+
}
|