prisma-next 0.5.0-dev.9 → 0.5.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.
Files changed (142) hide show
  1. package/dist/cli-errors-B9OBbled.d.mts +3 -0
  2. package/dist/cli-errors-D3_sMh2K.mjs +33 -0
  3. package/dist/cli-errors-D3_sMh2K.mjs.map +1 -0
  4. package/dist/cli.mjs +16 -78
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/client-BCnP7cHo.mjs +1485 -0
  7. package/dist/client-BCnP7cHo.mjs.map +1 -0
  8. package/dist/{result-handler-Ba3zWQsI.mjs → command-helpers-BeZHkxV8.mjs} +70 -47
  9. package/dist/command-helpers-BeZHkxV8.mjs.map +1 -0
  10. package/dist/commands/contract-emit.d.mts.map +1 -1
  11. package/dist/commands/contract-emit.mjs +2 -4
  12. package/dist/commands/contract-infer.d.mts.map +1 -1
  13. package/dist/commands/contract-infer.mjs +2 -4
  14. package/dist/commands/db-init.d.mts.map +1 -1
  15. package/dist/commands/db-init.mjs +16 -13
  16. package/dist/commands/db-init.mjs.map +1 -1
  17. package/dist/commands/db-schema.d.mts.map +1 -1
  18. package/dist/commands/db-schema.mjs +6 -7
  19. package/dist/commands/db-schema.mjs.map +1 -1
  20. package/dist/commands/db-sign.d.mts.map +1 -1
  21. package/dist/commands/db-sign.mjs +9 -9
  22. package/dist/commands/db-sign.mjs.map +1 -1
  23. package/dist/commands/db-update.d.mts.map +1 -1
  24. package/dist/commands/db-update.mjs +15 -13
  25. package/dist/commands/db-update.mjs.map +1 -1
  26. package/dist/commands/db-verify.d.mts.map +1 -1
  27. package/dist/commands/db-verify.mjs +1 -321
  28. package/dist/commands/migration-apply.d.mts +28 -13
  29. package/dist/commands/migration-apply.d.mts.map +1 -1
  30. package/dist/commands/migration-apply.mjs +55 -151
  31. package/dist/commands/migration-apply.mjs.map +1 -1
  32. package/dist/commands/migration-new.d.mts +0 -1
  33. package/dist/commands/migration-new.d.mts.map +1 -1
  34. package/dist/commands/migration-new.mjs +34 -40
  35. package/dist/commands/migration-new.mjs.map +1 -1
  36. package/dist/commands/migration-plan.d.mts +33 -6
  37. package/dist/commands/migration-plan.d.mts.map +1 -1
  38. package/dist/commands/migration-plan.mjs +2 -348
  39. package/dist/commands/migration-ref.d.mts +1 -1
  40. package/dist/commands/migration-ref.d.mts.map +1 -1
  41. package/dist/commands/migration-ref.mjs +8 -12
  42. package/dist/commands/migration-ref.mjs.map +1 -1
  43. package/dist/commands/migration-show.d.mts +64 -10
  44. package/dist/commands/migration-show.d.mts.map +1 -1
  45. package/dist/commands/migration-show.mjs +166 -60
  46. package/dist/commands/migration-show.mjs.map +1 -1
  47. package/dist/commands/migration-status.d.mts +126 -5
  48. package/dist/commands/migration-status.d.mts.map +1 -1
  49. package/dist/commands/migration-status.mjs +2 -4
  50. package/dist/{config-loader-C25b63rJ.mjs → config-loader-B6sJjXTv.mjs} +3 -5
  51. package/dist/config-loader-B6sJjXTv.mjs.map +1 -0
  52. package/dist/config-loader.d.mts +0 -1
  53. package/dist/config-loader.d.mts.map +1 -1
  54. package/dist/config-loader.mjs +2 -3
  55. package/dist/contract-emit-9DBda5Ou.mjs +150 -0
  56. package/dist/contract-emit-9DBda5Ou.mjs.map +1 -0
  57. package/dist/contract-emit-B77TsJqf.mjs +327 -0
  58. package/dist/contract-emit-B77TsJqf.mjs.map +1 -0
  59. package/dist/{contract-enrichment-CAOELa-H.mjs → contract-enrichment-Dani0mMW.mjs} +4 -6
  60. package/dist/contract-enrichment-Dani0mMW.mjs.map +1 -0
  61. package/dist/{contract-infer-D9cC3rJm.mjs → contract-infer-ByxhPjpW.mjs} +13 -22
  62. package/dist/contract-infer-ByxhPjpW.mjs.map +1 -0
  63. package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs +160 -0
  64. package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs.map +1 -0
  65. package/dist/db-verify-Czm5T-J4.mjs +404 -0
  66. package/dist/db-verify-Czm5T-J4.mjs.map +1 -0
  67. package/dist/exports/config-types.mjs +1 -2
  68. package/dist/exports/control-api.d.mts +101 -586
  69. package/dist/exports/control-api.d.mts.map +1 -1
  70. package/dist/exports/control-api.mjs +4 -6
  71. package/dist/exports/index.d.mts.map +1 -1
  72. package/dist/exports/index.mjs +28 -30
  73. package/dist/exports/index.mjs.map +1 -1
  74. package/dist/exports/init-output.d.mts +2 -4
  75. package/dist/exports/init-output.d.mts.map +1 -1
  76. package/dist/exports/init-output.mjs +2 -3
  77. package/dist/{framework-components-Cr--XBKy.mjs → framework-components-ChqVUxR-.mjs} +3 -4
  78. package/dist/{framework-components-Cr--XBKy.mjs.map → framework-components-ChqVUxR-.mjs.map} +1 -1
  79. package/dist/global-flags-Icqpxk23.d.mts +12 -0
  80. package/dist/global-flags-Icqpxk23.d.mts.map +1 -0
  81. package/dist/helpers-eqdN8tH6.mjs +25 -0
  82. package/dist/helpers-eqdN8tH6.mjs.map +1 -0
  83. package/dist/{init-C5220SY9.mjs → init-DETSgw3h.mjs} +40 -49
  84. package/dist/init-DETSgw3h.mjs.map +1 -0
  85. package/dist/{inspect-live-schema-yrHAvG71.mjs → inspect-live-schema-DxdBd4Er.mjs} +10 -11
  86. package/dist/inspect-live-schema-DxdBd4Er.mjs.map +1 -0
  87. package/dist/migration-cli.d.mts +41 -12
  88. package/dist/migration-cli.d.mts.map +1 -1
  89. package/dist/migration-cli.mjs +309 -86
  90. package/dist/migration-cli.mjs.map +1 -1
  91. package/dist/{migration-command-scaffold-B3B09et6.mjs → migration-command-scaffold-BdV8JYXV.mjs} +8 -9
  92. package/dist/migration-command-scaffold-BdV8JYXV.mjs.map +1 -0
  93. package/dist/migration-plan-mRu5K81L.mjs +494 -0
  94. package/dist/migration-plan-mRu5K81L.mjs.map +1 -0
  95. package/dist/{migration-status-DUMiH8_G.mjs → migration-status-By9G5p2H.mjs} +270 -65
  96. package/dist/migration-status-By9G5p2H.mjs.map +1 -0
  97. package/dist/migrations-CTsyBXCA.mjs +229 -0
  98. package/dist/migrations-CTsyBXCA.mjs.map +1 -0
  99. package/dist/{output-BpcQrnnq.mjs → output-B16Kefzx.mjs} +9 -3
  100. package/dist/output-B16Kefzx.mjs.map +1 -0
  101. package/dist/{progress-adapter-DvQWB1nK.mjs → progress-adapter-DFfvZcYL.mjs} +2 -2
  102. package/dist/{progress-adapter-DvQWB1nK.mjs.map → progress-adapter-DFfvZcYL.mjs.map} +1 -1
  103. package/dist/result-handler-rmPVKIP2.mjs +25 -0
  104. package/dist/result-handler-rmPVKIP2.mjs.map +1 -0
  105. package/dist/rolldown-runtime-twds-ZHy.mjs +14 -0
  106. package/dist/{terminal-ui-C3ZLwQxK.mjs → terminal-ui-C_hFNbAn.mjs} +4 -28
  107. package/dist/terminal-ui-C_hFNbAn.mjs.map +1 -0
  108. package/dist/types-LItU7E4l.d.mts +856 -0
  109. package/dist/types-LItU7E4l.d.mts.map +1 -0
  110. package/dist/{verify-Bkycc-Tf.mjs → verify-CiwNWM9N.mjs} +3 -4
  111. package/dist/verify-CiwNWM9N.mjs.map +1 -0
  112. package/package.json +19 -17
  113. package/dist/cli-errors-BFYgBH3L.d.mts +0 -4
  114. package/dist/cli-errors-Cd79vmTH.mjs +0 -5
  115. package/dist/client-CrsnY58k.mjs +0 -997
  116. package/dist/client-CrsnY58k.mjs.map +0 -1
  117. package/dist/commands/db-verify.mjs.map +0 -1
  118. package/dist/commands/migration-plan.mjs.map +0 -1
  119. package/dist/config-loader-C25b63rJ.mjs.map +0 -1
  120. package/dist/contract-emit--feXyNd7.mjs +0 -4
  121. package/dist/contract-emit-NJ01hiiv.mjs +0 -195
  122. package/dist/contract-emit-NJ01hiiv.mjs.map +0 -1
  123. package/dist/contract-emit-V5SSitUT.mjs +0 -122
  124. package/dist/contract-emit-V5SSitUT.mjs.map +0 -1
  125. package/dist/contract-enrichment-CAOELa-H.mjs.map +0 -1
  126. package/dist/contract-infer-D9cC3rJm.mjs.map +0 -1
  127. package/dist/extract-operation-statements-DsFfxXVZ.mjs +0 -13
  128. package/dist/extract-operation-statements-DsFfxXVZ.mjs.map +0 -1
  129. package/dist/extract-sql-ddl-D9UbZDyz.mjs +0 -26
  130. package/dist/extract-sql-ddl-D9UbZDyz.mjs.map +0 -1
  131. package/dist/init-C5220SY9.mjs.map +0 -1
  132. package/dist/inspect-live-schema-yrHAvG71.mjs.map +0 -1
  133. package/dist/migration-command-scaffold-B3B09et6.mjs.map +0 -1
  134. package/dist/migration-status-DUMiH8_G.mjs.map +0 -1
  135. package/dist/migrations-Bo5WtTla.mjs +0 -153
  136. package/dist/migrations-Bo5WtTla.mjs.map +0 -1
  137. package/dist/output-BpcQrnnq.mjs.map +0 -1
  138. package/dist/result-handler-Ba3zWQsI.mjs.map +0 -1
  139. package/dist/terminal-ui-C3ZLwQxK.mjs.map +0 -1
  140. package/dist/validate-contract-deps-B_Cs29TL.mjs +0 -37
  141. package/dist/validate-contract-deps-B_Cs29TL.mjs.map +0 -1
  142. package/dist/verify-Bkycc-Tf.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":[],"mappings":";;;;;;UA2BiB,mBAAA;;EAAA,SAAA,OAAA,EAAA,MAAmB;EAsBpB,SAAA,OAAA,EAAA,MAAmB;EACd,SAAA,IAAA,EAAA,MAAA;EAEX,SAAA,EAAA,EAAA,MAAA;EAAiB,SAAA,WAAA,EAAA,MAAA;EAAxB,SAAA,IAAA,EAAA,MAAA;EAAM,SAAA,SAAA,EAAA,MAAA;EAiJO,SAAA,UAAA,EAAA,SAA0B;;;;;;;;iBApJ1B,mBAAA,oBACK,oCAElB,OAAO,iBAAiB;iBAiJX,0BAAA,CAAA,GAA8B"}
