@prisma-next/cli 0.12.0-dev.52 → 0.12.0-dev.54
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/dist/cli.mjs +7 -7
- package/dist/{client-BfNYTr8w.mjs → client-DIcitJdy.mjs} +95 -38
- package/dist/client-DIcitJdy.mjs.map +1 -0
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +2 -2
- package/dist/commands/db-schema.mjs +1 -1
- package/dist/commands/db-sign.mjs +1 -1
- package/dist/commands/db-update.mjs +2 -2
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +35 -1
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +287 -6
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.mjs +2 -2
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +4 -2
- package/dist/commands/migration-graph.mjs.map +1 -1
- package/dist/commands/migration-list.d.mts +1 -0
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +1 -1
- package/dist/commands/migration-log.mjs +1 -1
- package/dist/commands/migration-show.mjs +2 -2
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -2
- package/dist/{contract-infer-sUml0McE.mjs → contract-infer-BAdhYGQH.mjs} +2 -2
- package/dist/{contract-infer-sUml0McE.mjs.map → contract-infer-BAdhYGQH.mjs.map} +1 -1
- package/dist/{db-verify-DSZcaGQs.mjs → db-verify-CiUCDXnv.mjs} +2 -2
- package/dist/{db-verify-DSZcaGQs.mjs.map → db-verify-CiUCDXnv.mjs.map} +1 -1
- package/dist/exports/control-api.mjs +1 -1
- package/dist/{inspect-live-schema-B44OravN.mjs → inspect-live-schema-DegaqKFT.mjs} +2 -2
- package/dist/{inspect-live-schema-B44OravN.mjs.map → inspect-live-schema-DegaqKFT.mjs.map} +1 -1
- package/dist/{migration-check-BxWlQBOs.mjs → migration-check-ldvGvsgM.mjs} +2 -3
- package/dist/{migration-check-BxWlQBOs.mjs.map → migration-check-ldvGvsgM.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-BvVTTjzK.mjs → migration-command-scaffold-D6UeN71F.mjs} +2 -2
- package/dist/{migration-command-scaffold-BvVTTjzK.mjs.map → migration-command-scaffold-D6UeN71F.mjs.map} +1 -1
- package/dist/{migration-graph-space-render-CeNXh_Wy.mjs → migration-graph-space-render-B0HkTNj3.mjs} +488 -84
- package/dist/migration-graph-space-render-B0HkTNj3.mjs.map +1 -0
- package/dist/{migration-list-vJWFuXca.mjs → migration-list-mYmj2j33.mjs} +6 -4
- package/dist/migration-list-mYmj2j33.mjs.map +1 -0
- package/dist/{migration-log-DD01Jm_i.mjs → migration-log-Dzs18GU7.mjs} +3 -3
- package/dist/{migration-log-DD01Jm_i.mjs.map → migration-log-Dzs18GU7.mjs.map} +1 -1
- package/dist/{migration-path-target-UkxkgXnv.mjs → migration-path-target-DK-B7POa.mjs} +1 -1
- package/dist/{migration-path-target-UkxkgXnv.mjs.map → migration-path-target-DK-B7POa.mjs.map} +1 -1
- package/dist/{migration-status-jL5ajRrB.mjs → migration-status-BGKGc0iR.mjs} +7 -5
- package/dist/migration-status-BGKGc0iR.mjs.map +1 -0
- package/dist/{schemas-DJY2O09F.mjs → schemas-B4xeMrNt.mjs} +1 -1
- package/dist/{schemas-DJY2O09F.mjs.map → schemas-B4xeMrNt.mjs.map} +1 -1
- package/package.json +18 -18
- package/src/commands/migrate.ts +512 -2
- package/src/commands/migration-graph.ts +2 -0
- package/src/commands/migration-list.ts +3 -0
- package/src/commands/migration-status.ts +4 -0
- package/src/control-api/operations/migrate.ts +149 -56
- package/src/utils/formatters/migration-graph-layout.ts +187 -42
- package/src/utils/formatters/migration-graph-space-render.ts +11 -1
- package/src/utils/formatters/migration-graph-tree-render.ts +609 -59
- package/src/utils/formatters/migration-list-render.ts +12 -0
- package/src/utils/formatters/migration-list-styler.ts +5 -7
- package/dist/client-BfNYTr8w.mjs.map +0 -1
- package/dist/migration-graph-space-render-CeNXh_Wy.mjs.map +0 -1
- package/dist/migration-list-vJWFuXca.mjs.map +0 -1
- package/dist/migration-status-jL5ajRrB.mjs.map +0 -1
package/dist/{migration-graph-space-render-CeNXh_Wy.mjs → migration-graph-space-render-B0HkTNj3.mjs}
RENAMED
|
@@ -143,9 +143,14 @@ function refineAdjacency(rows, nodeColumn, position, forwardInDegree, forwardOut
|
|
|
143
143
|
if (row.kind !== "edge" || row.edge === void 0 || row.laneIndex === void 0) return row;
|
|
144
144
|
const divergenceBranchEdge = row.edge.kind === "forward" && !(row.convergenceProducer ?? false) && (forwardOutDegree.get(row.edge.from) ?? 0) >= 2 && branchLaneForEdge(row.edge) !== void 0;
|
|
145
145
|
const adjacency = row.convergenceProducer === true && convergenceProducerUsesShortAdjacency(row.edge, row.laneIndex, forwardProducersByTo, producerLaneByHash) ? classifyForwardShortConvergenceAdjacency(rows, rowIndex, row.edge, row.laneIndex) : classifyLayoutAdjacency(rows, rowIndex, row.edge, row.laneIndex, row.passThroughLanes ?? [], nodeColumn, position, forwardInDegree, row.convergenceProducer ?? false, divergenceBranchEdge);
|
|
146
|
+
const existingLaneEdge = /* @__PURE__ */ new Map();
|
|
147
|
+
for (const lane of row.passThroughLanes ?? []) {
|
|
148
|
+
const cell = row.cells[lane];
|
|
149
|
+
if (cell !== void 0 && "migrationHash" in cell && cell.migrationHash !== void 0) existingLaneEdge.set(lane, cell.migrationHash);
|
|
150
|
+
}
|
|
146
151
|
return {
|
|
147
152
|
...row,
|
|
148
|
-
cells: buildEdgeCells(row.edge, row.laneIndex, row.passThroughLanes ?? [], adjacency, row.cells.length)
|
|
153
|
+
cells: buildEdgeCells(row.edge, row.laneIndex, row.passThroughLanes ?? [], adjacency, row.cells.length, existingLaneEdge)
|
|
149
154
|
};
|
|
150
155
|
});
|
|
151
156
|
}
|
|
@@ -164,48 +169,100 @@ function classifyEdgeAdjacency(edge, position) {
|
|
|
164
169
|
function emptyCells(width) {
|
|
165
170
|
return Array.from({ length: width }, () => ({ kind: "empty" }));
|
|
166
171
|
}
|
|
167
|
-
|
|
172
|
+
/** Returns `{ migrationHash: hash }` when hash is defined, otherwise `{}`. */
|
|
173
|
+
function hashProp(hash) {
|
|
174
|
+
return hash !== void 0 ? { migrationHash: hash } : {};
|
|
175
|
+
}
|
|
176
|
+
/** Returns `{ arcMigrationHash: hash }` when hash is defined, otherwise `{}`. */
|
|
177
|
+
function arcHashProp(hash) {
|
|
178
|
+
return hash !== void 0 ? { arcMigrationHash: hash } : {};
|
|
179
|
+
}
|
|
180
|
+
function buildBranchConnectorCells(startLane, endLane, fanTargetLanes, activeLanes, gridWidth, trunkEdgeHash, fanEdgeHashByLane, laneEdgeByIndex) {
|
|
168
181
|
const cells = emptyCells(gridWidth);
|
|
169
182
|
for (let lane = 0; lane < gridWidth; lane++) {
|
|
170
183
|
if (activeLanes.has(lane) && (lane < startLane || lane > endLane)) {
|
|
171
|
-
cells[lane] = {
|
|
184
|
+
cells[lane] = {
|
|
185
|
+
kind: "vertical-pass",
|
|
186
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
187
|
+
};
|
|
172
188
|
continue;
|
|
173
189
|
}
|
|
174
|
-
if (lane === startLane) cells[lane] = {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
else cells[lane] = {
|
|
190
|
+
if (lane === startLane) cells[lane] = {
|
|
191
|
+
kind: "branch-tee",
|
|
192
|
+
...hashProp(trunkEdgeHash)
|
|
193
|
+
};
|
|
194
|
+
else if (lane === endLane) cells[lane] = {
|
|
195
|
+
kind: "branch-corner",
|
|
196
|
+
...hashProp(fanEdgeHashByLane.get(lane))
|
|
197
|
+
};
|
|
198
|
+
else if (lane > startLane && lane < endLane) if (fanTargetLanes.has(lane)) cells[lane] = {
|
|
199
|
+
kind: "branch-tee",
|
|
200
|
+
...hashProp(fanEdgeHashByLane.get(lane))
|
|
201
|
+
};
|
|
202
|
+
else if (activeLanes.has(lane)) cells[lane] = {
|
|
203
|
+
kind: "arc-crossing",
|
|
204
|
+
...hashProp(laneEdgeByIndex.get(lane)),
|
|
205
|
+
...arcHashProp(fanEdgeHashByLane.get(endLane))
|
|
206
|
+
};
|
|
207
|
+
else cells[lane] = {
|
|
208
|
+
kind: "branch-tee",
|
|
209
|
+
...hashProp(fanEdgeHashByLane.get(lane))
|
|
210
|
+
};
|
|
179
211
|
}
|
|
180
212
|
return cells;
|
|
181
213
|
}
|
|
182
|
-
function buildMergeConnectorCells(startLane, endLane, fanTargetLanes, activeLanes, gridWidth) {
|
|
214
|
+
function buildMergeConnectorCells(startLane, endLane, fanTargetLanes, activeLanes, gridWidth, laneEdgeByIndex) {
|
|
183
215
|
const cells = emptyCells(gridWidth);
|
|
184
216
|
for (let lane = 0; lane < gridWidth; lane++) {
|
|
185
217
|
if (activeLanes.has(lane) && (lane < startLane || lane > endLane)) {
|
|
186
|
-
cells[lane] = {
|
|
218
|
+
cells[lane] = {
|
|
219
|
+
kind: "vertical-pass",
|
|
220
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
221
|
+
};
|
|
187
222
|
continue;
|
|
188
223
|
}
|
|
189
|
-
if (lane === startLane) cells[lane] = {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
else cells[lane] = {
|
|
224
|
+
if (lane === startLane) cells[lane] = {
|
|
225
|
+
kind: "merge-tee",
|
|
226
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
227
|
+
};
|
|
228
|
+
else if (lane === endLane) cells[lane] = {
|
|
229
|
+
kind: "merge-corner",
|
|
230
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
231
|
+
};
|
|
232
|
+
else if (lane > startLane && lane < endLane) if (fanTargetLanes.has(lane)) cells[lane] = {
|
|
233
|
+
kind: "merge-tee",
|
|
234
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
235
|
+
};
|
|
236
|
+
else if (activeLanes.has(lane)) cells[lane] = {
|
|
237
|
+
kind: "arc-crossing",
|
|
238
|
+
...hashProp(laneEdgeByIndex.get(lane)),
|
|
239
|
+
...arcHashProp(laneEdgeByIndex.get(endLane))
|
|
240
|
+
};
|
|
241
|
+
else cells[lane] = {
|
|
242
|
+
kind: "horizontal-pass",
|
|
243
|
+
...hashProp(laneEdgeByIndex.get(startLane))
|
|
244
|
+
};
|
|
194
245
|
}
|
|
195
246
|
return cells;
|
|
196
247
|
}
|
|
197
|
-
function buildNodeCells(contractHash, nodeColumn, activeLanes, gridWidth) {
|
|
248
|
+
function buildNodeCells(contractHash, nodeColumn, activeLanes, gridWidth, laneEdgeByIndex) {
|
|
198
249
|
const cells = emptyCells(gridWidth);
|
|
199
|
-
for (const lane of activeLanes) if (lane !== nodeColumn && lane < gridWidth) cells[lane] = {
|
|
250
|
+
for (const lane of activeLanes) if (lane !== nodeColumn && lane < gridWidth) cells[lane] = {
|
|
251
|
+
kind: "vertical-pass",
|
|
252
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
253
|
+
};
|
|
200
254
|
if (nodeColumn < gridWidth) cells[nodeColumn] = {
|
|
201
255
|
kind: "node",
|
|
202
256
|
contractHash
|
|
203
257
|
};
|
|
204
258
|
return cells;
|
|
205
259
|
}
|
|
206
|
-
function buildEdgeCells(edge, laneIndex, passThroughLanes, adjacency, gridWidth) {
|
|
260
|
+
function buildEdgeCells(edge, laneIndex, passThroughLanes, adjacency, gridWidth, laneEdgeByIndex) {
|
|
207
261
|
const cells = emptyCells(gridWidth);
|
|
208
|
-
for (const lane of passThroughLanes) if (lane < gridWidth) cells[lane] = {
|
|
262
|
+
for (const lane of passThroughLanes) if (lane < gridWidth) cells[lane] = {
|
|
263
|
+
kind: "vertical-pass",
|
|
264
|
+
...hashProp(laneEdgeByIndex.get(lane))
|
|
265
|
+
};
|
|
209
266
|
if (laneIndex < gridWidth) cells[laneIndex] = {
|
|
210
267
|
kind: "edge-lane",
|
|
211
268
|
migrationHash: edge.migrationHash,
|
|
@@ -357,6 +414,7 @@ function applySkipRollbackRouting(rows, skipRollbacks, position, nodeColumn, edg
|
|
|
357
414
|
const maxCoSourcedLane = Math.max(...coSourcedLanes);
|
|
358
415
|
const coLandingLanes = routes.filter((other) => other.edge.to === edge.to).map((other) => other.backLane);
|
|
359
416
|
const maxCoLandingLane = Math.max(...coLandingLanes);
|
|
417
|
+
const { migrationHash: arcHash } = edge;
|
|
360
418
|
const sourceRow = result[sourceRowIndex];
|
|
361
419
|
if (sourceRow !== void 0) {
|
|
362
420
|
const cells = sourceRow.cells;
|
|
@@ -368,22 +426,43 @@ function applySkipRollbackRouting(rows, skipRollbacks, position, nodeColumn, edg
|
|
|
368
426
|
};
|
|
369
427
|
for (let lane = nodeCol + 1; lane < backLane; lane += 1) {
|
|
370
428
|
if (coSourcedLanes.includes(lane)) {
|
|
371
|
-
cells[lane] = {
|
|
429
|
+
cells[lane] = {
|
|
430
|
+
kind: "arc-branch-tee",
|
|
431
|
+
...hashProp(routes.find((r) => r.backLane === lane && r.edge.from === edge.from)?.edge.migrationHash)
|
|
432
|
+
};
|
|
372
433
|
continue;
|
|
373
434
|
}
|
|
374
435
|
const existing = cells[lane];
|
|
375
|
-
|
|
436
|
+
if (existing !== void 0 && existing.kind !== "empty" && existing.kind !== "horizontal-pass" && existing.kind !== "arc-land-bridge" || routes.some((other) => other.edge.migrationHash !== arcHash && other.backLane === lane && routeCrossesRow(other, sourceRowIndex, result))) cells[lane] = {
|
|
437
|
+
kind: "arc-crossing",
|
|
438
|
+
...hashProp(existing !== void 0 && "migrationHash" in existing ? existing.migrationHash : void 0),
|
|
439
|
+
arcMigrationHash: arcHash
|
|
440
|
+
};
|
|
441
|
+
else cells[lane] = {
|
|
442
|
+
kind: "horizontal-pass",
|
|
443
|
+
migrationHash: arcHash
|
|
444
|
+
};
|
|
376
445
|
}
|
|
377
|
-
cells[backLane] = backLane < maxCoSourcedLane ? {
|
|
446
|
+
cells[backLane] = backLane < maxCoSourcedLane ? {
|
|
447
|
+
kind: "arc-branch-tee",
|
|
448
|
+
migrationHash: arcHash
|
|
449
|
+
} : {
|
|
450
|
+
kind: "arc-branch-corner",
|
|
451
|
+
migrationHash: arcHash
|
|
452
|
+
};
|
|
378
453
|
}
|
|
379
454
|
const edgeRow = result[edgeRowIndex];
|
|
380
455
|
if (edgeRow !== void 0) {
|
|
381
456
|
const cells = edgeRow.cells;
|
|
382
457
|
ensureCellWidth(cells, backLane + 1);
|
|
383
|
-
cells[nodeCol]
|
|
458
|
+
const forwardLaneCell = cells[nodeCol];
|
|
459
|
+
cells[nodeCol] = {
|
|
460
|
+
kind: "vertical-pass",
|
|
461
|
+
...hashProp(forwardLaneCell !== void 0 && "migrationHash" in forwardLaneCell ? forwardLaneCell.migrationHash : void 0)
|
|
462
|
+
};
|
|
384
463
|
cells[backLane] = {
|
|
385
464
|
kind: "edge-lane",
|
|
386
|
-
migrationHash:
|
|
465
|
+
migrationHash: arcHash,
|
|
387
466
|
edgeKind: edge.kind,
|
|
388
467
|
ownsLabel: true,
|
|
389
468
|
adjacency: "node-skipping-rollback"
|
|
@@ -401,7 +480,10 @@ function applySkipRollbackRouting(rows, skipRollbacks, position, nodeColumn, edg
|
|
|
401
480
|
const cells = row.cells;
|
|
402
481
|
ensureCellWidth(cells, backLane + 1);
|
|
403
482
|
const existing = cells[backLane];
|
|
404
|
-
if (existing?.kind !== "arc-land-corner" && existing?.kind !== "arc-land-tee" && existing?.kind !== "arc-land-bridge" && existing?.kind !== "arc-branch-corner" && existing?.kind !== "arc-branch-tee" && existing?.kind !== "arc-crossing") cells[backLane] = {
|
|
483
|
+
if (existing?.kind !== "arc-land-corner" && existing?.kind !== "arc-land-tee" && existing?.kind !== "arc-land-bridge" && existing?.kind !== "arc-branch-corner" && existing?.kind !== "arc-branch-tee" && existing?.kind !== "arc-crossing") cells[backLane] = {
|
|
484
|
+
kind: "vertical-pass",
|
|
485
|
+
migrationHash: arcHash
|
|
486
|
+
};
|
|
405
487
|
}
|
|
406
488
|
const targetRow = result[targetRowIndex];
|
|
407
489
|
if (targetRow !== void 0) {
|
|
@@ -414,19 +496,39 @@ function applySkipRollbackRouting(rows, skipRollbacks, position, nodeColumn, edg
|
|
|
414
496
|
};
|
|
415
497
|
for (let lane = targetCol + 1; lane < backLane; lane += 1) {
|
|
416
498
|
if (coLandingLanes.includes(lane)) {
|
|
417
|
-
cells[lane] = {
|
|
499
|
+
cells[lane] = {
|
|
500
|
+
kind: "arc-land-tee",
|
|
501
|
+
...hashProp(routes.find((r) => r.backLane === lane && r.edge.to === edge.to)?.edge.migrationHash)
|
|
502
|
+
};
|
|
418
503
|
continue;
|
|
419
504
|
}
|
|
420
505
|
const existing = cells[lane];
|
|
421
|
-
|
|
506
|
+
if (existing !== void 0 && existing.kind !== "empty" && existing.kind !== "horizontal-pass" && existing.kind !== "arc-land-bridge" && existing.kind !== "arc-land-tee" || routes.some((other) => other.edge.migrationHash !== arcHash && other.backLane === lane && routeCrossesRow(other, targetRowIndex, result))) cells[lane] = {
|
|
507
|
+
kind: "arc-crossing",
|
|
508
|
+
...hashProp(existing !== void 0 && "migrationHash" in existing ? existing.migrationHash : void 0),
|
|
509
|
+
arcMigrationHash: arcHash
|
|
510
|
+
};
|
|
511
|
+
else cells[lane] = {
|
|
512
|
+
kind: "arc-land-bridge",
|
|
513
|
+
migrationHash: arcHash
|
|
514
|
+
};
|
|
422
515
|
}
|
|
423
|
-
cells[backLane] = backLane < maxCoLandingLane ? {
|
|
516
|
+
cells[backLane] = backLane < maxCoLandingLane ? {
|
|
517
|
+
kind: "arc-land-tee",
|
|
518
|
+
migrationHash: arcHash
|
|
519
|
+
} : {
|
|
520
|
+
kind: "arc-land-corner",
|
|
521
|
+
migrationHash: arcHash
|
|
522
|
+
};
|
|
424
523
|
for (const other of routes) {
|
|
425
524
|
if (other.backLane <= backLane) continue;
|
|
426
525
|
if (!routeCrossesRow(other, targetRowIndex, result)) continue;
|
|
427
526
|
ensureCellWidth(cells, other.backLane + 1);
|
|
428
527
|
const existing = cells[other.backLane];
|
|
429
|
-
if (existing?.kind !== "arc-land-corner" && existing?.kind !== "arc-land-tee" && existing?.kind !== "arc-land-bridge" && existing?.kind !== "node") cells[other.backLane] = {
|
|
528
|
+
if (existing?.kind !== "arc-land-corner" && existing?.kind !== "arc-land-tee" && existing?.kind !== "arc-land-bridge" && existing?.kind !== "node") cells[other.backLane] = {
|
|
529
|
+
kind: "vertical-pass",
|
|
530
|
+
migrationHash: other.edge.migrationHash
|
|
531
|
+
};
|
|
430
532
|
}
|
|
431
533
|
}
|
|
432
534
|
}
|
|
@@ -476,6 +578,7 @@ function layoutComponent(componentNodes, allEdges) {
|
|
|
476
578
|
const nodeColumn = /* @__PURE__ */ new Map();
|
|
477
579
|
const edgeColumn = /* @__PURE__ */ new Map();
|
|
478
580
|
const producerLaneByHash = /* @__PURE__ */ new Map();
|
|
581
|
+
const laneEdgeByIndex = /* @__PURE__ */ new Map();
|
|
479
582
|
let gridWidth = 1;
|
|
480
583
|
function ensureGridWidth(minWidth) {
|
|
481
584
|
if (minWidth > gridWidth) gridWidth = minWidth;
|
|
@@ -514,21 +617,22 @@ function layoutComponent(componentNodes, allEdges) {
|
|
|
514
617
|
startLane,
|
|
515
618
|
endLane,
|
|
516
619
|
branchCount: laneIndices.length,
|
|
517
|
-
cells: buildMergeConnectorCells(startLane, endLane, fanTargetLanes, activeLanes, gridWidth)
|
|
620
|
+
cells: buildMergeConnectorCells(startLane, endLane, fanTargetLanes, activeLanes, gridWidth, laneEdgeByIndex)
|
|
518
621
|
});
|
|
519
622
|
for (const index of laneIndices) if (index !== startLane) setLane(index, null);
|
|
520
623
|
return startLane;
|
|
521
624
|
}
|
|
522
|
-
function emitBranchConnector(contractHash, startLane, endLane, branchCount, fanTargetLanes) {
|
|
625
|
+
function emitBranchConnector(contractHash, startLane, endLane, branchCount, fanTargetLanes, fanEdgeHashByLane) {
|
|
523
626
|
ensureGridWidth(endLane + 1);
|
|
524
627
|
const activeLanes = new Set(activeLaneIndices());
|
|
628
|
+
const trunkEdgeHash = fanEdgeHashByLane.get(startLane) ?? laneEdgeByIndex.get(startLane);
|
|
525
629
|
rows.push({
|
|
526
630
|
kind: "branch-connector",
|
|
527
631
|
contractHash,
|
|
528
632
|
startLane,
|
|
529
633
|
endLane,
|
|
530
634
|
branchCount,
|
|
531
|
-
cells: buildBranchConnectorCells(startLane, endLane, new Set(fanTargetLanes), activeLanes, gridWidth)
|
|
635
|
+
cells: buildBranchConnectorCells(startLane, endLane, new Set(fanTargetLanes), activeLanes, gridWidth, trunkEdgeHash, fanEdgeHashByLane, laneEdgeByIndex)
|
|
532
636
|
});
|
|
533
637
|
}
|
|
534
638
|
function emitEdgeRow(edge, lane, convergenceProducer) {
|
|
@@ -540,7 +644,7 @@ function layoutComponent(componentNodes, allEdges) {
|
|
|
540
644
|
edge,
|
|
541
645
|
laneIndex: lane,
|
|
542
646
|
passThroughLanes: passThrough,
|
|
543
|
-
cells: buildEdgeCells(edge, lane, passThrough, adjacency, gridWidth)
|
|
647
|
+
cells: buildEdgeCells(edge, lane, passThrough, adjacency, gridWidth, laneEdgeByIndex)
|
|
544
648
|
};
|
|
545
649
|
rows.push(convergenceProducer ? {
|
|
546
650
|
...row,
|
|
@@ -548,6 +652,7 @@ function layoutComponent(componentNodes, allEdges) {
|
|
|
548
652
|
} : row);
|
|
549
653
|
edgeColumn.set(edge.migrationHash, lane);
|
|
550
654
|
if (convergenceProducer) producerLaneByHash.set(edge.migrationHash, lane);
|
|
655
|
+
laneEdgeByIndex.set(lane, edge.migrationHash);
|
|
551
656
|
}
|
|
552
657
|
function emitNodeRow(contractHash, column) {
|
|
553
658
|
ensureGridWidth(column + 1);
|
|
@@ -555,7 +660,7 @@ function layoutComponent(componentNodes, allEdges) {
|
|
|
555
660
|
rows.push({
|
|
556
661
|
kind: "node",
|
|
557
662
|
contractHash,
|
|
558
|
-
cells: buildNodeCells(contractHash, column, passThrough, gridWidth)
|
|
663
|
+
cells: buildNodeCells(contractHash, column, passThrough, gridWidth, laneEdgeByIndex)
|
|
559
664
|
});
|
|
560
665
|
nodeColumn.set(contractHash, column);
|
|
561
666
|
}
|
|
@@ -601,7 +706,21 @@ function layoutComponent(componentNodes, allEdges) {
|
|
|
601
706
|
}
|
|
602
707
|
if (groups.length >= 2) {
|
|
603
708
|
const endLane = Math.max(...laneForGroup);
|
|
604
|
-
|
|
709
|
+
const fanEdgeHashByLane = /* @__PURE__ */ new Map();
|
|
710
|
+
for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
|
711
|
+
const group = groups[groupIndex];
|
|
712
|
+
const lane = laneForGroup[groupIndex];
|
|
713
|
+
if (group === void 0 || lane === void 0) continue;
|
|
714
|
+
const firstEdge = group.edges[0];
|
|
715
|
+
if (firstEdge !== void 0) fanEdgeHashByLane.set(lane, firstEdge.migrationHash);
|
|
716
|
+
}
|
|
717
|
+
emitBranchConnector(node, column, endLane, groups.length, laneForGroup, fanEdgeHashByLane);
|
|
718
|
+
for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
|
719
|
+
const fanLane = laneForGroup[groupIndex];
|
|
720
|
+
if (fanLane === void 0) continue;
|
|
721
|
+
const fanHash = fanEdgeHashByLane.get(fanLane);
|
|
722
|
+
if (fanHash !== void 0) laneEdgeByIndex.set(fanLane, fanHash);
|
|
723
|
+
}
|
|
605
724
|
}
|
|
606
725
|
for (let groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
|
607
726
|
const group = groups[groupIndex];
|
|
@@ -1349,20 +1468,23 @@ function buildRefsByHashFromListEntries(entries) {
|
|
|
1349
1468
|
function formatEmptyStateLine(spaceId, style) {
|
|
1350
1469
|
return style.emptyState(`There are no migrations in migrations/${spaceId}/ yet`);
|
|
1351
1470
|
}
|
|
1352
|
-
function renderSpaceTreeBlock(spaceId, migrations, multiSpace, glyphMode, style, colorize, liveContractHash, graphForSpace, globalMaxEdgeTreePrefixWidth, globalMaxDirNameWidth) {
|
|
1471
|
+
function renderSpaceTreeBlock(spaceId, migrations, multiSpace, glyphMode, style, colorize, liveContractHash, graphForSpace, appSpaceId, globalMaxEdgeTreePrefixWidth, globalMaxDirNameWidth) {
|
|
1353
1472
|
if (migrations.length === 0) {
|
|
1354
1473
|
const emptyLine = formatEmptyStateLine(spaceId, style);
|
|
1355
1474
|
if (!multiSpace) return [emptyLine];
|
|
1356
1475
|
return [style.spaceHeading(`${spaceId}:`), ` ${emptyLine}`];
|
|
1357
1476
|
}
|
|
1477
|
+
const graph = graphForSpace(spaceId) ?? migrationGraphFromListEntries(migrations);
|
|
1478
|
+
const isAppSpace = appSpaceId === void 0 ? void 0 : spaceId === appSpaceId;
|
|
1358
1479
|
const treeOutput = renderMigrationGraphSpaceTree({
|
|
1359
|
-
graph
|
|
1480
|
+
graph,
|
|
1360
1481
|
migrations,
|
|
1361
1482
|
liveContractHash,
|
|
1362
1483
|
glyphMode,
|
|
1363
1484
|
colorize,
|
|
1364
1485
|
refsByHash: buildRefsByHashFromListEntries(migrations),
|
|
1365
1486
|
styler: style,
|
|
1487
|
+
...isAppSpace !== void 0 ? { isAppSpace } : {},
|
|
1366
1488
|
...globalMaxEdgeTreePrefixWidth !== void 0 ? { globalMaxEdgeTreePrefixWidth } : {},
|
|
1367
1489
|
...globalMaxDirNameWidth !== void 0 ? { globalMaxDirNameWidth } : {}
|
|
1368
1490
|
});
|
|
@@ -1383,6 +1505,7 @@ function renderMigrationListWithStyle(result, style, glyphMode = "unicode", opti
|
|
|
1383
1505
|
const colorize = options.colorize ?? false;
|
|
1384
1506
|
const liveContractHash = options.liveContractHash ?? EMPTY_CONTRACT_HASH;
|
|
1385
1507
|
const graphForSpace = options.graphForSpace ?? (() => void 0);
|
|
1508
|
+
const appSpaceId = options.appSpaceId;
|
|
1386
1509
|
const globalLayoutInputs = multiSpace ? result.spaces.filter((space) => space.migrations.length > 0).map((space) => ({
|
|
1387
1510
|
graph: graphForSpace(space.space) ?? migrationGraphFromListEntries(space.migrations),
|
|
1388
1511
|
liveContractHash
|
|
@@ -1393,7 +1516,7 @@ function renderMigrationListWithStyle(result, style, glyphMode = "unicode", opti
|
|
|
1393
1516
|
for (let index = 0; index < result.spaces.length; index++) {
|
|
1394
1517
|
const space = result.spaces[index];
|
|
1395
1518
|
if (index > 0) lines.push("");
|
|
1396
|
-
lines.push(...renderSpaceTreeBlock(space.space, space.migrations, multiSpace, glyphMode, style, colorize, liveContractHash, graphForSpace, globalMaxEdgeTreePrefixWidth, globalMaxDirNameWidth));
|
|
1519
|
+
lines.push(...renderSpaceTreeBlock(space.space, space.migrations, multiSpace, glyphMode, style, colorize, liveContractHash, graphForSpace, appSpaceId, globalMaxEdgeTreePrefixWidth, globalMaxDirNameWidth));
|
|
1397
1520
|
}
|
|
1398
1521
|
if (result.spaces.reduce((count, space) => count + space.migrations.length, 0) > 0) {
|
|
1399
1522
|
lines.push("");
|
|
@@ -1410,7 +1533,7 @@ function styleMarkerName(name) {
|
|
|
1410
1533
|
return name === "contract" ? bold(green(name)) : green(name);
|
|
1411
1534
|
}
|
|
1412
1535
|
function plainMarkers(names) {
|
|
1413
|
-
return
|
|
1536
|
+
return names.map((name) => `@${name}`).join(" ");
|
|
1414
1537
|
}
|
|
1415
1538
|
function formatContractNodeOverlays(styler, markers, refs) {
|
|
1416
1539
|
const parts = [];
|
|
@@ -1444,8 +1567,8 @@ function styleRefName(name) {
|
|
|
1444
1567
|
* - `glyph` (`→` / `⟲` / `∅`): dim
|
|
1445
1568
|
* - `lane` (graph gutter lines `│` and fan/join connectors `├─┐` / `├─┘`): dim
|
|
1446
1569
|
* - `invariants` (`{...}`): yellow
|
|
1447
|
-
* - `markers` (
|
|
1448
|
-
* green-bold (`db` is plain green)
|
|
1570
|
+
* - `markers` (`@contract @db`): green; the `contract` desired-state marker is
|
|
1571
|
+
* green-bold (`db` is plain green); the `@` sigil is applied to each name
|
|
1449
1572
|
* - `refs` (`(...)`): green (the active ref is bolded separately by the tree styler)
|
|
1450
1573
|
* - `spaceHeading` (`<spaceId>:`): bold
|
|
1451
1574
|
* - `summary`: dim
|
|
@@ -1465,10 +1588,8 @@ function createAnsiMigrationListStyler(opts) {
|
|
|
1465
1588
|
lane: (text) => dim(text),
|
|
1466
1589
|
invariants: (ids) => yellow(`{${ids.join(", ")}}`),
|
|
1467
1590
|
markers: (names) => {
|
|
1468
|
-
const
|
|
1469
|
-
|
|
1470
|
-
const separator = green(", ");
|
|
1471
|
-
return open + names.map(styleMarkerName).join(separator) + close;
|
|
1591
|
+
const sigil = green("@");
|
|
1592
|
+
return names.map((name) => sigil + styleMarkerName(name)).join(" ");
|
|
1472
1593
|
},
|
|
1473
1594
|
refs: (names) => {
|
|
1474
1595
|
const open = green("(");
|
|
@@ -1560,12 +1681,71 @@ function arrowForEdgeKind(kind, palette) {
|
|
|
1560
1681
|
return palette.edgeArrow[kind];
|
|
1561
1682
|
}
|
|
1562
1683
|
/**
|
|
1563
|
-
* Forced
|
|
1564
|
-
* (
|
|
1565
|
-
*
|
|
1566
|
-
*
|
|
1684
|
+
* Forced-color functions that always emit ANSI regardless of the ambient TTY
|
|
1685
|
+
* environment (NO_COLOR, piped output). Used for:
|
|
1686
|
+
*
|
|
1687
|
+
* - `forcedBold`: branch-coloured migration names pair their lane hue with bold;
|
|
1688
|
+
* both must emit so the name is deterministically bold + hue.
|
|
1689
|
+
* - `forcedDim`: off-path path-highlight override (migrate --show).
|
|
1690
|
+
* The renderer gates this behind `opts.colorize`; the forced variant ensures
|
|
1691
|
+
* ANSI is emitted in controlled environments (e.g. tests with `NO_COLOR=1`)
|
|
1692
|
+
* when the caller explicitly requests colour. Without forcing, `dim()` from
|
|
1693
|
+
* the ambient module-level import no-ops under NO_COLOR, making the
|
|
1694
|
+
* path-highlight unreachable in tests.
|
|
1567
1695
|
*/
|
|
1568
|
-
const { bold: forcedBold } = createColors({ useColor: true });
|
|
1696
|
+
const { bold: forcedBold, dim: forcedDim, greenBright: forcedGreen } = createColors({ useColor: true });
|
|
1697
|
+
/**
|
|
1698
|
+
* The two styles used in `migrate --show` path-highlight mode.
|
|
1699
|
+
*
|
|
1700
|
+
* In path-highlight mode the normal by-branch rotating-colour logic
|
|
1701
|
+
* (`LANE_COLOR_CYCLE` / `laneStylerForColumn`) is suppressed entirely.
|
|
1702
|
+
* Every glyph, name, and hash is styled by its on-path / off-path role,
|
|
1703
|
+
* never by lane column index.
|
|
1704
|
+
*
|
|
1705
|
+
* - `onPath`: neutral single-path style — exactly how a linear (no-branch)
|
|
1706
|
+
* section renders today. Lane glyphs are dim, names are bold, hashes use
|
|
1707
|
+
* the default `sourceHash`/`destHash` colours. No rotation hue is applied.
|
|
1708
|
+
* This is identical to how the pgvector single-path section renders.
|
|
1709
|
+
* - `offPath`: uniform dim grey on every cell (name, hashes, lane glyphs,
|
|
1710
|
+
* direction arrows).
|
|
1711
|
+
*
|
|
1712
|
+
* To change the on-path or off-path colour in future, edit this object only.
|
|
1713
|
+
*/
|
|
1714
|
+
const PATH_HIGHLIGHT_STYLES = {
|
|
1715
|
+
/**
|
|
1716
|
+
* Lane/glyph/arrow stylers for on-path cells.
|
|
1717
|
+
*
|
|
1718
|
+
* - lane: `forcedGreen` when colour is on — bright green so the on-path
|
|
1719
|
+
* branch glyphs (`│ ├ ╯ ↑`) and node markers (`○`/`∅`) are visually
|
|
1720
|
+
* distinct from off-path (dim grey). Uses forced ANSI so it survives
|
|
1721
|
+
* NO_COLOR in tests. Identity when `colorize` is false.
|
|
1722
|
+
* - arrow: identity (plain, no colouring)
|
|
1723
|
+
* - dirName: `bold` (ambient bold — name stays white/bold, not green)
|
|
1724
|
+
* - hashOverride: undefined — `style.sourceHash`/`style.destHash` apply
|
|
1725
|
+
* normally (cyan) so hashes keep their existing neutral colour.
|
|
1726
|
+
*
|
|
1727
|
+
* `style` is the same `MigrationListStyler` the tree renderer uses.
|
|
1728
|
+
* Rotation (`LANE_COLOR_CYCLE`) is never applied to on-path cells.
|
|
1729
|
+
*/
|
|
1730
|
+
onPath: (_style, colorize) => ({
|
|
1731
|
+
lane: colorize ? forcedGreen : (text) => text,
|
|
1732
|
+
arrow: (text) => text,
|
|
1733
|
+
dirName: (text) => bold(text),
|
|
1734
|
+
hashOverride: void 0
|
|
1735
|
+
}),
|
|
1736
|
+
/**
|
|
1737
|
+
* Lane/glyph/arrow/hash stylers for off-path cells.
|
|
1738
|
+
* Uniform dim grey on everything — uses `forcedDim` so ANSI is emitted even
|
|
1739
|
+
* under NO_COLOR (test environments use `colorize:true` + NO_COLOR=1 to verify dim).
|
|
1740
|
+
* Returns identity functions when colour is off (`colorize: false`).
|
|
1741
|
+
*/
|
|
1742
|
+
offPath: (colorize) => ({
|
|
1743
|
+
lane: colorize ? forcedDim : (text) => text,
|
|
1744
|
+
arrow: colorize ? forcedDim : (text) => text,
|
|
1745
|
+
dirName: colorize ? forcedDim : (text) => text,
|
|
1746
|
+
hashOverride: colorize ? forcedDim : void 0
|
|
1747
|
+
})
|
|
1748
|
+
};
|
|
1569
1749
|
function laneStylerForColumn(colorColumn, colorize, style) {
|
|
1570
1750
|
return stylerForLaneColumn(colorColumn, colorize, style.lane);
|
|
1571
1751
|
}
|
|
@@ -1605,24 +1785,30 @@ function renderConnectorTee(pair, glyphColumn, dashColumn, colorize, style) {
|
|
|
1605
1785
|
* marker takes its own lane's hue (so each node visibly belongs to its branch);
|
|
1606
1786
|
* the connector follows the arc it belongs to (its owning back-lane hue).
|
|
1607
1787
|
* Direction arrows are handled elsewhere — they take their edge's lane hue too.
|
|
1788
|
+
*
|
|
1789
|
+
* When `laneOverride` is provided (for path-highlight rows), it replaces the
|
|
1790
|
+
* marker styler. `arcLaneOverride` (if provided) replaces the connector styler
|
|
1791
|
+
* independently — this matters when the node is on-path but the arc belongs to
|
|
1792
|
+
* an off-path rollback edge, which must render dim rather than green.
|
|
1608
1793
|
*/
|
|
1609
|
-
function renderNodeMarkerPair(pair, nodeColumn, arcColumn, colorize, style) {
|
|
1610
|
-
const marker = laneStylerForColumn(nodeColumn, colorize, style);
|
|
1611
|
-
const connector = laneStylerForColumn(arcColumn, colorize, style);
|
|
1794
|
+
function renderNodeMarkerPair(pair, nodeColumn, arcColumn, colorize, style, laneOverride, arcLaneOverride) {
|
|
1795
|
+
const marker = laneOverride ?? laneStylerForColumn(nodeColumn, colorize, style);
|
|
1796
|
+
const connector = arcLaneOverride ?? laneOverride ?? laneStylerForColumn(arcColumn, colorize, style);
|
|
1612
1797
|
return marker(pair.slice(0, 1)) + connector(pair.slice(1));
|
|
1613
1798
|
}
|
|
1614
|
-
function renderCellPair(cell, column, colors, colorize, style, palette) {
|
|
1799
|
+
function renderCellPair(cell, column, colors, colorize, style, palette, laneOverride, arrowOverride, arcLaneOverride) {
|
|
1615
1800
|
const laneColumn = colors.lane[column] ?? column;
|
|
1616
|
-
const lane = laneStylerForColumn(laneColumn, colorize, style);
|
|
1801
|
+
const lane = laneOverride ?? laneStylerForColumn(laneColumn, colorize, style);
|
|
1802
|
+
const arrow = arrowOverride ?? ((text) => branchStylerOrDefault(column, colorize, style.kind)(text));
|
|
1617
1803
|
switch (cell.kind) {
|
|
1618
1804
|
case "node": {
|
|
1619
1805
|
const arcColumn = colors.connector[column] ?? 0;
|
|
1620
|
-
if (cell.arcLand === true) return renderNodeMarkerPair(palette.arcLand, column, arcColumn, colorize, style);
|
|
1621
|
-
if (cell.arcTee === true) return renderNodeMarkerPair(palette.arcTee, column, arcColumn, colorize, style);
|
|
1806
|
+
if (cell.arcLand === true) return renderNodeMarkerPair(palette.arcLand, column, arcColumn, colorize, style, laneOverride, arcLaneOverride);
|
|
1807
|
+
if (cell.arcTee === true) return renderNodeMarkerPair(palette.arcTee, column, arcColumn, colorize, style, laneOverride, arcLaneOverride);
|
|
1622
1808
|
return lane(palette.node);
|
|
1623
1809
|
}
|
|
1624
1810
|
case "vertical-pass": return lane(palette.verticalPass);
|
|
1625
|
-
case "edge-lane": return cell.ownsLabel ? lane(palette.verticalPass.trimEnd()) +
|
|
1811
|
+
case "edge-lane": return cell.ownsLabel ? lane(palette.verticalPass.trimEnd()) + arrow(arrowForEdgeKind(cell.edgeKind, palette)) : lane(palette.verticalPass);
|
|
1626
1812
|
case "branch-tee": return lane(palette.branchTee);
|
|
1627
1813
|
case "merge-tee": return lane(palette.mergeTee);
|
|
1628
1814
|
case "branch-corner": return lane(palette.branchCorner);
|
|
@@ -1630,14 +1816,26 @@ function renderCellPair(cell, column, colors, colorize, style, palette) {
|
|
|
1630
1816
|
case "arc-branch-corner": return lane(palette.arcBranchCorner);
|
|
1631
1817
|
case "arc-branch-tee": return lane(palette.arcBranchTee);
|
|
1632
1818
|
case "arc-land-corner": return lane(palette.arcLandCorner);
|
|
1633
|
-
case "arc-land-tee": return renderConnectorTee(palette.arcLandTee, laneColumn, colors.dash[column] ?? laneColumn, colorize, style);
|
|
1819
|
+
case "arc-land-tee": return laneOverride !== void 0 ? laneOverride(palette.arcLandTee) : renderConnectorTee(palette.arcLandTee, laneColumn, colors.dash[column] ?? laneColumn, colorize, style);
|
|
1634
1820
|
case "arc-crossing": return lane(palette.arcLandBridge);
|
|
1635
1821
|
case "arc-land-bridge": return lane(palette.arcLandBridge);
|
|
1636
1822
|
case "horizontal-pass": return lane(palette.horizontalPass);
|
|
1637
1823
|
case "empty": return " ";
|
|
1638
1824
|
}
|
|
1639
1825
|
}
|
|
1640
|
-
|
|
1826
|
+
/**
|
|
1827
|
+
* Render a branch-connector or merge-connector row.
|
|
1828
|
+
*
|
|
1829
|
+
* `columnLaneOverride` is an optional per-column map populated when path-highlight
|
|
1830
|
+
* annotations are active (`migrate --show`). For each column in the connector's
|
|
1831
|
+
* lane range, the map supplies the override styler (dim for off-path) that should
|
|
1832
|
+
* replace the normal rotating-lane colour for that column. Columns absent from the
|
|
1833
|
+
* map (on-path or unannotated) use the standard `laneStylerForColumn` logic unchanged.
|
|
1834
|
+
* This ensures off-path branch connectors appear dim rather than in their rotation
|
|
1835
|
+
* colour (e.g. magenta).
|
|
1836
|
+
*/
|
|
1837
|
+
function renderConnectorRow(row, gridWidth, colorize, style, palette, columnLaneOverride) {
|
|
1838
|
+
const resolvedLane = (column) => columnLaneOverride?.get(column) ?? laneStylerForColumn(column, colorize, style);
|
|
1641
1839
|
const isMerge = row.kind === "merge-connector";
|
|
1642
1840
|
if (row.cells.length > 0) {
|
|
1643
1841
|
const colors = resolveConnectorLaneColors(row.cells, row.startLane ?? 0);
|
|
@@ -1648,6 +1846,43 @@ function renderConnectorRow(row, gridWidth, colorize, style, palette) {
|
|
|
1648
1846
|
if (cell === void 0) continue;
|
|
1649
1847
|
const glyphColumn = colors.glyph[column] ?? column;
|
|
1650
1848
|
const dashColumn = colors.dash[column] ?? glyphColumn;
|
|
1849
|
+
const override = columnLaneOverride?.get(glyphColumn);
|
|
1850
|
+
const dashOverrideForPathHighlight = columnLaneOverride?.get(dashColumn) ?? override;
|
|
1851
|
+
if (override !== void 0 || columnLaneOverride !== void 0 && dashOverrideForPathHighlight !== void 0) {
|
|
1852
|
+
const effectiveOverride = override ?? dashOverrideForPathHighlight;
|
|
1853
|
+
if (effectiveOverride === void 0) {
|
|
1854
|
+
out += " ";
|
|
1855
|
+
continue;
|
|
1856
|
+
}
|
|
1857
|
+
switch (cell.kind) {
|
|
1858
|
+
case "branch-tee":
|
|
1859
|
+
case "merge-tee": {
|
|
1860
|
+
const pair = seenTee ? palette.connectorBranchTeeCo : palette.connectorBranchTee;
|
|
1861
|
+
out += effectiveOverride(pair.slice(0, 1)) + effectiveOverride(pair.slice(1));
|
|
1862
|
+
seenTee = true;
|
|
1863
|
+
break;
|
|
1864
|
+
}
|
|
1865
|
+
case "branch-corner":
|
|
1866
|
+
out += effectiveOverride(palette.branchCorner);
|
|
1867
|
+
break;
|
|
1868
|
+
case "merge-corner":
|
|
1869
|
+
out += effectiveOverride(palette.mergeCorner);
|
|
1870
|
+
break;
|
|
1871
|
+
case "vertical-pass":
|
|
1872
|
+
out += effectiveOverride(palette.verticalPass);
|
|
1873
|
+
break;
|
|
1874
|
+
case "horizontal-pass":
|
|
1875
|
+
out += effectiveOverride(palette.horizontalPass);
|
|
1876
|
+
break;
|
|
1877
|
+
case "arc-crossing": {
|
|
1878
|
+
const arcCrossingDashOverride = columnLaneOverride?.get(dashColumn) ?? effectiveOverride;
|
|
1879
|
+
out += effectiveOverride(palette.arcCrossing.slice(0, 1)) + arcCrossingDashOverride(palette.arcCrossing.slice(1));
|
|
1880
|
+
break;
|
|
1881
|
+
}
|
|
1882
|
+
default: out += " ";
|
|
1883
|
+
}
|
|
1884
|
+
continue;
|
|
1885
|
+
}
|
|
1651
1886
|
const lane = laneStylerForColumn(glyphColumn, colorize, style);
|
|
1652
1887
|
switch (cell.kind) {
|
|
1653
1888
|
case "branch-tee":
|
|
@@ -1681,7 +1916,7 @@ function renderConnectorRow(row, gridWidth, colorize, style, palette) {
|
|
|
1681
1916
|
}
|
|
1682
1917
|
const start = row.startLane ?? 0;
|
|
1683
1918
|
const end = row.endLane ?? start;
|
|
1684
|
-
const runLane =
|
|
1919
|
+
const runLane = resolvedLane(end);
|
|
1685
1920
|
let out = "";
|
|
1686
1921
|
for (let column = 0; column < gridWidth; column++) if (column < start || column > end) out += " ";
|
|
1687
1922
|
else if (column === start) out += runLane(palette.connectorBranchTee);
|
|
@@ -1699,7 +1934,7 @@ function overlayNamesForContract(contractHash, opts) {
|
|
|
1699
1934
|
const refs = [];
|
|
1700
1935
|
const userRefs = opts.refsByHash?.get(contractHash);
|
|
1701
1936
|
if (userRefs) refs.push(...[...userRefs].sort((a, b) => a.localeCompare(b)));
|
|
1702
|
-
if (opts.contractHash === contractHash && contractHash !== EMPTY_CONTRACT_HASH) markers.push(CONTRACT_MARKER_NAME);
|
|
1937
|
+
if (opts.isAppSpace !== false && opts.contractHash === contractHash && contractHash !== EMPTY_CONTRACT_HASH) markers.push(CONTRACT_MARKER_NAME);
|
|
1703
1938
|
if (opts.dbHash === contractHash) markers.push(DB_MARKER_NAME);
|
|
1704
1939
|
markers.sort((a, b) => {
|
|
1705
1940
|
if (a === "contract") return -1;
|
|
@@ -1726,6 +1961,7 @@ function createTreeStyler(opts) {
|
|
|
1726
1961
|
function formatEdgeAnnotationSuffix(migrationHash, opts, style) {
|
|
1727
1962
|
const annotation = opts.edgeAnnotationsByHash?.get(migrationHash);
|
|
1728
1963
|
if (annotation === void 0) return "";
|
|
1964
|
+
const isOffPath = annotation.pathHighlight === "off-path";
|
|
1729
1965
|
const segments = [];
|
|
1730
1966
|
if (annotation.operationCount !== void 0) segments.push(`${annotation.operationCount} ops`);
|
|
1731
1967
|
if (annotation.invariants !== void 0 && annotation.invariants.length > 0) segments.push(style.invariants(annotation.invariants));
|
|
@@ -1740,15 +1976,31 @@ function formatEdgeAnnotationSuffix(migrationHash, opts, style) {
|
|
|
1740
1976
|
segments.push(styler(`${glyph} ${label}`));
|
|
1741
1977
|
}
|
|
1742
1978
|
}
|
|
1979
|
+
if (annotation.pathHighlight === "on-path") {
|
|
1980
|
+
const glyph = opts.glyphMode === "ascii" ? ">" : "↑";
|
|
1981
|
+
segments.push(`${glyph} will run`);
|
|
1982
|
+
}
|
|
1743
1983
|
if (segments.length === 0) return "";
|
|
1744
|
-
|
|
1984
|
+
const suffix = ` ${segments.join(" ")}`;
|
|
1985
|
+
return opts.colorize && isOffPath ? forcedDim(suffix) : suffix;
|
|
1745
1986
|
}
|
|
1746
|
-
|
|
1987
|
+
/**
|
|
1988
|
+
* Format the `from → to` hash data column for an edge row.
|
|
1989
|
+
*
|
|
1990
|
+
* When `hashOverride` is provided (off-path → `dim`), it replaces ALL sub-stylers
|
|
1991
|
+
* (`sourceHash`, `destHash`, arrow `glyph`) so dim reaches every character without
|
|
1992
|
+
* inner ANSI codes (e.g. the dim+cyan of `sourceHash`) overriding it. On-path edges
|
|
1993
|
+
* carry no override. Without an override, the normal `style` sub-stylers apply.
|
|
1994
|
+
*/
|
|
1995
|
+
function formatEdgeHashColumn(edge, style, hashLength, palette, hashOverride) {
|
|
1996
|
+
const src = hashOverride ?? style.sourceHash;
|
|
1997
|
+
const dst = hashOverride ?? style.destHash;
|
|
1998
|
+
const glyph = hashOverride ?? style.glyph;
|
|
1747
1999
|
if (edge.kind === "self") {
|
|
1748
2000
|
const hash = abbreviateHash(edge.from, hashLength, palette.emptySource);
|
|
1749
|
-
return `${padFromHashColumn(
|
|
2001
|
+
return `${padFromHashColumn(src(hash), hashLength)} ${glyph(palette.forwardArrow)} ${dst(hash)}`;
|
|
1750
2002
|
}
|
|
1751
|
-
return `${edge.from === EMPTY_CONTRACT_HASH ? padFromHashColumn(
|
|
2003
|
+
return `${edge.from === EMPTY_CONTRACT_HASH ? padFromHashColumn(glyph(palette.emptySource), hashLength) : padFromHashColumn(src(abbreviateHash(edge.from, hashLength, palette.emptySource)), hashLength)} ${glyph(palette.forwardArrow)} ${dst(abbreviateHash(edge.to, hashLength, palette.emptySource))}`;
|
|
1752
2004
|
}
|
|
1753
2005
|
function padVisible(text, targetWidth) {
|
|
1754
2006
|
const padding = Math.max(0, targetWidth - stringWidth(text));
|
|
@@ -1807,6 +2059,60 @@ function renderMigrationGraphTree(model, opts) {
|
|
|
1807
2059
|
const effectiveMaxDirNameLen = opts.globalMaxDirNameWidth ?? maxDirNameLen;
|
|
1808
2060
|
const maxEdgePrefixWidth = opts.globalMaxEdgeTreePrefixWidth ?? maxEdgeTreePrefixWidth(model.rows, wideLabelColumn);
|
|
1809
2061
|
const edgeDirNameWidth = rowDirNameWidth(maxEdgePrefixWidth, effectiveMaxDirNameLen, dirNameGap);
|
|
2062
|
+
const contractHighlights = /* @__PURE__ */ new Map();
|
|
2063
|
+
if (opts.edgeAnnotationsByHash) for (const row of model.rows) {
|
|
2064
|
+
if (row.kind !== "edge" || row.edge === void 0) continue;
|
|
2065
|
+
const annotation = opts.edgeAnnotationsByHash.get(row.edge.migrationHash);
|
|
2066
|
+
if (annotation?.pathHighlight === void 0) continue;
|
|
2067
|
+
const highlight = annotation.pathHighlight;
|
|
2068
|
+
for (const hash of [row.edge.from, row.edge.to]) {
|
|
2069
|
+
if (hash === EMPTY_CONTRACT_HASH) continue;
|
|
2070
|
+
if (contractHighlights.get(hash) !== "on-path") contractHighlights.set(hash, highlight);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
const pathHighlightActive = opts.edgeAnnotationsByHash !== void 0;
|
|
2074
|
+
/**
|
|
2075
|
+
* Resolve the lane and arrow overrides for a row in path-highlight mode.
|
|
2076
|
+
* - on-path → neutral single-path style (style.lane for glyphs, plain arrow, bold name).
|
|
2077
|
+
* Rotation colour is suppressed; `style.sourceHash`/`style.destHash` apply for hashes.
|
|
2078
|
+
* - off-path → uniform dim grey (forcedDim) on every glyph, arrow, name, and hash.
|
|
2079
|
+
* - undefined → `undefined` (no override). Unannotated rows use normal rotation. This covers
|
|
2080
|
+
* both non-path-highlight commands (graph/status/list) and any annotation without pathHighlight.
|
|
2081
|
+
* - When pathHighlightActive is false: always returns undefined, preserving normal rotation.
|
|
2082
|
+
*/
|
|
2083
|
+
function pathStyleForHighlight(highlight) {
|
|
2084
|
+
if (!pathHighlightActive || highlight === void 0) return void 0;
|
|
2085
|
+
if (highlight === "off-path") {
|
|
2086
|
+
const s = PATH_HIGHLIGHT_STYLES.offPath(opts.colorize);
|
|
2087
|
+
return {
|
|
2088
|
+
lane: s.lane,
|
|
2089
|
+
arrow: s.arrow,
|
|
2090
|
+
dirName: s.dirName,
|
|
2091
|
+
hashOverride: s.hashOverride
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
const s = PATH_HIGHLIGHT_STYLES.onPath(style, opts.colorize);
|
|
2095
|
+
return {
|
|
2096
|
+
lane: s.lane,
|
|
2097
|
+
arrow: s.arrow,
|
|
2098
|
+
dirName: s.dirName,
|
|
2099
|
+
hashOverride: s.hashOverride
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* Lane override for a given highlight in path-highlight mode.
|
|
2104
|
+
* Returns the `lane` part only — used for per-cell overrides.
|
|
2105
|
+
*/
|
|
2106
|
+
function pathLaneFor(highlight) {
|
|
2107
|
+
return pathStyleForHighlight(highlight)?.lane;
|
|
2108
|
+
}
|
|
2109
|
+
/**
|
|
2110
|
+
* Arrow override for a given highlight in path-highlight mode.
|
|
2111
|
+
* Returns the `arrow` part only — used for edge-lane cell arrow rendering.
|
|
2112
|
+
*/
|
|
2113
|
+
function pathArrowFor(highlight) {
|
|
2114
|
+
return pathStyleForHighlight(highlight)?.arrow;
|
|
2115
|
+
}
|
|
1810
2116
|
const lines = [];
|
|
1811
2117
|
for (let rowIndex = 0; rowIndex < model.rows.length; rowIndex++) {
|
|
1812
2118
|
const row = model.rows[rowIndex];
|
|
@@ -1816,11 +2122,58 @@ function renderMigrationGraphTree(model, opts) {
|
|
|
1816
2122
|
continue;
|
|
1817
2123
|
}
|
|
1818
2124
|
if (row.kind === "branch-connector" || row.kind === "merge-connector") {
|
|
1819
|
-
|
|
2125
|
+
let connectorColumnOverride;
|
|
2126
|
+
if (pathHighlightActive && opts.colorize) {
|
|
2127
|
+
connectorColumnOverride = /* @__PURE__ */ new Map();
|
|
2128
|
+
for (let col = 0; col < row.cells.length; col++) {
|
|
2129
|
+
const cell = row.cells[col];
|
|
2130
|
+
if (cell === void 0 || cell.kind === "empty") continue;
|
|
2131
|
+
const hashForCell = "migrationHash" in cell && cell.migrationHash !== void 0 ? cell.migrationHash : void 0;
|
|
2132
|
+
if (hashForCell === void 0) continue;
|
|
2133
|
+
const highlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;
|
|
2134
|
+
const override = pathLaneFor(highlight);
|
|
2135
|
+
if (override !== void 0) connectorColumnOverride.set(col, override);
|
|
2136
|
+
}
|
|
2137
|
+
if (connectorColumnOverride.size === 0) connectorColumnOverride = void 0;
|
|
2138
|
+
}
|
|
2139
|
+
lines.push(trimTrailingWhitespace(renderConnectorRow(row, gridWidth, opts.colorize, style, palette, connectorColumnOverride)));
|
|
1820
2140
|
continue;
|
|
1821
2141
|
}
|
|
2142
|
+
let rowPathHighlight;
|
|
2143
|
+
if (row.kind === "edge" && row.edge !== void 0) rowPathHighlight = opts.edgeAnnotationsByHash?.get(row.edge.migrationHash)?.pathHighlight;
|
|
2144
|
+
else if (row.kind === "node" && row.contractHash !== void 0) rowPathHighlight = contractHighlights.get(row.contractHash);
|
|
2145
|
+
const rowStyle = pathStyleForHighlight(rowPathHighlight);
|
|
2146
|
+
const rowLaneOverride = rowStyle?.lane;
|
|
2147
|
+
const rowArrowOverride = rowStyle?.arrow;
|
|
1822
2148
|
const cellColors = resolveRowArcLaneColors(row.cells);
|
|
1823
|
-
let gutter = row.cells.map((cell, column) =>
|
|
2149
|
+
let gutter = row.cells.map((cell, column) => {
|
|
2150
|
+
let laneOverride = rowLaneOverride;
|
|
2151
|
+
let arrowOverride = rowArrowOverride;
|
|
2152
|
+
let arcLaneOverride;
|
|
2153
|
+
if (pathHighlightActive) {
|
|
2154
|
+
if (cell.kind === "edge-lane") {
|
|
2155
|
+
const cellHighlight = opts.edgeAnnotationsByHash?.get(cell.migrationHash)?.pathHighlight;
|
|
2156
|
+
laneOverride = pathLaneFor(cellHighlight);
|
|
2157
|
+
arrowOverride = pathArrowFor(cellHighlight);
|
|
2158
|
+
} else if (cell.kind === "node" && (cell.arcTee === true || cell.arcLand === true)) {
|
|
2159
|
+
const arcColumn = cellColors.connector[column] ?? 0;
|
|
2160
|
+
const arcCell = row.cells[arcColumn];
|
|
2161
|
+
const arcHash = arcCell !== void 0 && "migrationHash" in arcCell ? arcCell.migrationHash : void 0;
|
|
2162
|
+
if (arcHash !== void 0) {
|
|
2163
|
+
const arcHighlight = opts.edgeAnnotationsByHash?.get(arcHash)?.pathHighlight;
|
|
2164
|
+
arcLaneOverride = pathLaneFor(arcHighlight);
|
|
2165
|
+
}
|
|
2166
|
+
} else if (cell.kind !== "node" && cell.kind !== "empty") {
|
|
2167
|
+
const hashForCell = cell.kind === "arc-crossing" && "arcMigrationHash" in cell && cell.arcMigrationHash !== void 0 ? cell.arcMigrationHash : "migrationHash" in cell && cell.migrationHash !== void 0 ? cell.migrationHash : void 0;
|
|
2168
|
+
if (hashForCell !== void 0) {
|
|
2169
|
+
const cellHighlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;
|
|
2170
|
+
laneOverride = pathLaneFor(cellHighlight);
|
|
2171
|
+
arrowOverride = pathArrowFor(cellHighlight);
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
return renderCellPair(cell, column, cellColors, opts.colorize, style, palette, laneOverride, arrowOverride, arcLaneOverride);
|
|
2176
|
+
}).join("");
|
|
1824
2177
|
let laneSpan = row.cells.length;
|
|
1825
2178
|
if (row.kind === "node") if ((row.contractHash ?? EMPTY_CONTRACT_HASH) === EMPTY_CONTRACT_HASH) laneSpan = 1;
|
|
1826
2179
|
else {
|
|
@@ -1832,15 +2185,39 @@ function renderMigrationGraphTree(model, opts) {
|
|
|
1832
2185
|
laneSpan = lastActiveColumn >= 0 ? lastActiveColumn + 1 : 1;
|
|
1833
2186
|
}
|
|
1834
2187
|
const labelColumn = row.kind === "edge" ? maxEdgePrefixWidth : wideLabelColumn !== void 0 && (nodeHasArcDecoration(row) || row.contractHash !== void 0) ? wideLabelColumn : laneSpan * 2 + LABEL_GAP;
|
|
1835
|
-
if (row.kind === "edge" && row.edge?.from === EMPTY_CONTRACT_HASH && (row.laneIndex ?? 0) === 0) gutter = row.cells.slice(0, 1).map((cell, column) => renderCellPair(cell, column, cellColors, opts.colorize, style, palette)).join("");
|
|
1836
|
-
else if (row.kind === "node" && laneSpan < row.cells.length && !nodeHasArcDecoration(row)) gutter = row.cells.slice(0, laneSpan).map((cell, column) =>
|
|
2188
|
+
if (row.kind === "edge" && row.edge?.from === EMPTY_CONTRACT_HASH && (row.laneIndex ?? 0) === 0) gutter = row.cells.slice(0, 1).map((cell, column) => renderCellPair(cell, column, cellColors, opts.colorize, style, palette, rowLaneOverride, rowArrowOverride)).join("");
|
|
2189
|
+
else if (row.kind === "node" && laneSpan < row.cells.length && !nodeHasArcDecoration(row)) gutter = row.cells.slice(0, laneSpan).map((cell, column) => {
|
|
2190
|
+
let cellLaneOverride = rowLaneOverride;
|
|
2191
|
+
let cellArrowOverride = rowArrowOverride;
|
|
2192
|
+
if (pathHighlightActive && cell.kind !== "node" && cell.kind !== "empty") {
|
|
2193
|
+
const hashForCell = cell.kind === "arc-crossing" && "arcMigrationHash" in cell && cell.arcMigrationHash !== void 0 ? cell.arcMigrationHash : "migrationHash" in cell && cell.migrationHash !== void 0 ? cell.migrationHash : void 0;
|
|
2194
|
+
if (hashForCell !== void 0) {
|
|
2195
|
+
const cellHighlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;
|
|
2196
|
+
cellLaneOverride = pathLaneFor(cellHighlight);
|
|
2197
|
+
cellArrowOverride = pathArrowFor(cellHighlight);
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
return renderCellPair(cell, column, cellColors, opts.colorize, style, palette, cellLaneOverride, cellArrowOverride);
|
|
2201
|
+
}).join("");
|
|
1837
2202
|
else if (gutter.length < laneSpan * 2) gutter = gutter.padEnd(laneSpan * 2, " ");
|
|
1838
2203
|
const dirNameWidth = row.kind === "edge" ? edgeDirNameWidth : rowDirNameWidth(labelColumn, maxDirNameLen, dirNameGap);
|
|
1839
2204
|
const gutterPad = padVisible(gutter, labelColumn);
|
|
1840
2205
|
if (row.kind === "node") {
|
|
1841
2206
|
const contractHash = row.contractHash ?? EMPTY_CONTRACT_HASH;
|
|
1842
2207
|
if (contractHash === EMPTY_CONTRACT_HASH) {
|
|
1843
|
-
const trailingLanes = row.cells.slice(1).map((cell, offset) =>
|
|
2208
|
+
const trailingLanes = row.cells.slice(1).map((cell, offset) => {
|
|
2209
|
+
let cellLaneOverride = rowLaneOverride;
|
|
2210
|
+
let cellArrowOverride = rowArrowOverride;
|
|
2211
|
+
if (pathHighlightActive && cell.kind !== "node" && cell.kind !== "empty") {
|
|
2212
|
+
const hashForCell = cell.kind === "arc-crossing" && "arcMigrationHash" in cell && cell.arcMigrationHash !== void 0 ? cell.arcMigrationHash : "migrationHash" in cell && cell.migrationHash !== void 0 ? cell.migrationHash : void 0;
|
|
2213
|
+
if (hashForCell !== void 0) {
|
|
2214
|
+
const cellHighlight = opts.edgeAnnotationsByHash?.get(hashForCell)?.pathHighlight;
|
|
2215
|
+
cellLaneOverride = pathLaneFor(cellHighlight);
|
|
2216
|
+
cellArrowOverride = pathArrowFor(cellHighlight);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
return renderCellPair(cell, offset + 1, cellColors, opts.colorize, style, palette, cellLaneOverride, cellArrowOverride);
|
|
2220
|
+
}).join("");
|
|
1844
2221
|
const emptyGutter = palette.emptySource.padEnd(2, " ") + trailingLanes;
|
|
1845
2222
|
const overlays = overlayNamesForContract(contractHash, opts);
|
|
1846
2223
|
if (overlays.markers.length === 0 && overlays.refs.length === 0) {
|
|
@@ -1851,7 +2228,7 @@ function renderMigrationGraphTree(model, opts) {
|
|
|
1851
2228
|
lines.push(trimTrailingWhitespace(`${emptyGutter}${" ".repeat(LABEL_GAP)}${overlay}`));
|
|
1852
2229
|
continue;
|
|
1853
2230
|
}
|
|
1854
|
-
const hashText = style.sourceHash(abbreviateHash(contractHash, hashLength, palette.emptySource));
|
|
2231
|
+
const hashText = (rowStyle?.hashOverride ?? style.sourceHash)(abbreviateHash(contractHash, hashLength, palette.emptySource));
|
|
1855
2232
|
const overlays = overlayNamesForContract(contractHash, opts);
|
|
1856
2233
|
const hasOverlays = overlays.markers.length > 0 || overlays.refs.length > 0;
|
|
1857
2234
|
const overlayPad = hasOverlays ? " ".repeat(LABEL_GAP) : "";
|
|
@@ -1863,19 +2240,44 @@ function renderMigrationGraphTree(model, opts) {
|
|
|
1863
2240
|
if (edge === void 0) continue;
|
|
1864
2241
|
const dirNamePadding = " ".repeat(Math.max(0, dirNameWidth - edge.dirName.length));
|
|
1865
2242
|
const laneIndex = row.laneIndex ?? 0;
|
|
1866
|
-
const
|
|
1867
|
-
|
|
2243
|
+
const edgeGutterPad = padVisible(gutter, labelColumn);
|
|
2244
|
+
let dirName;
|
|
2245
|
+
if (rowStyle !== void 0) dirName = `${(rowStyle.dirName ?? style.dirName)(edge.dirName)}${dirNamePadding}`;
|
|
2246
|
+
else dirName = `${(opts.colorize && laneIndex > 0 ? (text) => forcedBold(laneColorForColumn(laneIndex)(text)) : style.dirName)(edge.dirName)}${dirNamePadding}`;
|
|
2247
|
+
const hashColumnOverride = rowStyle?.hashOverride;
|
|
2248
|
+
const hashColumn = formatEdgeHashColumn(edge, style, hashLength, palette, hashColumnOverride);
|
|
1868
2249
|
const annotationSuffix = formatEdgeAnnotationSuffix(edge.migrationHash, opts, style);
|
|
1869
|
-
lines.push(trimTrailingWhitespace(`${
|
|
2250
|
+
lines.push(trimTrailingWhitespace(`${edgeGutterPad}${dirName}${hashColumn}${annotationSuffix}`));
|
|
1870
2251
|
}
|
|
1871
2252
|
return lines.join("\n");
|
|
1872
2253
|
}
|
|
2254
|
+
/**
|
|
2255
|
+
* Format a single on-path migration row for the `migrate --show` run-list.
|
|
2256
|
+
*
|
|
2257
|
+
* Uses the SAME styling as the tree renderer's on-path rows (PATH_HIGHLIGHT_STYLES.onPath)
|
|
2258
|
+
* so the run-list and graph tree are byte-for-byte identical in their name/hash columns.
|
|
2259
|
+
* The gutter is omitted — the list has no graph structure.
|
|
2260
|
+
*
|
|
2261
|
+
* This is the SINGLE code path for on-path row styling shared by both the graph tree
|
|
2262
|
+
* and the "Will run, in order:" list. To change the on-path colour, edit PATH_HIGHLIGHT_STYLES.
|
|
2263
|
+
*/
|
|
2264
|
+
function formatOnPathMigrationRow(dirName, from, to, dirNameWidth, colorize, glyphMode) {
|
|
2265
|
+
const palette = paletteFor(glyphMode);
|
|
2266
|
+
const style = createAnsiMigrationListStyler({ useColor: colorize });
|
|
2267
|
+
const styledDirName = `${PATH_HIGHLIGHT_STYLES.onPath(style, colorize).dirName(dirName)}${" ".repeat(Math.max(0, dirNameWidth - dirName.length))}`;
|
|
2268
|
+
const hashLength = 7;
|
|
2269
|
+
const emptySource = palette.emptySource;
|
|
2270
|
+
const fromAbbr = from === EMPTY_CONTRACT_HASH ? padFromHashColumn(style.glyph(emptySource), hashLength) : padFromHashColumn(style.sourceHash(abbreviateHashShort(from, hashLength)), hashLength);
|
|
2271
|
+
const toAbbr = to === EMPTY_CONTRACT_HASH ? style.glyph(emptySource) : style.destHash(abbreviateHashShort(to, hashLength));
|
|
2272
|
+
return `${styledDirName} ${fromAbbr} ${style.glyph(palette.forwardArrow)} ${toAbbr}`;
|
|
2273
|
+
}
|
|
2274
|
+
function abbreviateHashShort(hash, length) {
|
|
2275
|
+
return (hash.startsWith("sha256:") ? hash.slice(7) : hash).slice(0, length);
|
|
2276
|
+
}
|
|
1873
2277
|
function formatLegendExampleMarkers(colorize) {
|
|
1874
|
-
if (!colorize) return "
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1877
|
-
const separator = green(", ");
|
|
1878
|
-
return open + green("contract") + separator + green("db") + close;
|
|
2278
|
+
if (!colorize) return "@contract @db";
|
|
2279
|
+
const sigil = green("@");
|
|
2280
|
+
return `${sigil + bold(green("contract"))} ${sigil}${green("db")}`;
|
|
1879
2281
|
}
|
|
1880
2282
|
/**
|
|
1881
2283
|
* A compact key for the tree visual language: the contract node glyph, the
|
|
@@ -1903,7 +2305,7 @@ function renderMigrationGraphLegend(opts) {
|
|
|
1903
2305
|
` ${style.kind(palette.edgeArrow.self)} ${style.summary("migration without schema change")}`,
|
|
1904
2306
|
appliedPending,
|
|
1905
2307
|
` ${style.kind(palette.emptySource)} ${style.summary("empty database (baseline)")}`,
|
|
1906
|
-
` ${exampleMarkers} ${style.summary("
|
|
2308
|
+
` ${exampleMarkers} ${style.summary("reserved markers — also typeable as --from/--to tokens")}`,
|
|
1907
2309
|
` ${exampleRefs} ${style.summary("user-defined refs")}`,
|
|
1908
2310
|
` ${sampleArrow} ${style.summary("migration from contract aaaaaa to bbbbbb")}`
|
|
1909
2311
|
].join("\n");
|
|
@@ -1938,12 +2340,14 @@ function computeGlobalMaxDirNameWidth(inputs) {
|
|
|
1938
2340
|
return globalMax;
|
|
1939
2341
|
}
|
|
1940
2342
|
function renderMigrationGraphSpaceTreeInternal(input) {
|
|
1941
|
-
const
|
|
2343
|
+
const appSpace = input.isAppSpace !== false;
|
|
2344
|
+
const layout = buildMigrationGraphLayout(buildMigrationGraphRows(input.graph, { ...appSpace ? { contractHash: input.liveContractHash } : {} }));
|
|
1942
2345
|
const listOverlay = buildEdgeAnnotationsByHashFromListEntries(input.migrations);
|
|
1943
2346
|
const edgeAnnotationsByHash = input.statusOverlayByHash === void 0 ? listOverlay : mergeMigrationEdgeAnnotations(listOverlay, input.statusOverlayByHash);
|
|
1944
2347
|
return renderMigrationGraphTree(layout, {
|
|
1945
2348
|
refsByHash: input.refsByHash ?? buildRefsByHashFromListEntries(input.migrations),
|
|
1946
2349
|
contractHash: input.liveContractHash,
|
|
2350
|
+
isAppSpace: appSpace,
|
|
1947
2351
|
edgeAnnotationsByHash,
|
|
1948
2352
|
colorize: input.colorize,
|
|
1949
2353
|
glyphMode: input.glyphMode,
|
|
@@ -1961,6 +2365,6 @@ function indentMigrationGraphTreeBlock(treeOutput, indent) {
|
|
|
1961
2365
|
return treeOutput.split("\n").map((line) => line.length === 0 ? line : `${indent}${line}`).join("\n");
|
|
1962
2366
|
}
|
|
1963
2367
|
//#endregion
|
|
1964
|
-
export {
|
|
2368
|
+
export { buildMigrationGraphLayout as _, computeMaxDirNameLengthForLayout as a, renderMigrationGraphLegend as c, IDENTITY_MIGRATION_LIST_STYLER as d, renderMigrationListWithStyle as f, buildMigrationGraphRows as g, migrationListForwardArrow as h, renderMigrationGraphSpaceTree as i, renderMigrationGraphTree as l, migrationListEmptySource as m, computeGlobalMaxEdgeTreePrefixWidth as n, computeMaxEdgeTreePrefixWidthForLayout as o, abbreviateContractHash as p, indentMigrationGraphTreeBlock as r, formatOnPathMigrationRow as s, computeGlobalMaxDirNameWidth as t, createAnsiMigrationListStyler as u };
|
|
1965
2369
|
|
|
1966
|
-
//# sourceMappingURL=migration-graph-space-render-
|
|
2370
|
+
//# sourceMappingURL=migration-graph-space-render-B0HkTNj3.mjs.map
|