@ddt-tools/cli 0.2.0 → 0.2.4

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 (203) hide show
  1. package/dist/advise-tests-YNMKVJCD.js +87 -0
  2. package/dist/advise-tests-YNMKVJCD.js.map +1 -0
  3. package/dist/ai-NTNPYEKZ.js +86 -0
  4. package/dist/ai-NTNPYEKZ.js.map +1 -0
  5. package/dist/anonymize-LERTWUQO.js +139 -0
  6. package/dist/anonymize-LERTWUQO.js.map +1 -0
  7. package/dist/approval-GGZGKIU4.js +73 -0
  8. package/dist/approval-GGZGKIU4.js.map +1 -0
  9. package/dist/approval-chain-GWJKZHVU.js +118 -0
  10. package/dist/approval-chain-GWJKZHVU.js.map +1 -0
  11. package/dist/audit-log-2PH55BU4.js +159 -0
  12. package/dist/audit-log-2PH55BU4.js.map +1 -0
  13. package/dist/backlog-QNXGOUF4.js +76 -0
  14. package/dist/backlog-QNXGOUF4.js.map +1 -0
  15. package/dist/bisect-W3XKKRWG.js +111 -0
  16. package/dist/bisect-W3XKKRWG.js.map +1 -0
  17. package/dist/bookmarks-XVOGXGMC.js +107 -0
  18. package/dist/bookmarks-XVOGXGMC.js.map +1 -0
  19. package/dist/branch-S3I2IJGQ.js +103 -0
  20. package/dist/branch-S3I2IJGQ.js.map +1 -0
  21. package/dist/build-MP3JQEFO.js +20 -0
  22. package/dist/build-MP3JQEFO.js.map +1 -0
  23. package/dist/catalog-3J3NFNXP.js +137 -0
  24. package/dist/catalog-3J3NFNXP.js.map +1 -0
  25. package/dist/changelog-ZQAH3ULB.js +216 -0
  26. package/dist/changelog-ZQAH3ULB.js.map +1 -0
  27. package/dist/chunk-2FT6HXKS.js +55 -0
  28. package/dist/chunk-2FT6HXKS.js.map +1 -0
  29. package/dist/chunk-DGUM43GV.js +11 -0
  30. package/dist/chunk-DGUM43GV.js.map +1 -0
  31. package/dist/chunk-DL3V7UJ2.js +25 -0
  32. package/dist/chunk-DL3V7UJ2.js.map +1 -0
  33. package/dist/chunk-VM2H4LAO.js +15 -0
  34. package/dist/chunk-VM2H4LAO.js.map +1 -0
  35. package/dist/chunk-XFXG347C.js +40 -0
  36. package/dist/chunk-XFXG347C.js.map +1 -0
  37. package/dist/cli.js +499 -19402
  38. package/dist/cli.js.map +1 -1
  39. package/dist/compare-P7JOV76O.js +379 -0
  40. package/dist/compare-P7JOV76O.js.map +1 -0
  41. package/dist/compare-profiles-H33CXZPD.js +219 -0
  42. package/dist/compare-profiles-H33CXZPD.js.map +1 -0
  43. package/dist/completion-ZSNCQKJ2.js +89 -0
  44. package/dist/completion-ZSNCQKJ2.js.map +1 -0
  45. package/dist/connection-CDGVEFUC.js +148 -0
  46. package/dist/connection-CDGVEFUC.js.map +1 -0
  47. package/dist/cost-estimate-S2MKHT2H.js +321 -0
  48. package/dist/cost-estimate-S2MKHT2H.js.map +1 -0
  49. package/dist/data-compare-46ZI7KHL.js +128 -0
  50. package/dist/data-compare-46ZI7KHL.js.map +1 -0
  51. package/dist/data-fit-WGEPLD5S.js +127 -0
  52. package/dist/data-fit-WGEPLD5S.js.map +1 -0
  53. package/dist/deploy-status-4H5KJFRC.js +58 -0
  54. package/dist/deploy-status-4H5KJFRC.js.map +1 -0
  55. package/dist/design-ILX3ZSWW.js +135 -0
  56. package/dist/design-ILX3ZSWW.js.map +1 -0
  57. package/dist/diagnose-WPUL67E4.js +150 -0
  58. package/dist/diagnose-WPUL67E4.js.map +1 -0
  59. package/dist/discover-DEO2R5T6.js +78 -0
  60. package/dist/discover-DEO2R5T6.js.map +1 -0
  61. package/dist/docs-QNY3MUVO.js +183 -0
  62. package/dist/docs-QNY3MUVO.js.map +1 -0
  63. package/dist/drift-FDRNPWQA.js +233 -0
  64. package/dist/drift-FDRNPWQA.js.map +1 -0
  65. package/dist/drift-gate-6BWWWMHW.js +103 -0
  66. package/dist/drift-gate-6BWWWMHW.js.map +1 -0
  67. package/dist/error-lookup-4R3Y4RBC.js +56 -0
  68. package/dist/error-lookup-4R3Y4RBC.js.map +1 -0
  69. package/dist/errorReporting-3LPE2IJY.js +109 -0
  70. package/dist/errorReporting-3LPE2IJY.js.map +1 -0
  71. package/dist/exec-JOLH5LPT.js +122 -0
  72. package/dist/exec-JOLH5LPT.js.map +1 -0
  73. package/dist/explain-NS26WE2Y.js +189 -0
  74. package/dist/explain-NS26WE2Y.js.map +1 -0
  75. package/dist/explorer-GSYYYOAL.js +58 -0
  76. package/dist/explorer-GSYYYOAL.js.map +1 -0
  77. package/dist/extract-4LWEZG4O.js +152 -0
  78. package/dist/extract-4LWEZG4O.js.map +1 -0
  79. package/dist/features-KQV4OFIZ.js +54 -0
  80. package/dist/features-KQV4OFIZ.js.map +1 -0
  81. package/dist/feedback-CBLGXUEG.js +158 -0
  82. package/dist/feedback-CBLGXUEG.js.map +1 -0
  83. package/dist/find-SMXRCZ76.js +176 -0
  84. package/dist/find-SMXRCZ76.js.map +1 -0
  85. package/dist/format-HMGG6MY3.js +277 -0
  86. package/dist/format-HMGG6MY3.js.map +1 -0
  87. package/dist/generate-W7VLBDLI.js +160 -0
  88. package/dist/generate-W7VLBDLI.js.map +1 -0
  89. package/dist/graph-YYL5UYCJ.js +168 -0
  90. package/dist/graph-YYL5UYCJ.js.map +1 -0
  91. package/dist/history-GDRFP4PG.js +184 -0
  92. package/dist/history-GDRFP4PG.js.map +1 -0
  93. package/dist/hosts-DRFZTMIJ.js +45 -0
  94. package/dist/hosts-DRFZTMIJ.js.map +1 -0
  95. package/dist/impact-A4NU6CB2.js +63 -0
  96. package/dist/impact-A4NU6CB2.js.map +1 -0
  97. package/dist/import-2RNYDL4E.js +79 -0
  98. package/dist/import-2RNYDL4E.js.map +1 -0
  99. package/dist/index.cjs +11 -5
  100. package/dist/index.cjs.map +1 -1
  101. package/dist/index.js +8 -2
  102. package/dist/index.js.map +1 -1
  103. package/dist/init-EAOGNGXI.js +54 -0
  104. package/dist/init-EAOGNGXI.js.map +1 -0
  105. package/dist/install-hooks-G3Y5LVXK.js +109 -0
  106. package/dist/install-hooks-G3Y5LVXK.js.map +1 -0
  107. package/dist/license-Z5YSC7XQ.js +43 -0
  108. package/dist/license-Z5YSC7XQ.js.map +1 -0
  109. package/dist/lineage-C5CGVP36.js +555 -0
  110. package/dist/lineage-C5CGVP36.js.map +1 -0
  111. package/dist/lint-AQFPZ3WG.js +144 -0
  112. package/dist/lint-AQFPZ3WG.js.map +1 -0
  113. package/dist/mcp-F7FND5X7.js +343 -0
  114. package/dist/mcp-F7FND5X7.js.map +1 -0
  115. package/dist/migrate-from-dbt-K4ELOWUD.js +156 -0
  116. package/dist/migrate-from-dbt-K4ELOWUD.js.map +1 -0
  117. package/dist/migrate-platform-E7VZFPO5.js +91 -0
  118. package/dist/migrate-platform-E7VZFPO5.js.map +1 -0
  119. package/dist/optimize-WUJ5ZN5Y.js +109 -0
  120. package/dist/optimize-WUJ5ZN5Y.js.map +1 -0
  121. package/dist/perf-UULZSREY.js +200 -0
  122. package/dist/perf-UULZSREY.js.map +1 -0
  123. package/dist/pii-QHU32VML.js +146 -0
  124. package/dist/pii-QHU32VML.js.map +1 -0
  125. package/dist/pilot-BR6GVK32.js +29 -0
  126. package/dist/pilot-BR6GVK32.js.map +1 -0
  127. package/dist/pr-comment-2FOA3EXG.js +81 -0
  128. package/dist/pr-comment-2FOA3EXG.js.map +1 -0
  129. package/dist/preview-XNY422OU.js +46 -0
  130. package/dist/preview-XNY422OU.js.map +1 -0
  131. package/dist/profile-SQTBNKYS.js +98 -0
  132. package/dist/profile-SQTBNKYS.js.map +1 -0
  133. package/dist/promote-FSGUPIPD.js +417 -0
  134. package/dist/promote-FSGUPIPD.js.map +1 -0
  135. package/dist/publish-AYCRMCE2.js +739 -0
  136. package/dist/publish-AYCRMCE2.js.map +1 -0
  137. package/dist/purge-Y5IOTXKA.js +56 -0
  138. package/dist/purge-Y5IOTXKA.js.map +1 -0
  139. package/dist/query-log-SDDGMJLJ.js +112 -0
  140. package/dist/query-log-SDDGMJLJ.js.map +1 -0
  141. package/dist/refactor-TC7S43F2.js +5809 -0
  142. package/dist/refactor-TC7S43F2.js.map +1 -0
  143. package/dist/refresh-MDJYOYV5.js +39 -0
  144. package/dist/refresh-MDJYOYV5.js.map +1 -0
  145. package/dist/replay-E4664A5K.js +118 -0
  146. package/dist/replay-E4664A5K.js.map +1 -0
  147. package/dist/revert-QWQWCJJB.js +111 -0
  148. package/dist/revert-QWQWCJJB.js.map +1 -0
  149. package/dist/review-7CAVLD67.js +164 -0
  150. package/dist/review-7CAVLD67.js.map +1 -0
  151. package/dist/rollback-suggest-C6D5YFCA.js +79 -0
  152. package/dist/rollback-suggest-C6D5YFCA.js.map +1 -0
  153. package/dist/safer-alternative-QR4QEFUV.js +84 -0
  154. package/dist/safer-alternative-QR4QEFUV.js.map +1 -0
  155. package/dist/safety-OFWUFLK4.js +165 -0
  156. package/dist/safety-OFWUFLK4.js.map +1 -0
  157. package/dist/savings-MEBE4TXI.js +95 -0
  158. package/dist/savings-MEBE4TXI.js.map +1 -0
  159. package/dist/scan-secrets-XCUBMLHL.js +54 -0
  160. package/dist/scan-secrets-XCUBMLHL.js.map +1 -0
  161. package/dist/schema-7JZIG6QR.js +447 -0
  162. package/dist/schema-7JZIG6QR.js.map +1 -0
  163. package/dist/script-BMYVBHFR.js +167 -0
  164. package/dist/script-BMYVBHFR.js.map +1 -0
  165. package/dist/search-TA3C3AZT.js +151 -0
  166. package/dist/search-TA3C3AZT.js.map +1 -0
  167. package/dist/seed-W4Q3L2IU.js +101 -0
  168. package/dist/seed-W4Q3L2IU.js.map +1 -0
  169. package/dist/sketch-6B2V6FJV.js +83 -0
  170. package/dist/sketch-6B2V6FJV.js.map +1 -0
  171. package/dist/snapshot-YMVS322L.js +171 -0
  172. package/dist/snapshot-YMVS322L.js.map +1 -0
  173. package/dist/snippets-EVTN63OU.js +74 -0
  174. package/dist/snippets-EVTN63OU.js.map +1 -0
  175. package/dist/standards-FGJW3CQL.js +238 -0
  176. package/dist/standards-FGJW3CQL.js.map +1 -0
  177. package/dist/suggest-V3LVIFZ5.js +44 -0
  178. package/dist/suggest-V3LVIFZ5.js.map +1 -0
  179. package/dist/suggest-constraints-EX2FCWOQ.js +154 -0
  180. package/dist/suggest-constraints-EX2FCWOQ.js.map +1 -0
  181. package/dist/suite-YTQ3CNX5.js +85 -0
  182. package/dist/suite-YTQ3CNX5.js.map +1 -0
  183. package/dist/telemetry-KOIY3NEQ.js +90 -0
  184. package/dist/telemetry-KOIY3NEQ.js.map +1 -0
  185. package/dist/template-MUJ6X6LN.js +396 -0
  186. package/dist/template-MUJ6X6LN.js.map +1 -0
  187. package/dist/test-XFSQHR2S.js +169 -0
  188. package/dist/test-XFSQHR2S.js.map +1 -0
  189. package/dist/trial-GFTGYCR3.js +31 -0
  190. package/dist/trial-GFTGYCR3.js.map +1 -0
  191. package/dist/validate-LFDEZFFH.js +107 -0
  192. package/dist/validate-LFDEZFFH.js.map +1 -0
  193. package/dist/verify-KRDYOJCR.js +76 -0
  194. package/dist/verify-KRDYOJCR.js.map +1 -0
  195. package/dist/watch-FSG23RR3.js +80 -0
  196. package/dist/watch-FSG23RR3.js.map +1 -0
  197. package/dist/xcompare-U4TXTTIR.js +87 -0
  198. package/dist/xcompare-U4TXTTIR.js.map +1 -0
  199. package/package.json +2 -2
  200. package/dist/cli.cjs +0 -19298
  201. package/dist/cli.cjs.map +0 -1
  202. package/dist/cli.d.cts +0 -1
  203. package/dist/cli.d.ts +0 -1