1
+ {"version":3,"file":"migration-show.d.mts","names":[],"sources":["../../src/commands/migration-show.ts"],"mappings":";;;;;;;;;AAmDA;UAAiB,yBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;EAAA,SACA,IAAA;EAAA,SACA,EAAA;EAAA,SACA,aAAA;EAAA,SACA,SAAA;EAAA,SACA,UAAA;IAAA,SACE,EAAA;IAAA,SACA,KAAA;IAAA,SACA,cAAA;EAAA;EAAA;;;;;EAAA,SAOF,OAAA,EAAS,gBAAA;EAAA,SACT,OAAA;AAAA;;;;;;;;UAUM,yBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;AAAA;AAAA,KAGC,wBAAA,GAA2B,yBAAA,GAA4B,yBAAA;AAAA,UAElD,mBAAA;EAAA,SACN,EAAA;EAKyC;;;;EAAA,SAAzC,MAAA,WAAiB,wBAAA;AAAA;AAoB5B;;;;;;;;;;;AAuBA;;AAvBA,iBAAgB,oBAAA,CACd,MAAA,UACA,gBAAA,UACA,qBAAA,WACC,MAAA,SAAe,kBAAA;AAAA,iBAmBF,mBAAA,CACd,QAAA,WAAmB,sBAAA,IACnB,MAAA,WACC,MAAA,CAAO,sBAAA,EAAwB,kBAAA;;;;;;;;;;iBAmCZ,oBAAA,CACpB,QAAA,WACC,OAAA,CAAQ,MAAA,CAAO,sBAAA,SAA+B,kBAAA;AAAA,iBAkOjC,0BAAA,CAAA,GAA8B,OAAA"}
@@ -1,46 +1,125 @@
1
- import { t as loadConfig } from "../config-loader-C25b63rJ.mjs";
2
- import { _ as errorUnexpected, m as errorRuntime } from "../cli-errors-Cd79vmTH.mjs";
3
- import { t as extractOperationStatements } from "../extract-operation-statements-DsFfxXVZ.mjs";
4
- import { t as TerminalUI } from "../terminal-ui-C3ZLwQxK.mjs";
5
- import { _ as formatStyledHeader, d as setCommandExamples, m as parseGlobalFlags, n as addGlobalOptions, t as handleResult, u as setCommandDescriptions } from "../result-handler-Ba3zWQsI.mjs";
6
- import { a as formatMigrationShowOutput } from "../migrations-Bo5WtTla.mjs";
1
+ import { t as loadConfig } from "../config-loader-B6sJjXTv.mjs";
2
+ import { _ as errorUnexpected, a as errorContractValidationFailed, l as errorFileNotFound, m as errorRuntime, v as mapMigrationToolsError } from "../cli-errors-D3_sMh2K.mjs";
3
+ import { c as resolveContractPath, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, l as resolveMigrationPaths, t as addGlobalOptions, y as formatStyledHeader } from "../command-helpers-BeZHkxV8.mjs";
4
+ import { t as TerminalUI } from "../terminal-ui-C_hFNbAn.mjs";
5
+ import { t as handleResult } from "../result-handler-rmPVKIP2.mjs";
6
+ import { t as createControlClient } from "../client-BCnP7cHo.mjs";
7
+ import { t as buildContractSpaceAggregate } from "../contract-space-aggregate-loader-BrwKK6Q6.mjs";
8
+ import { a as formatMigrationShowOutput } from "../migrations-CTsyBXCA.mjs";
7
9
  import { Command } from "commander";
10
+ import { ifDefined } from "@prisma-next/utils/defined";
8
11
  import { notOk, ok } from "@prisma-next/utils/result";
9
- import { relative, resolve } from "pathe";
10
- import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/dag";
12
+ import { isAbsolute, relative, resolve } from "pathe";
13
+ import { readFile } from "node:fs/promises";
14
+ import { createControlStack } from "@prisma-next/framework-components/control";
11
15
  import { readMigrationPackage, readMigrationsDir } from "@prisma-next/migration-tools/io";
12
- import { MigrationToolsError } from "@prisma-next/migration-tools/types";
13
-
16
+ import { findLatestMigration, reconstructGraph } from "@prisma-next/migration-tools/migration-graph";
17
+ import { spaceMigrationDirectory } from "@prisma-next/migration-tools/spaces";
18
+ import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
14
19
  //#region src/commands/migration-show.ts
15
20
  function looksLikePath(target) {
16
21
  return target.includes("/") || target.includes("\\");
17
22
  }
23
+ /**
24
+ * Validate that a path-like `migration show` target resolves inside the app
25
+ * migrations directory. The returned result is always emitted under
26
+ * `aggregate.app.spaceId`, so accepting an extension-space (or otherwise
27
+ * external) path here would silently mislabel the result. Returns the
28
+ * resolved absolute path on success.
29
+ *
30
+ * `pathe.relative` can return an absolute path when the target cannot be
31
+ * expressed relative to the base (e.g. on Windows when `target` is on a
32
+ * different drive than `appMigrationsDir`). That case does not start with
33
+ * `..`, so the absolute-check below is required to reject cross-drive
34
+ * targets rather than mislabeling them as app-space.
35
+ */
36
+ function resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative) {
37
+ const targetPath = resolve(target);
38
+ const relativeToApp = relative(appMigrationsDir, targetPath);
39
+ if (relativeToApp === "" || relativeToApp === "." || relativeToApp.startsWith("..") || isAbsolute(relativeToApp)) return notOk(errorRuntime("Target must point to an app-space migration", {
40
+ why: `Expected a path under ${appMigrationsRelative}, got ${target}`,
41
+ fix: "Pass an app-space migration directory or use a hash prefix."
42
+ }));
43
+ return ok(targetPath);
44
+ }
18
45
  function resolveByHashPrefix(packages, prefix) {
19
46
  const normalizedPrefix = prefix.startsWith("sha256:") ? prefix : `sha256:${prefix}`;
20
- const matches = packages.filter((p) => p.manifest.migrationId.startsWith(normalizedPrefix));
47
+ const matches = packages.filter((p) => p.metadata.migrationHash.startsWith(normalizedPrefix));
21
48
  if (matches.length === 1) return ok(matches[0]);
22
49
  if (matches.length === 0) return notOk(errorRuntime("No migration found matching prefix", {
23
- why: `No migration has a migrationId starting with "${normalizedPrefix}"`,
50
+ why: `No migration has a migrationHash starting with "${normalizedPrefix}"`,
24
51
  fix: "Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages."
25
52
  }));
26
53
  return notOk(errorRuntime("Ambiguous hash prefix", {
27
- why: `Multiple migrations match prefix "${normalizedPrefix}":\n${matches.map((p) => ` ${p.dirName} ${p.manifest.migrationId}`).join("\n")}`,
54
+ why: `Multiple migrations match prefix "${normalizedPrefix}":\n${matches.map((p) => ` ${p.dirName} ${p.metadata.migrationHash}`).join("\n")}`,
28
55
  fix: "Provide a longer prefix to uniquely identify the migration."
29
56
  }));
30
57
  }
58
+ /**
59
+ * Resolve the latest migration from a space directory.
60
+ *
61
+ * Returns `ok(null)` only when the directory is empty or absent (ENOENT is
62
+ * absorbed by `readMigrationsDir`). If `readMigrationsDir` returned packages
63
+ * but `findLatestMigration` cannot pick a leaf, the on-disk history is
64
+ * corrupt — return a runtime error rather than collapsing it to a `missing`
65
+ * placeholder, which would hide the corruption from the caller.
66
+ */
67
+ async function resolveLatestFromDir(spaceDir) {
68
+ try {
69
+ const allPackages = await readMigrationsDir(spaceDir);
70
+ if (allPackages.length === 0) return ok(null);
71
+ const latestMigration = findLatestMigration(reconstructGraph(allPackages));
72
+ if (!latestMigration) return notOk(errorRuntime("Could not resolve latest migration", {
73
+ why: `No latest migration found in ${relative(process.cwd(), spaceDir)}`,
74
+ fix: "The migrations directory may be corrupted. Inspect the migration.json files."
75
+ }));
76
+ return ok(allPackages.find((p) => p.metadata.migrationHash === latestMigration.migrationHash) ?? null);
77
+ } catch (error) {
78
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
79
+ return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migrations: ${error instanceof Error ? error.message : String(error)}` }));
80
+ }
81
+ }
82
+ function pkgToSpaceResult(spaceId, pkg, client) {
83
+ const ops = pkg.ops;
84
+ const preview = client.toOperationPreview(ops) ?? { statements: [] };
85
+ return {
86
+ kind: "present",
87
+ spaceId,
88
+ dirName: pkg.dirName,
89
+ dirPath: relative(process.cwd(), pkg.dirPath),
90
+ from: pkg.metadata.from,
91
+ to: pkg.metadata.to,
92
+ migrationHash: pkg.metadata.migrationHash,
93
+ createdAt: pkg.metadata.createdAt,
94
+ operations: ops.map((op) => ({
95
+ id: op.id,
96
+ label: op.label,
97
+ operationClass: op.operationClass
98
+ })),
99
+ preview,
100
+ summary: `${ops.length} operation(s)`
101
+ };
102
+ }
31
103
  async function executeMigrationShowCommand(target, options, flags, ui) {
32
104
  const config = await loadConfig(options.config);
33
- const configPath = options.config ? relative(process.cwd(), resolve(options.config)) : "prisma-next.config.ts";
34
- const migrationsDir = resolve(options.config ? resolve(options.config, "..") : process.cwd(), config.migrations?.dir ?? "migrations");
35
- const migrationsRelative = relative(process.cwd(), migrationsDir);
105
+ const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } = resolveMigrationPaths(options.config, config);
106
+ const contractPathAbsolute = resolveContractPath(config);
107
+ const contractPath = relative(process.cwd(), contractPathAbsolute);
36
108
  if (!flags.json && !flags.quiet) {
37
- const details = [{
38
- label: "config",
39
- value: configPath
40
- }, {
41
- label: "migrations",
42
- value: migrationsRelative
43
- }];
109
+ const details = [
110
+ {
111
+ label: "config",
112
+ value: configPath
113
+ },
114
+ {
115
+ label: "contract",
116
+ value: contractPath
117
+ },
118
+ {
119
+ label: "migrations",
120
+ value: appMigrationsRelative
121
+ }
122
+ ];
44
123
  if (target) details.push({
45
124
  label: "target",
46
125
  value: target
@@ -53,69 +132,96 @@ async function executeMigrationShowCommand(target, options, flags, ui) {
53
132
  });
54
133
  ui.stderr(header);
55
134
  }
56
- let pkg;
135
+ let contractJsonContent;
57
136
  try {
58
- if (target && looksLikePath(target)) pkg = await readMigrationPackage(resolve(target));
59
- else {
60
- const allPackages = await readMigrationsDir(migrationsDir);
137
+ contractJsonContent = await readFile(contractPathAbsolute, "utf-8");
138
+ } catch (error) {
139
+ if (error instanceof Error && error.code === "ENOENT") return notOk(errorFileNotFound(contractPathAbsolute, {
140
+ why: `Contract file not found at ${contractPathAbsolute}`,
141
+ fix: `Run \`prisma-next contract emit\` to generate ${contractPath}`
142
+ }));
143
+ return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: "Failed to read contract file" }));
144
+ }
145
+ let appContract;
146
+ try {
147
+ appContract = JSON.parse(contractJsonContent);
148
+ } catch (error) {
149
+ return notOk(errorContractValidationFailed(`Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`, { where: { path: contractPathAbsolute } }));
150
+ }
151
+ const stack = createControlStack(config);
152
+ const familyInstance = config.family.create(stack);
153
+ const aggregateResult = await buildContractSpaceAggregate({
154
+ targetId: config.target.targetId,
155
+ migrationsDir,
156
+ appContract,
157
+ extensionPacks: config.extensionPacks ?? [],
158
+ validateContract: (json) => familyInstance.validateContract(json)
159
+ });
160
+ if (!aggregateResult.ok) return notOk(aggregateResult.failure);
161
+ const aggregate = aggregateResult.value;
162
+ const client = createControlClient({
163
+ family: config.family,
164
+ target: config.target,
165
+ adapter: config.adapter,
166
+ ...ifDefined("driver", config.driver),
167
+ extensionPacks: config.extensionPacks ?? []
168
+ });
169
+ const spaces = [];
170
+ try {
171
+ let appPkg;
172
+ if (target && looksLikePath(target)) {
173
+ const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);
174
+ if (!resolved.ok) return resolved;
175
+ appPkg = await readMigrationPackage(resolved.value);
176
+ } else {
177
+ const allPackages = await readMigrationsDir(appMigrationsDir);
61
178
  if (allPackages.length === 0) return notOk(errorRuntime("No migrations found", {
62
- why: `No migration packages found in ${migrationsRelative}`,
179
+ why: `No migration packages found in ${appMigrationsRelative}`,
63
180
  fix: "Run `prisma-next migration plan` to create a migration first."
64
181
  }));
65
182
  if (target) {
66
183
  const resolved = resolveByHashPrefix(allPackages, target);
67
184
  if (!resolved.ok) return resolved;
68
- pkg = resolved.value;
185
+ appPkg = resolved.value;
69
186
  } else {
70
187
  const latestMigration = findLatestMigration(reconstructGraph(allPackages));
71
188
  if (!latestMigration) return notOk(errorRuntime("Could not resolve latest migration", {
72
189
  why: "No latest migration found in the migration history",
73
190
  fix: "The migrations directory may be corrupted. Inspect the migration.json files."
74
191
  }));
75
- const leafPkg = allPackages.find((p) => p.manifest.migrationId === latestMigration.migrationId);
192
+ const leafPkg = allPackages.find((p) => p.metadata.migrationHash === latestMigration.migrationHash);
76
193
  if (!leafPkg) return notOk(errorRuntime("Could not resolve latest migration", {
77
194
  why: `Latest migration ${latestMigration.dirName} does not match any package`,
78
195
  fix: "The migrations directory may be corrupted. Inspect the migration.json files."
79
196
  }));
80
- pkg = leafPkg;
197
+ appPkg = leafPkg;
81
198
  }
82
199
  }