@@ -0,0 +1,150 @@
1
+ import {
2
+ attachExplainFlag,
3
+ runExplain
4
+ } from "./chunk-XFXG347C.js";
5
+ import "./chunk-DGUM43GV.js";
6
+
7
+ // src/commands/diagnose.ts
8
+ import { promises as fs } from "fs";
9
+ import path from "path";
10
+ import { Command } from "commander";
11
+ import {
12
+ diagnostics,
13
+ interop,
14
+ loadProject,
15
+ pac,
16
+ parseProjectModel
17
+ } from "@ddt-tools/core";
18
+ function diagnoseCommand() {
19
+ const cmd = new Command("diagnose");
20
+ cmd.description(
21
+ "Project-level health report: lint + lineage smells + object smells + cost smells, with reasoning."
22
+ ).requiredOption("--source <path>", ".ddtproj or .ddtpac to analyze.").option(
23
+ "--category <c>",
24
+ "Filter to one category: lint | lineage | smell | cost | dim-modeling."
25
+ ).option(
26
+ "--min-severity <s>",
27
+ "Filter to a minimum severity: error | warning | info. Default info (everything).",
28
+ "info"
29
+ ).option(
30
+ "--format <fmt>",
31
+ "table | json | markdown | sarif. sarif emits SARIF 2.1.0 for GitHub code-scanning / Azure DevOps. Default table.",
32
+ "table"
33
+ ).option("-o, --out <path>", "Output file path. Defaults to stdout.").action(
34
+ async (opts) => {
35
+ const sourcePath = String(opts.source);
36
+ const model = await loadModel(sourcePath);
37
+ const report = diagnostics.analyzeProject(model, {
38
+ source: sourcePath,
39
+ ...opts.category ? { category: String(opts.category) } : {},
40
+ ...opts.minSeverity ? { minSeverity: String(opts.minSeverity) } : {}
41
+ });
42
+ const fmt = String(opts.format ?? "table").toLowerCase();
43
+ let payload;
44
+ if (fmt === "json") {
45
+ payload = JSON.stringify(report, null, 2);
46
+ } else if (fmt === "markdown") {
47
+ payload = renderReportMarkdown(report);
48
+ } else if (fmt === "sarif") {
49
+ payload = JSON.stringify(interop.diagnosticReportToSarif(report), null, 2);
50
+ } else if (fmt === "table") {
51
+ payload = diagnostics.formatReport(report);
52
+ } else {
53
+ throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown | sarif.`);
54
+ }
55
+ if (opts.out) {
56
+ const out = path.resolve(String(opts.out));
57
+ await fs.mkdir(path.dirname(out), { recursive: true });
58
+ await fs.writeFile(out, payload + (payload.endsWith("\n") ? "" : "\n"), "utf8");
59
+ console.error(
60
+ `Wrote ${out} (${payload.length} bytes, ${report.findings.length} finding(s)).`
61
+ );
62
+ } else {
63
+ process.stdout.write(payload + (payload.endsWith("\n") ? "" : "\n"));
64
+ }
65
+ if (report.totals.error > 0) process.exitCode = 1;
66
+ await runExplain({ feature: "diagnose.explain" }, opts, () => buildDiagnosePrompt(report));
67
+ }
68
+ );
69
+ attachExplainFlag(cmd);
70
+ return cmd;
71
+ }
72
+ function buildDiagnosePrompt(report) {
73
+ const lines = [];
74
+ lines.push(`Source: ${report.source || "(unknown)"}`);
75
+ lines.push(
76
+ `Totals: ${report.totals.error} error, ${report.totals.warning} warning, ${report.totals.info} info`
77
+ );
78
+ lines.push("");
79
+ const top = report.findings.slice().sort((a, b) => sevWeight(b.severity) - sevWeight(a.severity)).slice(0, 40);
80
+ lines.push(`Top ${top.length} findings (highest severity first):`);
81
+ for (const d of top) {
82
+ lines.push(`- [${d.severity}] ${d.id} \xB7 ${d.fqn || "(project)"} \u2014 ${d.message}`);
83
+ }
84
+ if (report.findings.length > top.length) {
85
+ lines.push(`(\u2026 ${report.findings.length - top.length} more truncated)`);
86
+ }
87
+ lines.push("");
88
+ lines.push(
89
+ "Explain the dominant themes, what they suggest about the project health, and the highest-leverage fixes the team should tackle first."
90
+ );
91
+ return lines.join("\n");
92
+ }
93
+ function sevWeight(s) {
94
+ return s === "error" ? 3 : s === "warning" ? 2 : 1;
95
+ }
96
+ function renderReportMarkdown(report) {
97
+ const lines = [];
98
+ lines.push(`# Diagnostic report \u2014 \`${report.source || "(no source)"}\``);
99
+ lines.push("");
100
+ lines.push(`Generated: ${report.generatedAt}`);
101
+ lines.push("");
102
+ lines.push(
103
+ `**Totals:** ${report.totals.error} error \xB7 ${report.totals.warning} warning \xB7 ${report.totals.info} info`
104
+ );
105
+ lines.push("");
106
+ lines.push("## By category");
107
+ lines.push("");
108
+ lines.push("| Category | Count |");
109
+ lines.push("|---|---|");
110
+ for (const [k, v] of Object.entries(report.byCategory)) {
111
+ if (v > 0) lines.push(`| ${k} | ${v} |`);
112
+ }
113
+ lines.push("");
114
+ if (report.findings.length === 0) {
115
+ lines.push("_No findings._");
116
+ return lines.join("\n");
117
+ }
118
+ lines.push("## Findings");
119
+ lines.push("");
120
+ for (const d of report.findings) {
121
+ const glyph = d.severity === "error" ? "\u{1F6D1}" : d.severity === "warning" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
122
+ lines.push(`### ${glyph} \`${d.id}\` \u2014 ${d.fqn || "(project)"}`);
123
+ lines.push("");
124
+ lines.push(`**${d.message}**`);
125
+ lines.push("");
126
+ lines.push(`*Why:* ${d.reasoning}`);
127
+ lines.push("");
128
+ lines.push(`*Suggestion:* ${d.suggestion}`);
129
+ lines.push("");
130
+ if (d.related && d.related.length > 0) {
131
+ lines.push(
132
+ `*Related:* ${d.related.slice(0, 5).map((r) => `\`${r}\``).join(", ")}`
133
+ );
134
+ lines.push("");
135
+ }
136
+ }
137
+ return lines.join("\n");
138
+ }
139
+ async function loadModel(sourcePath) {
140
+ if (sourcePath.endsWith(".ddtpac")) {
141
+ const c = await pac.readPac(sourcePath);
142
+ return c.model;
143
+ }
144
+ const loaded = await loadProject(sourcePath);
145
+ return await parseProjectModel(loaded);
146
+ }
147
+ export {
148
+ diagnoseCommand
149
+ };
150
+ //# sourceMappingURL=diagnose-WPUL67E4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/diagnose.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n diagnostics,\n interop,\n loadProject,\n pac,\n parseProjectModel,\n type DatabricksObject,\n} from '@ddt-tools/core';\nimport { attachExplainFlag, runExplain } from '../util/ai-explain.js';\n\n/**\n * `ddt diagnose` — project-level health report. Bundles lint, lineage\n * smells (orphan / no-downstream / hot-table / cycle), object smells\n * (`SELECT *` in views, large tables without CLUSTER BY / Z-ORDER,\n * streaming tables without watermark / checkpoint, deletion-vector\n * gaps) and cost smells (long delta.logRetentionDuration). Every\n * finding ships with a **reasoning** line explaining *why* it matters.\n *\n * Mirrors `sdt diagnose`.\n */\nexport function diagnoseCommand(): Command {\n const cmd = new Command('diagnose');\n cmd\n .description(\n 'Project-level health report: lint + lineage smells + object smells + cost smells, with reasoning.',\n )\n .requiredOption('--source <path>', '.ddtproj or .ddtpac to analyze.')\n .option(\n '--category <c>',\n 'Filter to one category: lint | lineage | smell | cost | dim-modeling.',\n )\n .option(\n '--min-severity <s>',\n 'Filter to a minimum severity: error | warning | info. Default info (everything).',\n 'info',\n )\n .option(\n '--format <fmt>',\n 'table | json | markdown | sarif. sarif emits SARIF 2.1.0 for GitHub code-scanning / Azure DevOps. Default table.',\n 'table',\n )\n .option('-o, --out <path>', 'Output file path. Defaults to stdout.')\n .action(\n async (opts: {\n source: string;\n category?: string;\n minSeverity?: string;\n format?: string;\n out?: string;\n explain?: boolean;\n }) => {\n const sourcePath = String(opts.source);\n const model = await loadModel(sourcePath);\n const report = diagnostics.analyzeProject(model, {\n source: sourcePath,\n ...(opts.category\n ? { category: String(opts.category) as diagnostics.DiagnosticCategory }\n : {}),\n ...(opts.minSeverity\n ? { minSeverity: String(opts.minSeverity) as diagnostics.DiagnosticSeverity }\n : {}),\n });\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n let payload: string;\n if (fmt === 'json') {\n payload = JSON.stringify(report, null, 2);\n } else if (fmt === 'markdown') {\n payload = renderReportMarkdown(report);\n } else if (fmt === 'sarif') {\n payload = JSON.stringify(interop.diagnosticReportToSarif(report), null, 2);\n } else if (fmt === 'table') {\n payload = diagnostics.formatReport(report);\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown | sarif.`);\n }\n\n if (opts.out) {\n const out = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, payload + (payload.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(\n `Wrote ${out} (${payload.length} bytes, ${report.findings.length} finding(s)).`,\n );\n } else {\n process.stdout.write(payload + (payload.endsWith('\\n') ? '' : '\\n'));\n }\n\n if (report.totals.error > 0) process.exitCode = 1;\n\n await runExplain({ feature: 'diagnose.explain' }, opts, () => buildDiagnosePrompt(report));\n },\n );\n attachExplainFlag(cmd);\n return cmd;\n}\n\nfunction buildDiagnosePrompt(report: diagnostics.DiagnosticReport): string {\n const lines: string[] = [];\n lines.push(`Source: ${report.source || '(unknown)'}`);\n lines.push(\n `Totals: ${report.totals.error} error, ${report.totals.warning} warning, ${report.totals.info} info`,\n );\n lines.push('');\n const top = report.findings\n .slice()\n .sort((a, b) => sevWeight(b.severity) - sevWeight(a.severity))\n .slice(0, 40);\n lines.push(`Top ${top.length} findings (highest severity first):`);\n for (const d of top) {\n lines.push(`- [${d.severity}] ${d.id} · ${d.fqn || '(project)'} — ${d.message}`);\n }\n if (report.findings.length > top.length) {\n lines.push(`(… ${report.findings.length - top.length} more truncated)`);\n }\n lines.push('');\n lines.push(\n 'Explain the dominant themes, what they suggest about the project health, and the highest-leverage fixes the team should tackle first.',\n );\n return lines.join('\\n');\n}\n\nfunction sevWeight(s: diagnostics.DiagnosticSeverity): number {\n return s === 'error' ? 3 : s === 'warning' ? 2 : 1;\n}\n\nfunction renderReportMarkdown(report: diagnostics.DiagnosticReport): string {\n const lines: string[] = [];\n lines.push(`# Diagnostic report — \\`${report.source || '(no source)'}\\``);\n lines.push('');\n lines.push(`Generated: ${report.generatedAt}`);\n lines.push('');\n lines.push(\n `**Totals:** ${report.totals.error} error · ${report.totals.warning} warning · ${report.totals.info} info`,\n );\n lines.push('');\n lines.push('## By category');\n lines.push('');\n lines.push('| Category | Count |');\n lines.push('|---|---|');\n for (const [k, v] of Object.entries(report.byCategory)) {\n if (v > 0) lines.push(`| ${k} | ${v} |`);\n }\n lines.push('');\n if (report.findings.length === 0) {\n lines.push('_No findings._');\n return lines.join('\\n');\n }\n lines.push('## Findings');\n lines.push('');\n for (const d of report.findings) {\n const glyph = d.severity === 'error' ? '🛑' : d.severity === 'warning' ? '⚠️' : 'ℹ️';\n lines.push(`### ${glyph} \\`${d.id}\\` — ${d.fqn || '(project)'}`);\n lines.push('');\n lines.push(`**${d.message}**`);\n lines.push('');\n lines.push(`*Why:* ${d.reasoning}`);\n lines.push('');\n lines.push(`*Suggestion:* ${d.suggestion}`);\n lines.push('');\n if (d.related && d.related.length > 0) {\n lines.push(\n `*Related:* ${d.related\n .slice(0, 5)\n .map((r) => `\\`${r}\\``)\n .join(', ')}`,\n );\n lines.push('');\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadModel(sourcePath: string): Promise<DatabricksObject[]> {\n if (sourcePath.endsWith('.ddtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await loadProject(sourcePath);\n return await parseProjectModel(loaded);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,78 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
3
+ // src/commands/discover.ts
4
+ import { rmSync } from "fs";
5
+ import { join } from "path";
6
+ import { homedir } from "os";
7
+ import { Command } from "commander";
8
+ import chalk from "chalk";
9
+ import { FeatureAdvisor, DDT_HINT_RULES } from "@ddt-tools/core/discovery";
10
+ var IMPORTANT_COMMANDS = [
11
+ "build",
12
+ "publish",
13
+ "compare",
14
+ "drift",
15
+ "lint",
16
+ "extract",
17
+ "safety",
18
+ "verify",
19
+ "validate",
20
+ "script"
21
+ ];
22
+ function discoverCommand() {
23
+ const cmd = new Command("discover");
24
+ cmd.description("Show personalized feature suggestions based on your usage history.").option("--reset", "Clear usage history and start fresh.").action((opts) => {
25
+ if (opts.reset) {
26
+ try {
27
+ rmSync(join(homedir(), ".ddt", "discovery.json"), { force: true });
28
+ } catch {
29
+ }
30
+ console.log(chalk.dim(" Discovery history cleared."));
31
+ return;
32
+ }
33
+ const advisor = new FeatureAdvisor("ddt", DDT_HINT_RULES);
34
+ const stats = advisor.getUsageStats();
35
+ const total = Object.values(stats).reduce((a, b) => a + b, 0);
36
+ console.log("");
37
+ console.log(chalk.bold(" Feature Discovery") + chalk.dim(" \u2014 based on your usage history"));
38
+ console.log("");
39
+ if (total === 0) {
40
+ console.log(
41
+ chalk.dim(
42
+ " No usage recorded yet. Run a few ddt commands to get personalized suggestions.\n"
43
+ )
44
+ );
45
+ console.log(chalk.dim(" Quick start:"));
46
+ console.log(` ${chalk.cyan("ddt init")} initialize a new project`);
47
+ console.log(` ${chalk.cyan("ddt build")} build a .ddtpac artifact`);
48
+ console.log(` ${chalk.cyan("ddt compare")} compare project vs. Unity Catalog`);
49
+ console.log("");
50
+ console.log(chalk.dim(" ddt features list \xB7 ddt explain <topic>"));
51
+ console.log("");
52
+ return;
53
+ }
54
+ const tried = IMPORTANT_COMMANDS.filter((c) => (stats[c] ?? 0) > 0);
55
+ const untried = IMPORTANT_COMMANDS.filter((c) => (stats[c] ?? 0) === 0);
56
+ if (tried.length > 0) {
57
+ console.log(chalk.dim(" Commands you use:"));
58
+ const sorted = [...tried].sort((a, b) => (stats[b] ?? 0) - (stats[a] ?? 0));
59
+ for (const c of sorted) {
60
+ console.log(` ${chalk.green("\u2714")} ddt ${c.padEnd(14)} ${chalk.dim(`${stats[c]}\xD7`)}`);
61
+ }
62
+ console.log("");
63
+ }
64
+ if (untried.length > 0) {
65
+ console.log(chalk.dim(" Worth exploring:"));
66
+ for (const c of untried) {
67
+ console.log(` ${chalk.yellow("\u2192")} ${chalk.cyan(`ddt ${c}`)}`);
68
+ }
69
+ console.log("");
70
+ }
71
+ console.log(chalk.dim(" ddt features list \xB7 ddt explain <topic>\n"));
72
+ });
73
+ return cmd;
74
+ }
75
+ export {
76
+ discoverCommand
77
+ };
78
+ //# sourceMappingURL=discover-DEO2R5T6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/discover.ts"],"sourcesContent":["import { rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { FeatureAdvisor, DDT_HINT_RULES } from '@ddt-tools/core/discovery';\n\nconst IMPORTANT_COMMANDS = [\n 'build',\n 'publish',\n 'compare',\n 'drift',\n 'lint',\n 'extract',\n 'safety',\n 'verify',\n 'validate',\n 'script',\n];\n\nexport function discoverCommand(): Command {\n const cmd = new Command('discover');\n cmd\n .description('Show personalized feature suggestions based on your usage history.')\n .option('--reset', 'Clear usage history and start fresh.')\n .action((opts) => {\n if (opts.reset as boolean) {\n try {\n rmSync(join(homedir(), '.ddt', 'discovery.json'), { force: true });\n } catch {\n /* ignore */\n }\n console.log(chalk.dim(' Discovery history cleared.'));\n return;\n }\n\n const advisor = new FeatureAdvisor('ddt', DDT_HINT_RULES);\n const stats = advisor.getUsageStats();\n const total = Object.values(stats).reduce((a, b) => a + b, 0);\n\n console.log('');\n console.log(chalk.bold(' Feature Discovery') + chalk.dim(' — based on your usage history'));\n console.log('');\n\n if (total === 0) {\n console.log(\n chalk.dim(\n ' No usage recorded yet. Run a few ddt commands to get personalized suggestions.\\n',\n ),\n );\n console.log(chalk.dim(' Quick start:'));\n console.log(` ${chalk.cyan('ddt init')} initialize a new project`);\n console.log(` ${chalk.cyan('ddt build')} build a .ddtpac artifact`);\n console.log(` ${chalk.cyan('ddt compare')} compare project vs. Unity Catalog`);\n console.log('');\n console.log(chalk.dim(' ddt features list · ddt explain <topic>'));\n console.log('');\n return;\n }\n\n const tried = IMPORTANT_COMMANDS.filter((c) => (stats[c] ?? 0) > 0);\n const untried = IMPORTANT_COMMANDS.filter((c) => (stats[c] ?? 0) === 0);\n\n if (tried.length > 0) {\n console.log(chalk.dim(' Commands you use:'));\n const sorted = [...tried].sort((a, b) => (stats[b] ?? 0) - (stats[a] ?? 0));\n for (const c of sorted) {\n console.log(` ${chalk.green('✔')} ddt ${c.padEnd(14)} ${chalk.dim(`${stats[c]}×`)}`);\n }\n console.log('');\n }\n\n if (untried.length > 0) {\n console.log(chalk.dim(' Worth exploring:'));\n for (const c of untried) {\n console.log(` ${chalk.yellow('→')} ${chalk.cyan(`ddt ${c}`)}`);\n }\n console.log('');\n }\n\n console.log(chalk.dim(' ddt features list · ddt explain <topic>\\n'));\n });\n return cmd;\n}\n"],"mappings":";;;AAAA,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,eAAe;AACxB,OAAO,WAAW;AAClB,SAAS,gBAAgB,sBAAsB;AAE/C,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,kBAA2B;AACzC,QAAM,MAAM,IAAI,QAAQ,UAAU;AAClC,MACG,YAAY,oEAAoE,EAChF,OAAO,WAAW,sCAAsC,EACxD,OAAO,CAAC,SAAS;AAChB,QAAI,KAAK,OAAkB;AACzB,UAAI;AACF,eAAO,KAAK,QAAQ,GAAG,QAAQ,gBAAgB,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,MACnE,QAAQ;AAAA,MAER;AACA,cAAQ,IAAI,MAAM,IAAI,8BAA8B,CAAC;AACrD;AAAA,IACF;AAEA,UAAM,UAAU,IAAI,eAAe,OAAO,cAAc;AACxD,UAAM,QAAQ,QAAQ,cAAc;AACpC,UAAM,QAAQ,OAAO,OAAO,KAAK,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAE5D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,MAAM,KAAK,qBAAqB,IAAI,MAAM,IAAI,qCAAgC,CAAC;AAC3F,YAAQ,IAAI,EAAE;AAEd,QAAI,UAAU,GAAG;AACf,cAAQ;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AACA,cAAQ,IAAI,MAAM,IAAI,gBAAgB,CAAC;AACvC,cAAQ,IAAI,OAAO,MAAM,KAAK,UAAU,CAAC,uCAAuC;AAChF,cAAQ,IAAI,OAAO,MAAM,KAAK,WAAW,CAAC,sCAAsC;AAChF,cAAQ,IAAI,OAAO,MAAM,KAAK,aAAa,CAAC,6CAA6C;AACzF,cAAQ,IAAI,EAAE;AACd,cAAQ,IAAI,MAAM,IAAI,8CAA2C,CAAC;AAClE,cAAQ,IAAI,EAAE;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,mBAAmB,OAAO,CAAC,OAAO,MAAM,CAAC,KAAK,KAAK,CAAC;AAClE,UAAM,UAAU,mBAAmB,OAAO,CAAC,OAAO,MAAM,CAAC,KAAK,OAAO,CAAC;AAEtE,QAAI,MAAM,SAAS,GAAG;AACpB,cAAQ,IAAI,MAAM,IAAI,qBAAqB,CAAC;AAC5C,YAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,OAAO,MAAM,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,EAAE;AAC1E,iBAAW,KAAK,QAAQ;AACtB,gBAAQ,IAAI,OAAO,MAAM,MAAM,QAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,IAAI,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,MAAG,CAAC,EAAE;AAAA,MACxF;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,QAAI,QAAQ,SAAS,GAAG;AACtB,cAAQ,IAAI,MAAM,IAAI,oBAAoB,CAAC;AAC3C,iBAAW,KAAK,SAAS;AACvB,gBAAQ,IAAI,OAAO,MAAM,OAAO,QAAG,CAAC,IAAI,MAAM,KAAK,OAAO,CAAC,EAAE,CAAC,EAAE;AAAA,MAClE;AACA,cAAQ,IAAI,EAAE;AAAA,IAChB;AAEA,YAAQ,IAAI,MAAM,IAAI,gDAA6C,CAAC;AAAA,EACtE,CAAC;AACH,SAAO;AACT;","names":[]}
@@ -0,0 +1,183 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
3
+ // src/commands/docs.ts
4
+ import { promises as fs } from "fs";
5
+ import { execSync } from "child_process";
6
+ import path from "path";
7
+ import { Command } from "commander";
8
+ import {
9
+ loadProject,
10
+ parseProjectModel,
11
+ renderDocsReport,
12
+ renderErdMarkdown,
13
+ renderErd3dHtml,
14
+ pac,
15
+ ai,
16
+ comments
17
+ } from "@ddt-tools/core";
18
+ import { buildDocsPublishPlan, renderDocsWorkflowYaml, searchDocs } from "@ddt-tools/core/docs";
19
+ function docsCommand() {
20
+ const cmd = new Command("docs");
21
+ cmd.description("Generate HTML schema docs from a .ddtproj or .ddtpac.").requiredOption("--source <path>", ".ddtproj or .ddtpac to document.").option("-o, --out <path>", "Output HTML file path (omit when using --augment-comments).").option("--title <text>", "Page title.", "Schema docs").option(
22
+ "--augment-comments",
23
+ "Skip HTML rendering. Instead, call the configured AI provider to suggest comments for every empty COMMENT slot and emit COMMENT ON / ALTER COLUMN SQL.",
24
+ false
25
+ ).option(
26
+ "--augment-out <path>",
27
+ "When --augment-comments is set, write the script here. Default ./augment-comments.sql."
28
+ ).option(
29
+ "--augment-max-calls <n>",
30
+ "When --augment-comments is set, cap AI calls. Default unbounded.",
31
+ (v) => parseInt(v, 10)
32
+ ).option(
33
+ "--augment-max-length <n>",
34
+ "When --augment-comments is set, cap suggestion length in characters. Default 200.",
35
+ (v) => parseInt(v, 10)
36
+ ).action(
37
+ async (opts) => {
38
+ const model = await loadModel(String(opts.source));
39
+ if (opts.augmentComments) {
40
+ const targets = comments.findMissingComments(model);
41
+ if (targets.length === 0) {
42
+ console.log("No missing COMMENT slots found. Nothing to augment.");
43
+ return;
44
+ }
45
+ console.log(`Found ${targets.length} missing comment slot(s). Calling AI provider\u2026`);
46
+ const suggestions = await comments.augmentComments(targets, {
47
+ completeFn: async (prompt) => {
48
+ const r = await ai.complete([{ role: "user", content: prompt }], {
49
+ feature: "docs.augment-comments"
50
+ });
51
+ return r.text;
52
+ },
53
+ ...opts.augmentMaxLength ? { maxCommentLength: opts.augmentMaxLength } : {},
54
+ ...opts.augmentMaxCalls ? { maxCalls: opts.augmentMaxCalls } : {}
55
+ });
56
+ const sql = comments.renderAlterCommentScript(suggestions);
57
+ const accepted = suggestions.filter((s) => s.suggestion.trim().length > 0).length;
58
+ const uncertain = suggestions.length - accepted;
59
+ const outPath2 = opts.augmentOut ? path.resolve(String(opts.augmentOut)) : path.resolve("augment-comments.sql");
60
+ await fs.mkdir(path.dirname(outPath2), { recursive: true });
61
+ await fs.writeFile(outPath2, sql, "utf8");
62
+ console.log(
63
+ `Wrote ${outPath2} (${accepted} suggestion(s), ${uncertain} flagged for review).`
64
+ );
65
+ return;
66
+ }
67
+ if (!opts.out) {
68
+ throw new Error("Missing --out. Required unless --augment-comments is set.");
69
+ }
70
+ const html = renderDocsReport(model, { title: String(opts.title ?? "Schema docs") });
71
+ const outPath = path.resolve(String(opts.out));
72
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
73
+ await fs.writeFile(outPath, html, "utf8");
74
+ console.log(`Wrote ${outPath} (${html.length} bytes, ${model.length} objects).`);
75
+ }
76
+ );
77
+ cmd.command("build").description(
78
+ "Build the HTML schema docs site (alias for the parent command with --out default)."
79
+ ).requiredOption("--source <path>", ".ddtproj or .ddtpac to document.").option("-o, --out <path>", "Output HTML file path.", "dist/docs/index.html").option("--title <text>", "Page title.", "Schema docs").action(async (opts) => {
80
+ const model = await loadModel(String(opts.source));
81
+ const html = renderDocsReport(model, { title: String(opts.title ?? "Schema docs") });
82
+ const outPath = path.resolve(String(opts.out));
83
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
84
+ await fs.writeFile(outPath, html, "utf8");
85
+ console.log(`Wrote ${outPath} (${html.length} bytes, ${model.length} objects).`);
86
+ });
87
+ cmd.command("publish").description("Publish the generated docs site to a gh-pages branch.").requiredOption("--site <path>", "Path to the built docs site directory (e.g. dist/docs).").option("--branch <name>", "Target branch name.", "gh-pages").option("--remote <name>", "Git remote name.", "origin").option("--message <text>", "Commit message.", "chore(docs): deploy schema docs [skip ci]").option("--dry-run", "Print the commands that would be executed without running them.", false).option("--emit-workflow <path>", "Write a GitHub Actions workflow YAML template to this path.").action(async (opts) => {
88
+ if (opts.emitWorkflow) {
89
+ const yaml = renderDocsWorkflowYaml({ branch: opts.branch, trigger: "main" });
90
+ const wPath = path.resolve(String(opts.emitWorkflow));
91
+ await fs.mkdir(path.dirname(wPath), { recursive: true });
92
+ await fs.writeFile(wPath, yaml, "utf8");
93
+ console.log(`Wrote workflow template \u2192 ${wPath}`);
94
+ return;
95
+ }
96
+ const plan = buildDocsPublishPlan({
97
+ siteDir: path.resolve(String(opts.site)),
98
+ branch: opts.branch,
99
+ remote: opts.remote,
100
+ message: opts.message
101
+ });
102
+ for (const step of plan.steps) {
103
+ console.log(` ${step.description}`);
104
+ if (opts.dryRun) {
105
+ console.log(` [dry-run] ${step.command}`);
106
+ } else {
107
+ execSync(step.command, { stdio: "inherit" });
108
+ }
109
+ }
110
+ if (!opts.dryRun) console.log(`Done \u2014 site pushed to ${plan.remote}/${plan.branch}.`);
111
+ });
112
+ cmd.command("search").description("Search object names, comments, and column names in a .ddtproj or .ddtpac.").argument("<query>", "Search query string.").requiredOption("--source <path>", ".ddtproj or .ddtpac to search.").option("-n, --max-results <n>", "Maximum number of results to return.", (v) => parseInt(v, 10)).action(async (query, opts) => {
113
+ const model = await loadModel(String(opts.source));
114
+ const hits = searchDocs(model, query, {
115
+ maxResults: opts.maxResults
116
+ });
117
+ if (hits.length === 0) {
118
+ console.log(`No results for "${query}".`);
119
+ return;
120
+ }
121
+ for (const hit of hits) {
122
+ console.log(`[${hit.score}] ${hit.objectFqn} (${hit.objectType}) \u2014 ${hit.field}`);
123
+ console.log(` ${hit.snippet}`);
124
+ }
125
+ console.log(`
126
+ ${hits.length} result(s) for "${query}".`);
127
+ });
128
+ return cmd;
129
+ }
130
+ function erdCommand() {
131
+ const cmd = new Command("erd");
132
+ cmd.description(
133
+ "Generate an ER diagram (Mermaid Markdown or interactive 3D HTML) from a .ddtproj or .ddtpac."
134
+ ).requiredOption("--source <path>", ".ddtproj or .ddtpac to diagram.").requiredOption(
135
+ "-o, --out <path>",
136
+ "Output file path. Format inferred from extension (.md \u2192 mermaid, .html \u2192 html3d) unless --format is given."
137
+ ).option("--title <text>", "Diagram title.", "Schema ER diagram").option(
138
+ "--format <fmt>",
139
+ "Output format: mermaid | html3d. Default: inferred from --out extension, falling back to mermaid."
140
+ ).action(async (opts) => {
141
+ const model = await loadModel(String(opts.source));
142
+ const title = String(opts.title ?? "Schema ER diagram");
143
+ const fmt = resolveErdFormat(String(opts.out), opts.format);
144
+ let content;
145
+ if (fmt === "html3d") {
146
+ content = renderErd3dHtml(model, { title });
147
+ } else {
148
+ content = renderErdMarkdown(model, title);
149
+ }
150
+ const outPath = path.resolve(String(opts.out));
151
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
152
+ await fs.writeFile(outPath, content, "utf8");
153
+ console.log(
154
+ `Wrote ${outPath} (${content.length} bytes, ${model.length} objects, format=${fmt}).`
155
+ );
156
+ });
157
+ return cmd;
158
+ }
159
+ function resolveErdFormat(outPath, explicit) {
160
+ if (explicit) {
161
+ const e = explicit.toLowerCase();
162
+ if (e === "mermaid" || e === "md") return "mermaid";
163
+ if (e === "html3d" || e === "3d" || e === "html") return "html3d";
164
+ throw new Error(`Unknown --format "${explicit}". Expected: mermaid | html3d.`);
165
+ }
166
+ const ext = outPath.toLowerCase();
167
+ if (ext.endsWith(".html") || ext.endsWith(".htm")) return "html3d";
168
+ return "mermaid";
169
+ }
170
+ async function loadModel(sourcePath) {
171
+ if (sourcePath.endsWith(".ddtpac")) {
172
+ const pacContents = await pac.readPac(sourcePath);
173
+ return pacContents.model;
174
+ }
175
+ const loaded = await loadProject(sourcePath);
176
+ const parsed = await parseProjectModel(loaded);
177
+ return parsed;
178
+ }
179
+ export {
180
+ docsCommand,
181
+ erdCommand
182
+ };
183
+ //# sourceMappingURL=docs-QNY3MUVO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/docs.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n loadProject,\n parseProjectModel,\n renderDocsReport,\n renderErdMarkdown,\n renderErd3dHtml,\n pac,\n ai,\n comments,\n type DatabricksObject,\n} from '@ddt-tools/core';\nimport { buildDocsPublishPlan, renderDocsWorkflowYaml, searchDocs } from '@ddt-tools/core/docs';\n\n/**\n * `ddt docs` — auto-generate HTML schema docs from a `.ddtproj` or\n * `.ddtpac`. dbt-docs-style: catalog → schema → object navigation with\n * per-object detail panels.\n */\nexport function docsCommand(): Command {\n const cmd = new Command('docs');\n cmd\n .description('Generate HTML schema docs from a .ddtproj or .ddtpac.')\n .requiredOption('--source <path>', '.ddtproj or .ddtpac to document.')\n .option('-o, --out <path>', 'Output HTML file path (omit when using --augment-comments).')\n .option('--title <text>', 'Page title.', 'Schema docs')\n .option(\n '--augment-comments',\n 'Skip HTML rendering. Instead, call the configured AI provider to suggest comments for every empty COMMENT slot and emit COMMENT ON / ALTER COLUMN SQL.',\n false,\n )\n .option(\n '--augment-out <path>',\n 'When --augment-comments is set, write the script here. Default ./augment-comments.sql.',\n )\n .option(\n '--augment-max-calls <n>',\n 'When --augment-comments is set, cap AI calls. Default unbounded.',\n (v) => parseInt(v, 10),\n )\n .option(\n '--augment-max-length <n>',\n 'When --augment-comments is set, cap suggestion length in characters. Default 200.',\n (v) => parseInt(v, 10),\n )\n .action(\n async (opts: {\n source: string;\n out?: string;\n title?: string;\n augmentComments?: boolean;\n augmentOut?: string;\n augmentMaxCalls?: number;\n augmentMaxLength?: number;\n }) => {\n const model = await loadModel(String(opts.source));\n\n if (opts.augmentComments) {\n const targets = comments.findMissingComments(model);\n if (targets.length === 0) {\n console.log('No missing COMMENT slots found. Nothing to augment.');\n return;\n }\n console.log(`Found ${targets.length} missing comment slot(s). Calling AI provider…`);\n const suggestions = await comments.augmentComments(targets, {\n completeFn: async (prompt: string) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'docs.augment-comments',\n });\n return r.text;\n },\n ...(opts.augmentMaxLength ? { maxCommentLength: opts.augmentMaxLength } : {}),\n ...(opts.augmentMaxCalls ? { maxCalls: opts.augmentMaxCalls } : {}),\n });\n const sql = comments.renderAlterCommentScript(suggestions);\n const accepted = suggestions.filter((s) => s.suggestion.trim().length > 0).length;\n const uncertain = suggestions.length - accepted;\n const outPath = opts.augmentOut\n ? path.resolve(String(opts.augmentOut))\n : path.resolve('augment-comments.sql');\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, sql, 'utf8');\n console.log(\n `Wrote ${outPath} (${accepted} suggestion(s), ${uncertain} flagged for review).`,\n );\n return;\n }\n\n if (!opts.out) {\n throw new Error('Missing --out. Required unless --augment-comments is set.');\n }\n const html = renderDocsReport(model, { title: String(opts.title ?? 'Schema docs') });\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, html, 'utf8');\n console.log(`Wrote ${outPath} (${html.length} bytes, ${model.length} objects).`);\n },\n );\n\n cmd\n .command('build')\n .description(\n 'Build the HTML schema docs site (alias for the parent command with --out default).',\n )\n .requiredOption('--source <path>', '.ddtproj or .ddtpac to document.')\n .option('-o, --out <path>', 'Output HTML file path.', 'dist/docs/index.html')\n .option('--title <text>', 'Page title.', 'Schema docs')\n .action(async (opts: { source: string; out: string; title?: string }) => {\n const model = await loadModel(String(opts.source));\n const html = renderDocsReport(model, { title: String(opts.title ?? 'Schema docs') });\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, html, 'utf8');\n console.log(`Wrote ${outPath} (${html.length} bytes, ${model.length} objects).`);\n });\n\n cmd\n .command('publish')\n .description('Publish the generated docs site to a gh-pages branch.')\n .requiredOption('--site <path>', 'Path to the built docs site directory (e.g. dist/docs).')\n .option('--branch <name>', 'Target branch name.', 'gh-pages')\n .option('--remote <name>', 'Git remote name.', 'origin')\n .option('--message <text>', 'Commit message.', 'chore(docs): deploy schema docs [skip ci]')\n .option('--dry-run', 'Print the commands that would be executed without running them.', false)\n .option('--emit-workflow <path>', 'Write a GitHub Actions workflow YAML template to this path.')\n .action(async (opts) => {\n if (opts.emitWorkflow) {\n const yaml = renderDocsWorkflowYaml({ branch: opts.branch, trigger: 'main' });\n const wPath = path.resolve(String(opts.emitWorkflow));\n await fs.mkdir(path.dirname(wPath), { recursive: true });\n await fs.writeFile(wPath, yaml, 'utf8');\n console.log(`Wrote workflow template → ${wPath}`);\n return;\n }\n const plan = buildDocsPublishPlan({\n siteDir: path.resolve(String(opts.site)),\n branch: opts.branch,\n remote: opts.remote,\n message: opts.message,\n });\n for (const step of plan.steps) {\n console.log(` ${step.description}`);\n if (opts.dryRun) {\n console.log(` [dry-run] ${step.command}`);\n } else {\n execSync(step.command, { stdio: 'inherit' });\n }\n }\n if (!opts.dryRun) console.log(`Done — site pushed to ${plan.remote}/${plan.branch}.`);\n });\n\n cmd\n .command('search')\n .description('Search object names, comments, and column names in a .ddtproj or .ddtpac.')\n .argument('<query>', 'Search query string.')\n .requiredOption('--source <path>', '.ddtproj or .ddtpac to search.')\n .option('-n, --max-results <n>', 'Maximum number of results to return.', (v) => parseInt(v, 10))\n .action(async (query: string, opts: { source: string; maxResults?: number }) => {\n const model = await loadModel(String(opts.source));\n const hits = searchDocs(model as Parameters<typeof searchDocs>[0], query, {\n maxResults: opts.maxResults,\n });\n if (hits.length === 0) {\n console.log(`No results for \"${query}\".`);\n return;\n }\n for (const hit of hits) {\n console.log(`[${hit.score}] ${hit.objectFqn} (${hit.objectType}) — ${hit.field}`);\n console.log(` ${hit.snippet}`);\n }\n console.log(`\\n${hits.length} result(s) for \"${query}\".`);\n });\n\n return cmd;\n}\n\n/**\n * `ddt erd` — auto-generate an ER diagram from a `.ddtproj` or `.ddtpac`.\n *\n * Output format defaults to Mermaid Markdown for back-compat. Pass\n * `--format html3d` (or write to a `.html` file) to emit the interactive\n * 3D WebGL viewer — a single self-contained HTML file you can open in\n * any browser. The 3D viewer lays out schemas as horizontal planes with\n * tables as boxes and FKs as bezier curves; supports click-to-focus,\n * search, 2D toggle, and full orbit/pan/zoom. See DIAG-1 spec.\n */\nexport function erdCommand(): Command {\n const cmd = new Command('erd');\n cmd\n .description(\n 'Generate an ER diagram (Mermaid Markdown or interactive 3D HTML) from a .ddtproj or .ddtpac.',\n )\n .requiredOption('--source <path>', '.ddtproj or .ddtpac to diagram.')\n .requiredOption(\n '-o, --out <path>',\n 'Output file path. Format inferred from extension (.md → mermaid, .html → html3d) unless --format is given.',\n )\n .option('--title <text>', 'Diagram title.', 'Schema ER diagram')\n .option(\n '--format <fmt>',\n 'Output format: mermaid | html3d. Default: inferred from --out extension, falling back to mermaid.',\n )\n .action(async (opts: { source: string; out: string; title?: string; format?: string }) => {\n const model = await loadModel(String(opts.source));\n const title = String(opts.title ?? 'Schema ER diagram');\n const fmt = resolveErdFormat(String(opts.out), opts.format);\n let content: string;\n if (fmt === 'html3d') {\n content = renderErd3dHtml(model, { title });\n } else {\n content = renderErdMarkdown(model, title);\n }\n const outPath = path.resolve(String(opts.out));\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, content, 'utf8');\n console.log(\n `Wrote ${outPath} (${content.length} bytes, ${model.length} objects, format=${fmt}).`,\n );\n });\n return cmd;\n}\n\nfunction resolveErdFormat(outPath: string, explicit?: string): 'mermaid' | 'html3d' {\n if (explicit) {\n const e = explicit.toLowerCase();\n if (e === 'mermaid' || e === 'md') return 'mermaid';\n if (e === 'html3d' || e === '3d' || e === 'html') return 'html3d';\n throw new Error(`Unknown --format \"${explicit}\". Expected: mermaid | html3d.`);\n }\n const ext = outPath.toLowerCase();\n if (ext.endsWith('.html') || ext.endsWith('.htm')) return 'html3d';\n return 'mermaid';\n}\n\nasync function loadModel(sourcePath: string): Promise<DatabricksObject[]> {\n if (sourcePath.endsWith('.ddtpac')) {\n const pacContents = await pac.readPac(sourcePath);\n return pacContents.model;\n }\n const loaded = await loadProject(sourcePath);\n const parsed = await parseProjectModel(loaded);\n return parsed as DatabricksObject[];\n}\n"],"mappings":"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","names":["outPath"]}