200
+ spaces.push(pkgToSpaceResult(aggregate.app.spaceId, appPkg, client));
83
201
  } catch (error) {
84
- if (MigrationToolsError.is(error)) return notOk(errorRuntime(error.message, {
85
- why: error.why,
86
- fix: error.fix,
87
- meta: {
88
- code: error.code,
89
- ...error.details ?? {}
90
- }
91
- }));
92
- return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}` }));
202
+ if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
203
+ return notOk(errorUnexpected(error instanceof Error ? error.message : String(error), { why: `Failed to read app-space migration: ${error instanceof Error ? error.message : String(error)}` }));
204
+ }
205
+ for (const ext of aggregate.extensions) {
206
+ const extPkgResult = await resolveLatestFromDir(spaceMigrationDirectory(migrationsDir, ext.spaceId));
207
+ if (!extPkgResult.ok) return extPkgResult;
208
+ if (extPkgResult.value !== null) spaces.push(pkgToSpaceResult(ext.spaceId, extPkgResult.value, client));
209
+ else spaces.push({
210
+ kind: "missing",
211
+ spaceId: ext.spaceId,
212
+ summary: "No on-disk migration package for this space"
213
+ });
93
214
  }
94
- const ops = pkg.ops;
95
- const sql = extractOperationStatements(config.family.familyId, ops) ?? [];
96
215
  return ok({
97
216
  ok: true,
98
- dirName: pkg.dirName,
99
- dirPath: relative(process.cwd(), pkg.dirPath),
100
- from: pkg.manifest.from,
101
- to: pkg.manifest.to,
102
- migrationId: pkg.manifest.migrationId,
103
- kind: pkg.manifest.kind,
104
- createdAt: pkg.manifest.createdAt,
105
- operations: ops.map((op) => ({
106
- id: op.id,
107
- label: op.label,
108
- operationClass: op.operationClass
109
- })),
110
- sql,
111
- summary: `${ops.length} operation(s)`
217
+ spaces
112
218
  });
113
219
  }
114
220
  function createMigrationShowCommand() {
115
221
  const command = new Command("show");
116
- setCommandDescriptions(command, "Display migration package contents", "Shows the operations, DDL preview, and metadata for a migration package.\nAccepts a directory path, a hash prefix (git-style), or defaults to the\nlatest migration.");
222
+ setCommandDescriptions(command, "Display migration package contents", "Shows the operations, statement preview, and metadata for every loaded contract\nspace (app + extensions). Accepts a directory path or hash prefix to target a\nspecific app-space migration; defaults to the latest per space.");
117
223
  setCommandExamples(command, ["prisma-next migration show", "prisma-next migration show sha256:a1b2c3"]);
118
- addGlobalOptions(command).argument("[target]", "Migration directory path or migrationId hash prefix (defaults to latest)").option("--config <path>", "Path to prisma-next.config.ts").action(async (target, options) => {
224
+ addGlobalOptions(command).argument("[target]", "App-space migration path or migrationHash prefix (defaults to latest)").option("--config <path>", "Path to prisma-next.config.ts").action(async (target, options) => {
119
225
  const flags = parseGlobalFlags(options);
120
226
  const ui = new TerminalUI({
121
227
  color: flags.color,
@@ -129,7 +235,7 @@ function createMigrationShowCommand() {
129
235
  });
130
236
  return command;
131
237
  }
132
-
133
238
  //#endregion
134
- export { createMigrationShowCommand, resolveByHashPrefix };
239
+ export { createMigrationShowCommand, resolveAppTargetPath, resolveByHashPrefix, resolveLatestFromDir };
240
+
135
241
  //# sourceMappingURL=migration-show.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-show.mjs","names":["details: Array<{ label: string; value: string }>","pkg: MigrationBundle"],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\nimport { findLatestMigration, reconstructGraph } from '@prisma-next/migration-tools/dag';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport type { MigrationBundle } from '@prisma-next/migration-tools/types';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/types';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { extractOperationStatements } from '../control-api/operations/extract-operation-statements';\nimport { type CliStructuredError, errorRuntime, errorUnexpected } from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport interface MigrationShowResult {\n readonly ok: true;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string;\n readonly to: string;\n readonly migrationId: string;\n readonly kind: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly sql: readonly string[];\n readonly summary: string;\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\nexport function resolveByHashPrefix(\n packages: readonly MigrationBundle[],\n prefix: string,\n): Result<MigrationBundle, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const matches = packages.filter((p) => p.manifest.migrationId.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No migration has a migrationId starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.manifest.migrationId}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n const migrationsDir = resolve(\n options.config ? resolve(options.config, '..') : process.cwd(),\n config.migrations?.dir ?? 'migrations',\n );\n const migrationsRelative = relative(process.cwd(), migrationsDir);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'migrations', value: migrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n let pkg: MigrationBundle;\n\n try {\n if (target && looksLikePath(target)) {\n pkg = await readMigrationPackage(resolve(target));\n } else {\n const allPackages = await readMigrationsDir(migrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${migrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n pkg = resolved.value;\n } else {\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.manifest.migrationId === latestMigration.migrationId,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n pkg = leafPkg;\n }\n }\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(\n errorRuntime(error.message, {\n why: error.why,\n fix: error.fix,\n meta: { code: error.code, ...(error.details ?? {}) },\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n const sql = extractOperationStatements(config.family.familyId, ops) ?? [];\n\n const result: MigrationShowResult = {\n ok: true,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.manifest.from,\n to: pkg.manifest.to,\n migrationId: pkg.manifest.migrationId,\n kind: pkg.manifest.kind,\n createdAt: pkg.manifest.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n sql,\n summary: `${ops.length} operation(s)`,\n };\n return ok(result);\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, DDL preview, and metadata for a migration package.\\n' +\n 'Accepts a directory path, a hash prefix (git-style), or defaults to the\\n' +\n 'latest migration.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument(\n '[target]',\n 'Migration directory path or migrationId hash prefix (defaults to latest)',\n )\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;AA6CA,SAAS,cAAc,QAAyB;AAC9C,QAAO,OAAO,SAAS,IAAI,IAAI,OAAO,SAAS,KAAK;;AAGtD,SAAgB,oBACd,UACA,QAC6C;CAC7C,MAAM,mBAAmB,OAAO,WAAW,UAAU,GAAG,SAAS,UAAU;CAC3E,MAAM,UAAU,SAAS,QAAQ,MAAM,EAAE,SAAS,YAAY,WAAW,iBAAiB,CAAC;AAE3F,KAAI,QAAQ,WAAW,EACrB,QAAO,GAAG,QAAQ,GAAI;AAGxB,KAAI,QAAQ,WAAW,EACrB,QAAO,MACL,aAAa,sCAAsC;EACjD,KAAK,iDAAiD,iBAAiB;EACvE,KAAK;EACN,CAAC,CACH;AAIH,QAAO,MACL,aAAa,yBAAyB;EACpC,KAAK,qCAAqC,iBAAiB,MAH5C,QAAQ,KAAK,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,SAAS,cAAc,CAAC,KAAK,KAAK;EAIzF,KAAK;EACN,CAAC,CACH;;AAGH,eAAe,4BACb,QACA,SACA,OACA,IAC0D;CAC1D,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;CAEJ,MAAM,gBAAgB,QACpB,QAAQ,SAAS,QAAQ,QAAQ,QAAQ,KAAK,GAAG,QAAQ,KAAK,EAC9D,OAAO,YAAY,OAAO,aAC3B;CACD,MAAM,qBAAqB,SAAS,QAAQ,KAAK,EAAE,cAAc;AAEjE,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMA,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,EACtC;GAAE,OAAO;GAAc,OAAO;GAAoB,CACnD;AACD,MAAI,OACF,SAAQ,KAAK;GAAE,OAAO;GAAU,OAAO;GAAQ,CAAC;EAElD,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb;GACA;GACD,CAAC;AACF,KAAG,OAAO,OAAO;;CAGnB,IAAIC;AAEJ,KAAI;AACF,MAAI,UAAU,cAAc,OAAO,CACjC,OAAM,MAAM,qBAAqB,QAAQ,OAAO,CAAC;OAC5C;GACL,MAAM,cAAc,MAAM,kBAAkB,cAAc;AAC1D,OAAI,YAAY,WAAW,EACzB,QAAO,MACL,aAAa,uBAAuB;IAClC,KAAK,kCAAkC;IACvC,KAAK;IACN,CAAC,CACH;AAGH,OAAI,QAAQ;IACV,MAAM,WAAW,oBAAoB,aAAa,OAAO;AACzD,QAAI,CAAC,SAAS,GAAI,QAAO;AACzB,UAAM,SAAS;UACV;IAEL,MAAM,kBAAkB,oBADV,iBAAiB,YAAY,CACO;AAClD,QAAI,CAAC,gBACH,QAAO,MACL,aAAa,sCAAsC;KACjD,KAAK;KACL,KAAK;KACN,CAAC,CACH;IAEH,MAAM,UAAU,YAAY,MACzB,MAAM,EAAE,SAAS,gBAAgB,gBAAgB,YACnD;AACD,QAAI,CAAC,QACH,QAAO,MACL,aAAa,sCAAsC;KACjD,KAAK,oBAAoB,gBAAgB,QAAQ;KACjD,KAAK;KACN,CAAC,CACH;AAEH,UAAM;;;UAGH,OAAO;AACd,MAAI,oBAAoB,GAAG,MAAM,CAC/B,QAAO,MACL,aAAa,MAAM,SAAS;GAC1B,KAAK,MAAM;GACX,KAAK,MAAM;GACX,MAAM;IAAE,MAAM,MAAM;IAAM,GAAI,MAAM,WAAW,EAAE;IAAG;GACrD,CAAC,CACH;AAEH,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACzF,CAAC,CACH;;CAGH,MAAM,MAAM,IAAI;CAChB,MAAM,MAAM,2BAA2B,OAAO,OAAO,UAAU,IAAI,IAAI,EAAE;AAmBzE,QAAO,GAjB6B;EAClC,IAAI;EACJ,SAAS,IAAI;EACb,SAAS,SAAS,QAAQ,KAAK,EAAE,IAAI,QAAQ;EAC7C,MAAM,IAAI,SAAS;EACnB,IAAI,IAAI,SAAS;EACjB,aAAa,IAAI,SAAS;EAC1B,MAAM,IAAI,SAAS;EACnB,WAAW,IAAI,SAAS;EACxB,YAAY,IAAI,KAAK,QAAQ;GAC3B,IAAI,GAAG;GACP,OAAO,GAAG;GACV,gBAAgB,GAAG;GACpB,EAAE;EACH;EACA,SAAS,GAAG,IAAI,OAAO;EACxB,CACgB;;AAGnB,SAAgB,6BAAsC;CACpD,MAAM,UAAU,IAAI,QAAQ,OAAO;AACnC,wBACE,SACA,sCACA,uKAGD;AACD,oBAAmB,SAAS,CAC1B,8BACA,2CACD,CAAC;AACF,kBAAiB,QAAQ,CACtB,SACC,YACA,2EACD,CACA,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,OAAO,QAA4B,YAAkC;EAC3E,MAAM,QAAQ,iBAAiB,QAAQ;EAEvC,MAAM,KAAK,IAAI,WAAW;GAAE,OAAO,MAAM;GAAO,aAAa,MAAM;GAAa,CAAC;EAIjF,MAAM,WAAW,aAFF,MAAM,4BAA4B,QAAQ,SAAS,OAAO,GAAG,EAEtC,OAAO,KAAK,eAAe;AAC/D,OAAI,MAAM,KACR,IAAG,OAAO,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;YACrC,CAAC,MAAM,MAChB,IAAG,IAAI,0BAA0B,YAAY,MAAM,CAAC;IAEtD;AAEF,UAAQ,KAAK,SAAS;GACtB;AAEJ,QAAO"}
1
+ {"version":3,"file":"migration-show.mjs","names":[],"sources":["../../src/commands/migration-show.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport {\n createControlStack,\n type MigrationPlanOperation,\n type OperationPreview,\n} from '@prisma-next/framework-components/control';\nimport { MigrationToolsError } from '@prisma-next/migration-tools/errors';\nimport { readMigrationPackage, readMigrationsDir } from '@prisma-next/migration-tools/io';\nimport {\n findLatestMigration,\n reconstructGraph,\n} from '@prisma-next/migration-tools/migration-graph';\nimport type { OnDiskMigrationPackage } from '@prisma-next/migration-tools/package';\nimport { spaceMigrationDirectory } from '@prisma-next/migration-tools/spaces';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { Command } from 'commander';\nimport { isAbsolute, relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n type CliStructuredError,\n errorContractValidationFailed,\n errorFileNotFound,\n errorRuntime,\n errorUnexpected,\n mapMigrationToolsError,\n} from '../utils/cli-errors';\nimport {\n addGlobalOptions,\n resolveContractPath,\n resolveMigrationPaths,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { buildContractSpaceAggregate } from '../utils/contract-space-aggregate-loader';\nimport { formatMigrationShowOutput } from '../utils/formatters/migrations';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { TerminalUI } from '../utils/terminal-ui';\n\ninterface MigrationShowOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\n/**\n * Details of one space's latest (or targeted) migration package.\n */\nexport interface MigrationShowSpacePresent {\n readonly kind: 'present';\n readonly spaceId: string;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the migration's operations. Always\n * defined; statements is empty for a no-op migration or a family that does\n * not implement the `OperationPreviewCapable` capability.\n */\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\n/**\n * Placeholder for a loaded contract space that has no on-disk migration\n * package — the extension descriptor declared the space but no migrations\n * directory has been materialised for it yet. Surfaces the space in the\n * response so JSON consumers see every loaded extension instead of having\n * silently-skipped entries.\n */\nexport interface MigrationShowSpaceMissing {\n readonly kind: 'missing';\n readonly spaceId: string;\n readonly summary: string;\n}\n\nexport type MigrationShowSpaceResult = MigrationShowSpacePresent | MigrationShowSpaceMissing;\n\nexport interface MigrationShowResult {\n readonly ok: true;\n /**\n * Per-space results, ordered: app first, then extensions alphabetically\n * (matching the aggregate's canonical ordering).\n */\n readonly spaces: readonly MigrationShowSpaceResult[];\n}\n\nfunction looksLikePath(target: string): boolean {\n return target.includes('/') || target.includes('\\\\');\n}\n\n/**\n * Validate that a path-like `migration show` target resolves inside the app\n * migrations directory. The returned result is always emitted under\n * `aggregate.app.spaceId`, so accepting an extension-space (or otherwise\n * external) path here would silently mislabel the result. Returns the\n * resolved absolute path on success.\n *\n * `pathe.relative` can return an absolute path when the target cannot be\n * expressed relative to the base (e.g. on Windows when `target` is on a\n * different drive than `appMigrationsDir`). That case does not start with\n * `..`, so the absolute-check below is required to reject cross-drive\n * targets rather than mislabeling them as app-space.\n */\nexport function resolveAppTargetPath(\n target: string,\n appMigrationsDir: string,\n appMigrationsRelative: string,\n): Result<string, CliStructuredError> {\n const targetPath = resolve(target);\n const relativeToApp = relative(appMigrationsDir, targetPath);\n const isOutsideAppDir =\n relativeToApp === '' ||\n relativeToApp === '.' ||\n relativeToApp.startsWith('..') ||\n isAbsolute(relativeToApp);\n if (isOutsideAppDir) {\n return notOk(\n errorRuntime('Target must point to an app-space migration', {\n why: `Expected a path under ${appMigrationsRelative}, got ${target}`,\n fix: 'Pass an app-space migration directory or use a hash prefix.',\n }),\n );\n }\n return ok(targetPath);\n}\n\nexport function resolveByHashPrefix(\n packages: readonly OnDiskMigrationPackage[],\n prefix: string,\n): Result<OnDiskMigrationPackage, CliStructuredError> {\n const normalizedPrefix = prefix.startsWith('sha256:') ? prefix : `sha256:${prefix}`;\n const matches = packages.filter((p) => p.metadata.migrationHash.startsWith(normalizedPrefix));\n\n if (matches.length === 1) {\n return ok(matches[0]!);\n }\n\n if (matches.length === 0) {\n return notOk(\n errorRuntime('No migration found matching prefix', {\n why: `No migration has a migrationHash starting with \"${normalizedPrefix}\"`,\n fix: 'Run `prisma-next migration show` (no argument) to see the latest migration, or check the migrations directory for available packages.',\n }),\n );\n }\n\n const candidates = matches.map((p) => ` ${p.dirName} ${p.metadata.migrationHash}`).join('\\n');\n return notOk(\n errorRuntime('Ambiguous hash prefix', {\n why: `Multiple migrations match prefix \"${normalizedPrefix}\":\\n${candidates}`,\n fix: 'Provide a longer prefix to uniquely identify the migration.',\n }),\n );\n}\n\n/**\n * Resolve the latest migration from a space directory.\n *\n * Returns `ok(null)` only when the directory is empty or absent (ENOENT is\n * absorbed by `readMigrationsDir`). If `readMigrationsDir` returned packages\n * but `findLatestMigration` cannot pick a leaf, the on-disk history is\n * corrupt — return a runtime error rather than collapsing it to a `missing`\n * placeholder, which would hide the corruption from the caller.\n */\nexport async function resolveLatestFromDir(\n spaceDir: string,\n): Promise<Result<OnDiskMigrationPackage | null, CliStructuredError>> {\n try {\n const allPackages = await readMigrationsDir(spaceDir);\n if (allPackages.length === 0) return ok(null);\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `No latest migration found in ${relative(process.cwd(), spaceDir)}`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n return ok(leafPkg ?? null);\n } catch (error) {\n if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read migrations: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n}\n\nfunction pkgToSpaceResult(\n spaceId: string,\n pkg: OnDiskMigrationPackage,\n client: ReturnType<typeof createControlClient>,\n): MigrationShowSpacePresent {\n const ops = pkg.ops as readonly MigrationPlanOperation[];\n const preview: OperationPreview = client.toOperationPreview(ops) ?? { statements: [] };\n return {\n kind: 'present',\n spaceId,\n dirName: pkg.dirName,\n dirPath: relative(process.cwd(), pkg.dirPath),\n from: pkg.metadata.from,\n to: pkg.metadata.to,\n migrationHash: pkg.metadata.migrationHash,\n createdAt: pkg.metadata.createdAt,\n operations: ops.map((op) => ({\n id: op.id,\n label: op.label,\n operationClass: op.operationClass,\n })),\n preview,\n summary: `${ops.length} operation(s)`,\n };\n}\n\nasync function executeMigrationShowCommand(\n target: string | undefined,\n options: MigrationShowOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n): Promise<Result<MigrationShowResult, CliStructuredError>> {\n const config = await loadConfig(options.config);\n const { configPath, migrationsDir, appMigrationsDir, appMigrationsRelative } =\n resolveMigrationPaths(options.config, config);\n\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n { label: 'migrations', value: appMigrationsRelative },\n ];\n if (target) {\n details.push({ label: 'target', value: target });\n }\n const header = formatStyledHeader({\n command: 'migration show',\n description: 'Display migration package contents',\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load the app contract so the aggregate loader can validate it.\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: 'Failed to read contract file',\n }),\n );\n }\n\n let appContract: Contract;\n try {\n appContract = JSON.parse(contractJsonContent) as Contract;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n // Build the aggregate against current disk state to enumerate all spaces.\n const stack = createControlStack(config);\n const familyInstance = config.family.create(stack);\n const aggregateResult = await buildContractSpaceAggregate({\n targetId: config.target.targetId,\n migrationsDir,\n appContract,\n extensionPacks: config.extensionPacks ?? [],\n validateContract: (json: unknown) => familyInstance.validateContract(json),\n });\n if (!aggregateResult.ok) {\n return notOk(aggregateResult.failure);\n }\n const aggregate = aggregateResult.value;\n\n // `migration show` is an offline command; the control client is constructed\n // purely to dispatch the family-specific `toOperationPreview` capability and\n // is not connected to a database.\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n ...ifDefined('driver', config.driver),\n extensionPacks: config.extensionPacks ?? [],\n });\n\n const spaces: MigrationShowSpaceResult[] = [];\n\n // App space: honour the `target` argument (path or hash prefix) when provided.\n try {\n let appPkg: OnDiskMigrationPackage;\n if (target && looksLikePath(target)) {\n const resolved = resolveAppTargetPath(target, appMigrationsDir, appMigrationsRelative);\n if (!resolved.ok) return resolved;\n appPkg = await readMigrationPackage(resolved.value);\n } else {\n const allPackages = await readMigrationsDir(appMigrationsDir);\n if (allPackages.length === 0) {\n return notOk(\n errorRuntime('No migrations found', {\n why: `No migration packages found in ${appMigrationsRelative}`,\n fix: 'Run `prisma-next migration plan` to create a migration first.',\n }),\n );\n }\n if (target) {\n const resolved = resolveByHashPrefix(allPackages, target);\n if (!resolved.ok) return resolved;\n appPkg = resolved.value;\n } else {\n const graph = reconstructGraph(allPackages);\n const latestMigration = findLatestMigration(graph);\n if (!latestMigration) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: 'No latest migration found in the migration history',\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n const leafPkg = allPackages.find(\n (p) => p.metadata.migrationHash === latestMigration.migrationHash,\n );\n if (!leafPkg) {\n return notOk(\n errorRuntime('Could not resolve latest migration', {\n why: `Latest migration ${latestMigration.dirName} does not match any package`,\n fix: 'The migrations directory may be corrupted. Inspect the migration.json files.',\n }),\n );\n }\n appPkg = leafPkg;\n }\n }\n spaces.push(pkgToSpaceResult(aggregate.app.spaceId, appPkg, client));\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n return notOk(mapMigrationToolsError(error));\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read app-space migration: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Extension spaces: always emit one entry per loaded extension so the\n // response enumerates every space the aggregate knows about. Spaces\n // with no on-disk migration package yet (e.g. an extension was declared\n // but never `migrate`d) become `kind: 'missing'` placeholders instead\n // of being silently skipped.\n for (const ext of aggregate.extensions) {\n const extSpaceDir = spaceMigrationDirectory(migrationsDir, ext.spaceId);\n const extPkgResult = await resolveLatestFromDir(extSpaceDir);\n if (!extPkgResult.ok) return extPkgResult;\n if (extPkgResult.value !== null) {\n spaces.push(pkgToSpaceResult(ext.spaceId, extPkgResult.value, client));\n } else {\n spaces.push({\n kind: 'missing',\n spaceId: ext.spaceId,\n summary: 'No on-disk migration package for this space',\n });\n }\n }\n\n return ok({ ok: true, spaces });\n}\n\nexport function createMigrationShowCommand(): Command {\n const command = new Command('show');\n setCommandDescriptions(\n command,\n 'Display migration package contents',\n 'Shows the operations, statement preview, and metadata for every loaded contract\\n' +\n 'space (app + extensions). Accepts a directory path or hash prefix to target a\\n' +\n 'specific app-space migration; defaults to the latest per space.',\n );\n setCommandExamples(command, [\n 'prisma-next migration show',\n 'prisma-next migration show sha256:a1b2c3',\n ]);\n addGlobalOptions(command)\n .argument('[target]', 'App-space migration path or migrationHash prefix (defaults to latest)')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (target: string | undefined, options: MigrationShowOptions) => {\n const flags = parseGlobalFlags(options);\n\n const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });\n\n const result = await executeMigrationShowCommand(target, options, flags, ui);\n\n const exitCode = handleResult(result, flags, ui, (showResult) => {\n if (flags.json) {\n ui.output(JSON.stringify(showResult, null, 2));\n } else if (!flags.quiet) {\n ui.log(formatMigrationShowOutput(showResult, flags));\n }\n });\n\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkGA,SAAS,cAAc,QAAyB;CAC9C,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO,SAAS,KAAK;;;;;;;;;;;;;;;AAgBtD,SAAgB,qBACd,QACA,kBACA,uBACoC;CACpC,MAAM,aAAa,QAAQ,OAAO;CAClC,MAAM,gBAAgB,SAAS,kBAAkB,WAAW;CAM5D,IAJE,kBAAkB,MAClB,kBAAkB,OAClB,cAAc,WAAW,KAAK,IAC9B,WAAW,cAAc,EAEzB,OAAO,MACL,aAAa,+CAA+C;EAC1D,KAAK,yBAAyB,sBAAsB,QAAQ;EAC5D,KAAK;EACN,CAAC,CACH;CAEH,OAAO,GAAG,WAAW;;AAGvB,SAAgB,oBACd,UACA,QACoD;CACpD,MAAM,mBAAmB,OAAO,WAAW,UAAU,GAAG,SAAS,UAAU;CAC3E,MAAM,UAAU,SAAS,QAAQ,MAAM,EAAE,SAAS,cAAc,WAAW,iBAAiB,CAAC;CAE7F,IAAI,QAAQ,WAAW,GACrB,OAAO,GAAG,QAAQ,GAAI;CAGxB,IAAI,QAAQ,WAAW,GACrB,OAAO,MACL,aAAa,sCAAsC;EACjD,KAAK,mDAAmD,iBAAiB;EACzE,KAAK;EACN,CAAC,CACH;CAIH,OAAO,MACL,aAAa,yBAAyB;EACpC,KAAK,qCAAqC,iBAAiB,MAH5C,QAAQ,KAAK,MAAM,KAAK,EAAE,QAAQ,IAAI,EAAE,SAAS,gBAAgB,CAAC,KAAK,KAGX;EAC3E,KAAK;EACN,CAAC,CACH;;;;;;;;;;;AAYH,eAAsB,qBACpB,UACoE;CACpE,IAAI;EACF,MAAM,cAAc,MAAM,kBAAkB,SAAS;EACrD,IAAI,YAAY,WAAW,GAAG,OAAO,GAAG,KAAK;EAE7C,MAAM,kBAAkB,oBADV,iBAAiB,YACkB,CAAC;EAClD,IAAI,CAAC,iBACH,OAAO,MACL,aAAa,sCAAsC;GACjD,KAAK,gCAAgC,SAAS,QAAQ,KAAK,EAAE,SAAS;GACtE,KAAK;GACN,CAAC,CACH;EAKH,OAAO,GAHS,YAAY,MACzB,MAAM,EAAE,SAAS,kBAAkB,gBAAgB,cAErC,IAAI,KAAK;UACnB,OAAO;EACd,IAAI,oBAAoB,GAAG,MAAM,EAAE,OAAO,MAAM,uBAAuB,MAAM,CAAC;EAC9E,OAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,8BAA8B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC1F,CAAC,CACH;;;AAIL,SAAS,iBACP,SACA,KACA,QAC2B;CAC3B,MAAM,MAAM,IAAI;CAChB,MAAM,UAA4B,OAAO,mBAAmB,IAAI,IAAI,EAAE,YAAY,EAAE,EAAE;CACtF,OAAO;EACL,MAAM;EACN;EACA,SAAS,IAAI;EACb,SAAS,SAAS,QAAQ,KAAK,EAAE,IAAI,QAAQ;EAC7C,MAAM,IAAI,SAAS;EACnB,IAAI,IAAI,SAAS;EACjB,eAAe,IAAI,SAAS;EAC5B,WAAW,IAAI,SAAS;EACxB,YAAY,IAAI,KAAK,QAAQ;GAC3B,IAAI,GAAG;GACP,OAAO,GAAG;GACV,gBAAgB,GAAG;GACpB,EAAE;EACH;EACA,SAAS,GAAG,IAAI,OAAO;EACxB;;AAGH,eAAe,4BACb,QACA,SACA,OACA,IAC0D;CAC1D,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,EAAE,YAAY,eAAe,kBAAkB,0BACnD,sBAAsB,QAAQ,QAAQ,OAAO;CAE/C,MAAM,uBAAuB,oBAAoB,OAAO;CACxD,MAAM,eAAe,SAAS,QAAQ,KAAK,EAAE,qBAAqB;CAElE,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAM,UAAmD;GACvD;IAAE,OAAO;IAAU,OAAO;IAAY;GACtC;IAAE,OAAO;IAAY,OAAO;IAAc;GAC1C;IAAE,OAAO;IAAc,OAAO;IAAuB;GACtD;EACD,IAAI,QACF,QAAQ,KAAK;GAAE,OAAO;GAAU,OAAO;GAAQ,CAAC;EAElD,MAAM,SAAS,mBAAmB;GAChC,SAAS;GACT,aAAa;GACb;GACA;GACD,CAAC;EACF,GAAG,OAAO,OAAO;;CAInB,IAAI;CACJ,IAAI;EACF,sBAAsB,MAAM,SAAS,sBAAsB,QAAQ;UAC5D,OAAO;EACd,IAAI,iBAAiB,SAAU,MAA4B,SAAS,UAClE,OAAO,MACL,kBAAkB,sBAAsB;GACtC,KAAK,8BAA8B;GACnC,KAAK,iDAAiD;GACvD,CAAC,CACH;EAEH,OAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,gCACN,CAAC,CACH;;CAGH,IAAI;CACJ,IAAI;EACF,cAAc,KAAK,MAAM,oBAAoB;UACtC,OAAO;EACd,OAAO,MACL,8BACE,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACnF,EAAE,OAAO,EAAE,MAAM,sBAAsB,EAAE,CAC1C,CACF;;CAIH,MAAM,QAAQ,mBAAmB,OAAO;CACxC,MAAM,iBAAiB,OAAO,OAAO,OAAO,MAAM;CAClD,MAAM,kBAAkB,MAAM,4BAA4B;EACxD,UAAU,OAAO,OAAO;EACxB;EACA;EACA,gBAAgB,OAAO,kBAAkB,EAAE;EAC3C,mBAAmB,SAAkB,eAAe,iBAAiB,KAAK;EAC3E,CAAC;CACF,IAAI,CAAC,gBAAgB,IACnB,OAAO,MAAM,gBAAgB,QAAQ;CAEvC,MAAM,YAAY,gBAAgB;CAKlC,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,GAAG,UAAU,UAAU,OAAO,OAAO;EACrC,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CAEF,MAAM,SAAqC,EAAE;CAG7C,IAAI;EACF,IAAI;EACJ,IAAI,UAAU,cAAc,OAAO,EAAE;GACnC,MAAM,WAAW,qBAAqB,QAAQ,kBAAkB,sBAAsB;GACtF,IAAI,CAAC,SAAS,IAAI,OAAO;GACzB,SAAS,MAAM,qBAAqB,SAAS,MAAM;SAC9C;GACL,MAAM,cAAc,MAAM,kBAAkB,iBAAiB;GAC7D,IAAI,YAAY,WAAW,GACzB,OAAO,MACL,aAAa,uBAAuB;IAClC,KAAK,kCAAkC;IACvC,KAAK;IACN,CAAC,CACH;GAEH,IAAI,QAAQ;IACV,MAAM,WAAW,oBAAoB,aAAa,OAAO;IACzD,IAAI,CAAC,SAAS,IAAI,OAAO;IACzB,SAAS,SAAS;UACb;IAEL,MAAM,kBAAkB,oBADV,iBAAiB,YACkB,CAAC;IAClD,IAAI,CAAC,iBACH,OAAO,MACL,aAAa,sCAAsC;KACjD,KAAK;KACL,KAAK;KACN,CAAC,CACH;IAEH,MAAM,UAAU,YAAY,MACzB,MAAM,EAAE,SAAS,kBAAkB,gBAAgB,cACrD;IACD,IAAI,CAAC,SACH,OAAO,MACL,aAAa,sCAAsC;KACjD,KAAK,oBAAoB,gBAAgB,QAAQ;KACjD,KAAK;KACN,CAAC,CACH;IAEH,SAAS;;;EAGb,OAAO,KAAK,iBAAiB,UAAU,IAAI,SAAS,QAAQ,OAAO,CAAC;UAC7D,OAAO;EACd,IAAI,oBAAoB,GAAG,MAAM,EAC/B,OAAO,MAAM,uBAAuB,MAAM,CAAC;EAE7C,OAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,uCAAuC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACnG,CAAC,CACH;;CAQH,KAAK,MAAM,OAAO,UAAU,YAAY;EAEtC,MAAM,eAAe,MAAM,qBADP,wBAAwB,eAAe,IAAI,QACJ,CAAC;EAC5D,IAAI,CAAC,aAAa,IAAI,OAAO;EAC7B,IAAI,aAAa,UAAU,MACzB,OAAO,KAAK,iBAAiB,IAAI,SAAS,aAAa,OAAO,OAAO,CAAC;OAEtE,OAAO,KAAK;GACV,MAAM;GACN,SAAS,IAAI;GACb,SAAS;GACV,CAAC;;CAIN,OAAO,GAAG;EAAE,IAAI;EAAM;EAAQ,CAAC;;AAGjC,SAAgB,6BAAsC;CACpD,MAAM,UAAU,IAAI,QAAQ,OAAO;CACnC,uBACE,SACA,sCACA,kOAGD;CACD,mBAAmB,SAAS,CAC1B,8BACA,2CACD,CAAC;CACF,iBAAiB,QAAQ,CACtB,SAAS,YAAY,wEAAwE,CAC7F,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,OAAO,QAA4B,YAAkC;EAC3E,MAAM,QAAQ,iBAAiB,QAAQ;EAEvC,MAAM,KAAK,IAAI,WAAW;GAAE,OAAO,MAAM;GAAO,aAAa,MAAM;GAAa,CAAC;EAIjF,MAAM,WAAW,aAAa,MAFT,4BAA4B,QAAQ,SAAS,OAAO,GAAG,EAEtC,OAAO,KAAK,eAAe;GAC/D,IAAI,MAAM,MACR,GAAG,OAAO,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM,OAChB,GAAG,IAAI,0BAA0B,YAAY,MAAM,CAAC;IAEtD;EAEF,QAAQ,KAAK,SAAS;GACtB;CAEJ,OAAO"}
@@ -1,6 +1,40 @@
1
1
  import { Command } from "commander";
2
- import { MigrationBundle, MigrationGraph } from "@prisma-next/migration-tools/types";
2
+ import { Result } from "@prisma-next/utils/result";
3
+ import { ControlExtensionDescriptor } from "@prisma-next/framework-components/control";
4
+ import { ContractMarkerRecordLike } from "@prisma-next/migration-tools/aggregate";
5
+ import { Contract } from "@prisma-next/contract/types";
6
+ import { OnDiskMigrationPackage } from "@prisma-next/migration-tools/package";
7
+ import { MigrationGraph } from "@prisma-next/migration-tools/graph";
3
8
 
9
+ //#region src/utils/contract-space-aggregate-loader.d.ts
10
+ /**
11
+ * Inputs needed to compose the aggregate loader at the CLI surface.
12
+ *
13
+ * Keeps the loader framework-neutral (no `Config` import) by accepting
14
+ * already-resolved structural inputs: validated app contract, target
15
+ * id, migrations root directory, and the set of extension descriptors.
16
+ */
17
+ interface BuildAggregateInputs<TFamilyId extends string, TTargetId extends string> {
18
+ readonly targetId: TTargetId;
19
+ readonly migrationsDir: string;
20
+ readonly appContract: Contract;
21
+ readonly extensionPacks: ReadonlyArray<ControlExtensionDescriptor<TFamilyId, TTargetId>>;
22
+ readonly validateContract: (contractJson: unknown) => Contract;
23
+ /**
24
+ * App-space migration packages to hydrate the app member's
25
+ * migration graph with. Defaults to `[]` (matches the `db init` /
26
+ * `db update` daily-driver behaviour, where the app's authored
27
+ * `migrations/` graph is not walked — the planner uses the synth
28
+ * strategy for the app member instead).
29
+ *
30
+ * `migration apply` callers thread the user's authored app-space
31
+ * packages (loaded via `loadMigrationPackages(appMigrationsDir)`)
32
+ * through here so the graph-walk strategy can plot a path through
33
+ * them — the prod-time replay path explicitly forbids synth.
34
+ */
35
+ readonly appMigrationPackages?: ReadonlyArray<OnDiskMigrationPackage>;
36
+ }
37
+ //#endregion
4
38
  //#region src/utils/migration-types.d.ts
5
39
  interface StatusRef {
6
40
  readonly name: string;
@@ -27,12 +61,47 @@ interface MigrationStatusEntry {
27
61
  readonly dirName: string;
28
62
  readonly from: string;
29
63
  readonly to: string;
30
- readonly migrationId: string;
64
+ readonly migrationHash: string;
31
65
  readonly operationCount: number;
32
66
  readonly operationSummary: string;
33
67
  readonly hasDestructive: boolean;
34
68
  readonly status: EdgeStatusKind | 'unknown';
35
69
  }
70
+ /**
71
+ * Per-space status row in the aggregate-shaped status output.
72
+ *
73
+ * Surfaces, for each contract space:
74
+ *
75
+ * - `headHash`: the on-disk head ref's hash (where the space is going).
76
+ * - `markerHash`: the live marker hash for the space, or null if no
77
+ * marker has been written yet (greenfield, or pre-`migration apply`).
78
+ * - `pendingCount`: number of migration edges between marker and head.
79
+ * Computed via {@link graphWalkStrategy}; 0 means the space is
80
+ * already at head.
81
+ * - `status`: convenience tag the formatter uses to pick a glyph.
82
+ * `'never-planned'` is reserved for spaces with non-empty head but
83
+ * no on-disk migrations — which shouldn't happen if the loader's
84
+ * integrity check passes.
85
+ *
86
+ * Online-only fields (`markerHash`, `status`) are absent when the
87
+ * command runs without a database connection.
88
+ */
89
+ interface MigrationStatusSpaceEntry {
90
+ readonly spaceId: string;
91
+ readonly kind: 'app' | 'extension';
92
+ readonly headHash: string;
93
+ readonly markerHash?: string | null;
94
+ readonly pendingCount?: number;
95
+ readonly status?: 'up-to-date' | 'pending' | 'no-marker' | 'never-planned' | 'unreachable';
96
+ }
97
+ /**
98
+ * Sum per-space `pendingCount` into a cross-space total, but only when
99
+ * every loaded space reports a defined `pendingCount`. Returns
100
+ * `undefined` if any space is on the marker-unknown / offline path
101
+ * (where `pendingCount` is intentionally absent), so JSON consumers can
102
+ * distinguish "no pending" from "unknown".
103
+ */
104
+ declare function computeTotalPendingAcrossSpaces(spaces: readonly MigrationStatusSpaceEntry[]): number | undefined;
36
105
  interface MigrationStatusResult {
37
106
  readonly ok: true;
38
107
  readonly mode: 'online' | 'offline';
@@ -41,23 +110,55 @@ interface MigrationStatusResult {
41
110
  readonly targetHash: string;
42
111
  readonly contractHash: string;
43
112
  readonly refs?: readonly StatusRef[];
113
+ /** Required invariants from the active ref, sorted ascending. Always present (`[]` when no `--ref` or the ref declares none) — knowable offline. */
114
+ readonly requiredInvariants: readonly string[];
115
+ /**
116
+ * Invariants the marker has applied at least once, intersected with
117
+ * `requiredInvariants` for display relevance. JSON consumers see only the
118
+ * subset overlapping the active ref's required set — the full unfiltered
119
+ * marker invariant list lives on `marker.invariants` (control plane) and
120
+ * is not surfaced here. Present only in `mode === 'online'`; absent when
121
+ * offline (the marker is unknown, not empty).
122
+ */
123
+ readonly appliedInvariants?: readonly string[];
124
+ /** required − applied. Present only in `mode === 'online'`; absent when offline. */
125
+ readonly missingInvariants?: readonly string[];
44
126
  readonly pathDecision?: {
45
127
  readonly fromHash: string;
46
128
  readonly toHash: string;
47
129
  readonly alternativeCount: number;
48
130
  readonly tieBreakReasons: readonly string[];
49
131
  readonly refName?: string;
132
+ readonly requiredInvariants: readonly string[];
133
+ readonly satisfiedInvariants: readonly string[];
50
134
  readonly selectedPath: readonly {
51
135
  readonly dirName: string;
52
- readonly migrationId: string;
136
+ readonly migrationHash: string;
53
137
  readonly from: string;
54
138
  readonly to: string;
139
+ readonly invariants: readonly string[];
55
140
  }[];
56
141
  };
57
142
  readonly summary: string;
58
143
  readonly diagnostics: readonly StatusDiagnostic[];
144
+ /**
145
+ * Aggregate enumeration of every on-disk contract space (app +
146
+ * extensions), in canonical schedule order (extensions
147
+ * alphabetically, then app). Present whenever the aggregate loader
148
+ * succeeded; absent in early-error returns (e.g. unreadable
149
+ * migrations directory) where the existing diagnostics already
150
+ * surface the failure.
151
+ *
152
+ * The legacy top-level fields (`migrations`, `markerHash`,
153
+ * `targetHash`, `pathDecision`, …) describe the **app member**
154
+ * specifically — back-compat with single-space callers. Per-space
155
+ * detail for extension members lives only on this list.
156
+ */
157
+ readonly spaces?: readonly MigrationStatusSpaceEntry[];
158
+ /** Cross-space pending-migration total (sum of `spaces[].pendingCount`). Present when `spaces` is. */
159
+ readonly totalPendingAcrossSpaces?: number;
59
160
  readonly graph?: MigrationGraph;
60
- readonly bundles?: readonly MigrationBundle[];
161
+ readonly bundles?: readonly OnDiskMigrationPackage[];
61
162
  readonly edgeStatuses?: readonly EdgeStatus[];
62
163
  readonly activeRefHash?: string;
63
164
  readonly activeRefName?: string;
@@ -79,7 +180,27 @@ interface MigrationStatusResult {
79
180
  * @internal Exported for testing only.
80
181
  */
81
182
  declare function deriveEdgeStatuses(graph: MigrationGraph, targetHash: string, contractHash: string, markerHash: string | undefined, mode: 'online' | 'offline'): EdgeStatus[];
183
+ /**
184
+ * Build the aggregate enumeration of contract spaces for the status
185
+ * output. Loads the aggregate from disk (lossy on failure — extension
186
+ * spaces are simply omitted, the existing single-space app behaviour
187
+ * keeps working), reads per-space marker rows when online, and uses
188
+ * {@link graphWalkStrategy} to compute each space's pending count.
189
+ *
190
+ * Sub-spec § `migration status` semantics — the aggregate-walking
191
+ * version reports per-space marker + pending state alongside the
192
+ * cross-space totals.
193
+ */
194
+ declare function loadAggregateStatusSpaces(args: {
195
+ readonly targetId: string;
196
+ readonly migrationsDir: string;
197
+ readonly appContractRaw: unknown;
198
+ readonly extensionPacks: BuildAggregateInputs<string, string>['extensionPacks'];
199
+ readonly validateContract: BuildAggregateInputs<string, string>['validateContract'];
200
+ readonly markersBySpace: ReadonlyMap<string, ContractMarkerRecordLike> | null;
201
+ }): Promise<readonly MigrationStatusSpaceEntry[]>;
82
202
  declare function createMigrationStatusCommand(): Command;
203
+ declare function formatStatusSummary(result: MigrationStatusResult, colorize: boolean): string;
83
204
  //#endregion
84
- export { MigrationStatusEntry, MigrationStatusResult, type StatusDiagnostic, type StatusRef, createMigrationStatusCommand, deriveEdgeStatuses };
205
+ export { MigrationStatusEntry, MigrationStatusResult, MigrationStatusSpaceEntry, type StatusDiagnostic, type StatusRef, computeTotalPendingAcrossSpaces, createMigrationStatusCommand, deriveEdgeStatuses, formatStatusSummary, loadAggregateStatusSpaces };
85
206
  //# sourceMappingURL=migration-status.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"sourcesContent":[],"mappings":";;;;UAAiB,SAAA;;;;AAAjB;AAMiB,UAAA,gBAAA,CAAgB;;;;ECWrB,SAAA,KAAA,EAAA,SAAc,MAAA,EAAA;AAmB1B;;;KAnBY,cAAA;ADjBZ;AAMiB,UC8BA,UAAA,CD9BgB;;mBCgCd;;;;ADtCF,UE2DA,oBAAA,CF3DS;EAMT,SAAA,OAAA,EAAA,MAAgB;;;;ECWrB,SAAA,cAAc,EAAA,MAAA;EAmBT,SAAA,gBAEE,EAAA,MAAA;;mBC6BA;;AAKF,UAAA,qBAAA,CAAqB;EAGN,SAAA,EAAA,EAAA,IAAA;EAIL,SAAA,IAAA,EAAA,QAAA,GAAA,SAAA;EAeM,SAAA,UAAA,EAAA,SAnBD,oBAmBC,EAAA;EACd,SAAA,UAAA,CAAA,EAAA,MAAA;EACW,SAAA,UAAA,EAAA,MAAA;EACK,SAAA,YAAA,EAAA,MAAA;EAAU,SAAA,IAAA,CAAA,EAAA,SAlBlB,SAkBkB,EAAA;EAkD7B,SAAA,YAAkB,CAAA,EAAA;IAsiBlB,SAAA,QAAA,EAAA,MAAA;;;;;;;;;;;;;iCA3lBiB;mBACd;8BACW;mCACK;;;;;;;;;;;;;;;;;;;;iBAkDnB,kBAAA,QACP,uHAKN;iBAgiBa,4BAAA,CAAA,GAAgC"}
1
+ {"version":3,"file":"migration-status.d.mts","names":[],"sources":["../../src/utils/contract-space-aggregate-loader.ts","../../src/utils/migration-types.ts","../../src/utils/formatters/graph-migration-mapper.ts","../../src/commands/migration-status.ts"],"mappings":";;;;;;;;;;;;;;;;UAqHiB,oBAAA;EAAA,SACN,QAAA,EAAU,SAAA;EAAA,SACV,aAAA;EAAA,SACA,WAAA,EAAa,QAAA;EAAA,SACb,cAAA,EAAgB,aAAA,CAAc,0BAAA,CAA2B,SAAA,EAAW,SAAA;EAAA,SACpE,gBAAA,GAAmB,YAAA,cAA0B,QAAA;EAJnC;;;;;;;;;;;;EAAA,SAiBV,oBAAA,GAAuB,aAAA,CAAc,sBAAA;AAAA;;;UCvI/B,SAAA;EAAA,SACN,IAAA;EAAA,SACA,IAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,IAAA;EAAA,SACA,QAAA;EAAA,SACA,OAAA;EAAA,SACA,KAAA;AAAA;;;KCOC,cAAA;;UAmBK,UAAA;EAAA,SACN,OAAA;EAAA,SACA,MAAA,EAAQ,cAAA;AAAA;;;UCwCF,oBAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAA;EAAA,SACA,EAAA;EAAA,SACA,aAAA;EAAA,SACA,cAAA;EAAA,SACA,gBAAA;EAAA,SACA,cAAA;EAAA,SACA,MAAA,EAAQ,cAAA;AAAA;;;;;;;;;;;;;;;;;;;;UAsBF,yBAAA;EAAA,SACN,OAAA;EAAA,SACA,IAAA;EAAA,SACA,QAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA;EAAA,SACA,MAAA;AAAA;;;;AFlHX;;;;iBE4HgB,+BAAA,CACd,MAAA,WAAiB,yBAAA;AAAA,UAaF,qBAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA,WAAqB,oBAAA;EAAA,SACrB,UAAA;EAAA,SACA,UAAA;EAAA,SACA,YAAA;EAAA,SACA,IAAA,YAAgB,SAAA;EFzIhB;EAAA,SE2IA,kBAAA;EFzIA;;;;;;ACOX;;EDPW,SEkJA,iBAAA;ED3Ie;EAAA,SC6If,iBAAA;EAAA,SACA,YAAA;IAAA,SACE,QAAA;IAAA,SACA,MAAA;IAAA,SACA,gBAAA;IAAA,SACA,eAAA;IAAA,SACA,OAAA;IAAA,SACA,kBAAA;IAAA,SACA,mBAAA;IAAA,SACA,YAAA;MAAA,SACE,OAAA;MAAA,SACA,aAAA;MAAA,SACA,IAAA;MAAA,SACA,EAAA;MAAA,SACA,UAAA;IAAA;EAAA;EAAA,SAGJ,OAAA;EAAA,SACA,WAAA,WAAsB,gBAAA;EA/FtB;;;;;;;;;AA2BX;;;;EA3BW,SA6GA,MAAA,YAAkB,yBAAA;EAhFlB;EAAA,SAkFA,wBAAA;EAAA,SACA,KAAA,GAAQ,cAAA;EAAA,SACR,OAAA,YAAmB,sBAAA;EAAA,SACnB,YAAA,YAAwB,UAAA;EAAA,SACxB,aAAA;EAAA,SACA,aAAA;EAAA,SACA,QAAA;AAAA;;;;AA5DX;;;;;;;;;;;;iBA2GgB,kBAAA,CACd,KAAA,EAAO,cAAA,EACP,UAAA,UACA,YAAA,UACA,UAAA,sBACA,IAAA,yBACC,UAAA;;;;;;;;;;;;iBAuMmB,yBAAA,CAA0B,IAAA;EAAA,SACrC,QAAA;EAAA,SACA,aAAA;EAAA,SACA,cAAA;EAAA,SACA,cAAA,EAAgB,oBAAA;EAAA,SAChB,gBAAA,EAAkB,oBAAA;EAAA,SAClB,cAAA,EAAgB,WAAA,SAAoB,wBAAA;AAAA,IAC3C,OAAA,UAAiB,yBAAA;AAAA,iBAqlBL,4BAAA,CAAA,GAAgC,OAAA;AAAA,iBAoGhC,mBAAA,CAAoB,MAAA,EAAQ,qBAAA,EAAuB,QAAA"}
@@ -1,4 +1,2 @@
1
- import "../config-loader-C25b63rJ.mjs";
2
- import { n as deriveEdgeStatuses, t as createMigrationStatusCommand } from "../migration-status-DUMiH8_G.mjs";
3
-
4
- export { createMigrationStatusCommand, deriveEdgeStatuses };
1
+ import { a as loadAggregateStatusSpaces, i as formatStatusSummary, n as createMigrationStatusCommand, r as deriveEdgeStatuses, t as computeTotalPendingAcrossSpaces } from "../migration-status-By9G5p2H.mjs";
2
+ export { computeTotalPendingAcrossSpaces, createMigrationStatusCommand, deriveEdgeStatuses, formatStatusSummary, loadAggregateStatusSpaces };
@@ -1,11 +1,10 @@
1
1
  import { getEmittedArtifactPaths } from "@prisma-next/emitter";
2
2
  import { errorConfigFileNotFound, errorConfigValidation, errorUnexpected } from "@prisma-next/errors/control";
3
+ import { ifDefined } from "@prisma-next/utils/defined";
3
4
  import { dirname, resolve } from "pathe";
4
5
  import { ConfigValidationError, validateConfig } from "@prisma-next/config/config-validation";
5
- import { ifDefined } from "@prisma-next/utils/defined";
6
6
  import { loadConfig } from "c12";
7
7
  import { normalizeContractConfig } from "@prisma-next/config/config-types";
8
-
9
8
  //#region src/config-path-validation.ts
10
9
  function throwValidation(field, why) {
11
10
  throw new ConfigValidationError(field, why);
@@ -44,7 +43,6 @@ function finalizeConfig(config, configDir) {
44
43
  }
45
44
  };
46
45
  }
47
-
48
46
  //#endregion
49
47
  //#region src/config-loader.ts
50
48
  async function loadValidatedConfig(configPath) {
@@ -84,7 +82,7 @@ async function loadConfig$1(configPath) {
84
82
  throw errorUnexpected(String(error));
85
83
  }
86
84
  }
87
-
88
85
  //#endregion
89
86
  export { loadConfig$1 as t };
90
- //# sourceMappingURL=config-loader-C25b63rJ.mjs.map
87
+
88
+ //# sourceMappingURL=config-loader-B6sJjXTv.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader-B6sJjXTv.mjs","names":["loadConfigC12","loadConfig"],"sources":["../src/config-path-validation.ts","../src/config-loader.ts"],"sourcesContent":["import {\n type ContractSourceProvider,\n normalizeContractConfig,\n type PrismaNextConfig,\n} from '@prisma-next/config/config-types';\nimport { ConfigValidationError } from '@prisma-next/config/config-validation';\nimport { getEmittedArtifactPaths } from '@prisma-next/emitter';\nimport { resolve } from 'pathe';\n\nfunction throwValidation(field: string, why: string): never {\n throw new ConfigValidationError(field, why);\n}\n\nfunction finalizeContractSource(\n source: ContractSourceProvider,\n configDir: string,\n): ContractSourceProvider {\n const resolvedInputs = source.inputs?.map((input) => resolve(configDir, input));\n if (resolvedInputs === undefined) {\n return source;\n }\n\n return {\n ...source,\n inputs: resolvedInputs,\n };\n}\n\nfunction validateNoOutputsAreInputs(\n inputs: readonly string[] | undefined,\n output: string | undefined,\n): void {\n if (inputs === undefined || output === undefined) {\n return;\n }\n\n let emittedArtifactPaths: ReturnType<typeof getEmittedArtifactPaths>;\n try {\n emittedArtifactPaths = getEmittedArtifactPaths(output);\n } catch (error) {\n throwValidation('contract.output', error instanceof Error ? error.message : String(error));\n }\n\n const emittedPaths = new Set([emittedArtifactPaths.jsonPath, emittedArtifactPaths.dtsPath]);\n\n for (const input of inputs) {\n if (emittedPaths.has(input)) {\n throwValidation(\n 'contract.source.inputs[]',\n 'Config.contract.source.inputs must not include emitted artifact paths derived from contract.output',\n );\n }\n }\n}\n\nexport function finalizeConfig(config: PrismaNextConfig, configDir: string): PrismaNextConfig {\n if (!config.contract) {\n return config;\n }\n const contract = normalizeContractConfig(config.contract);\n const source = finalizeContractSource(contract.source, configDir);\n const output = resolve(configDir, contract.output);\n\n validateNoOutputsAreInputs(source.inputs, output);\n\n return {\n ...config,\n contract: {\n ...contract,\n source,\n output,\n },\n };\n}\n","import type { PrismaNextConfig } from '@prisma-next/config/config-types';\nimport { ConfigValidationError, validateConfig } from '@prisma-next/config/config-validation';\nimport {\n errorConfigFileNotFound,\n errorConfigValidation,\n errorUnexpected,\n} from '@prisma-next/errors/control';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { loadConfig as loadConfigC12 } from 'c12';\nimport { dirname, resolve } from 'pathe';\nimport { finalizeConfig } from './config-path-validation';\n\nasync function loadValidatedConfig(configPath?: string): Promise<PrismaNextConfig> {\n const cwd = process.cwd();\n const resolvedConfigPath = configPath ? resolve(cwd, configPath) : undefined;\n const configCwd = resolvedConfigPath ? dirname(resolvedConfigPath) : cwd;\n\n const result = await loadConfigC12<PrismaNextConfig>({\n name: 'prisma-next',\n ...ifDefined('configFile', resolvedConfigPath),\n cwd: configCwd,\n });\n\n // When a specific config file was requested, verify it was actually loaded\n // (c12 falls back to searching by name if the specified file doesn't exist)\n if (resolvedConfigPath && result.configFile !== resolvedConfigPath) {\n throw errorConfigFileNotFound(resolvedConfigPath);\n }\n\n // Check if config is missing or empty (c12 may return empty object when file doesn't exist)\n if (!result.config || Object.keys(result.config).length === 0) {\n // Use c12's configFile if available, otherwise use explicit configPath, otherwise omit path\n const displayPath = result.configFile || resolvedConfigPath || configPath;\n throw errorConfigFileNotFound(displayPath);\n }\n\n // Validate config structure\n validateConfig(result.config);\n\n const loadedConfigDir = result.configFile ? dirname(result.configFile) : configCwd;\n return finalizeConfig(result.config, loadedConfigDir);\n}\n\n/**\n * Loads the Prisma Next config from a TypeScript file.\n * Supports both default export and named export.\n * Uses c12 to automatically handle TypeScript compilation and config file discovery.\n *\n * @param configPath - Optional path to config file. Defaults to `./prisma-next.config.ts` in current directory.\n * @returns The loaded config object.\n * @throws Error if config file doesn't exist or is invalid.\n */\nexport async function loadConfig(configPath?: string): Promise<PrismaNextConfig> {\n try {\n return await loadValidatedConfig(configPath);\n } catch (error) {\n if (error instanceof ConfigValidationError) {\n throw errorConfigValidation(error.field, {\n why: error.why,\n });\n }\n\n // Re-throw structured errors as-is\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof (error as { code: string }).code === 'string'\n ) {\n throw error;\n }\n\n if (error instanceof Error) {\n // Check for file not found errors\n if (\n error.message.includes('not found') ||\n error.message.includes('Cannot find') ||\n error.message.includes('ENOENT')\n ) {\n // Use resolved path if available, otherwise use original configPath\n const displayPath = configPath ? resolve(process.cwd(), configPath) : undefined;\n throw errorConfigFileNotFound(displayPath, {\n why: error.message,\n });\n }\n // For other errors, wrap in unexpected error\n throw errorUnexpected(error.message, {\n why: `Failed to load config: ${error.message}`,\n });\n }\n throw errorUnexpected(String(error));\n }\n}\n"],"mappings":";;;;;;;;AASA,SAAS,gBAAgB,OAAe,KAAoB;CAC1D,MAAM,IAAI,sBAAsB,OAAO,IAAI;;AAG7C,SAAS,uBACP,QACA,WACwB;CACxB,MAAM,iBAAiB,OAAO,QAAQ,KAAK,UAAU,QAAQ,WAAW,MAAM,CAAC;CAC/E,IAAI,mBAAmB,KAAA,GACrB,OAAO;CAGT,OAAO;EACL,GAAG;EACH,QAAQ;EACT;;AAGH,SAAS,2BACP,QACA,QACM;CACN,IAAI,WAAW,KAAA,KAAa,WAAW,KAAA,GACrC;CAGF,IAAI;CACJ,IAAI;EACF,uBAAuB,wBAAwB,OAAO;UAC/C,OAAO;EACd,gBAAgB,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;;CAG5F,MAAM,eAAe,IAAI,IAAI,CAAC,qBAAqB,UAAU,qBAAqB,QAAQ,CAAC;CAE3F,KAAK,MAAM,SAAS,QAClB,IAAI,aAAa,IAAI,MAAM,EACzB,gBACE,4BACA,qGACD;;AAKP,SAAgB,eAAe,QAA0B,WAAqC;CAC5F,IAAI,CAAC,OAAO,UACV,OAAO;CAET,MAAM,WAAW,wBAAwB,OAAO,SAAS;CACzD,MAAM,SAAS,uBAAuB,SAAS,QAAQ,UAAU;CACjE,MAAM,SAAS,QAAQ,WAAW,SAAS,OAAO;CAElD,2BAA2B,OAAO,QAAQ,OAAO;CAEjD,OAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG;GACH;GACA;GACD;EACF;;;;AC5DH,eAAe,oBAAoB,YAAgD;CACjF,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,qBAAqB,aAAa,QAAQ,KAAK,WAAW,GAAG,KAAA;CACnE,MAAM,YAAY,qBAAqB,QAAQ,mBAAmB,GAAG;CAErE,MAAM,SAAS,MAAMA,WAAgC;EACnD,MAAM;EACN,GAAG,UAAU,cAAc,mBAAmB;EAC9C,KAAK;EACN,CAAC;CAIF,IAAI,sBAAsB,OAAO,eAAe,oBAC9C,MAAM,wBAAwB,mBAAmB;CAInD,IAAI,CAAC,OAAO,UAAU,OAAO,KAAK,OAAO,OAAO,CAAC,WAAW,GAG1D,MAAM,wBADc,OAAO,cAAc,sBAAsB,WACrB;CAI5C,eAAe,OAAO,OAAO;CAE7B,MAAM,kBAAkB,OAAO,aAAa,QAAQ,OAAO,WAAW,GAAG;CACzE,OAAO,eAAe,OAAO,QAAQ,gBAAgB;;;;;;;;;;;AAYvD,eAAsBC,aAAW,YAAgD;CAC/E,IAAI;EACF,OAAO,MAAM,oBAAoB,WAAW;UACrC,OAAO;EACd,IAAI,iBAAiB,uBACnB,MAAM,sBAAsB,MAAM,OAAO,EACvC,KAAK,MAAM,KACZ,CAAC;EAIJ,IACE,iBAAiB,SACjB,UAAU,SACV,OAAQ,MAA2B,SAAS,UAE5C,MAAM;EAGR,IAAI,iBAAiB,OAAO;GAE1B,IACE,MAAM,QAAQ,SAAS,YAAY,IACnC,MAAM,QAAQ,SAAS,cAAc,IACrC,MAAM,QAAQ,SAAS,SAAS,EAIhC,MAAM,wBADc,aAAa,QAAQ,QAAQ,KAAK,EAAE,WAAW,GAAG,KAAA,GAC3B,EACzC,KAAK,MAAM,SACZ,CAAC;GAGJ,MAAM,gBAAgB,MAAM,SAAS,EACnC,KAAK,0BAA0B,MAAM,WACtC,CAAC;;EAEJ,MAAM,gBAAgB,OAAO,MAAM,CAAC"}