@sdt-tools/cli 0.2.0 → 0.2.6

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 (207) hide show
  1. package/dist/advise-tests-6DRSZMBL.js +87 -0
  2. package/dist/advise-tests-6DRSZMBL.js.map +1 -0
  3. package/dist/ai-G4MJWHTM.js +89 -0
  4. package/dist/ai-G4MJWHTM.js.map +1 -0
  5. package/dist/anonymize-QR6JGXA7.js +123 -0
  6. package/dist/anonymize-QR6JGXA7.js.map +1 -0
  7. package/dist/approval-YVHYTV53.js +73 -0
  8. package/dist/approval-YVHYTV53.js.map +1 -0
  9. package/dist/approval-chain-54KKJZS3.js +120 -0
  10. package/dist/approval-chain-54KKJZS3.js.map +1 -0
  11. package/dist/audit-log-QZFH7LUX.js +159 -0
  12. package/dist/audit-log-QZFH7LUX.js.map +1 -0
  13. package/dist/backlog-V2YUIQDL.js +76 -0
  14. package/dist/backlog-V2YUIQDL.js.map +1 -0
  15. package/dist/bisect-GEVYAVL5.js +111 -0
  16. package/dist/bisect-GEVYAVL5.js.map +1 -0
  17. package/dist/bookmarks-57LKS7P6.js +107 -0
  18. package/dist/bookmarks-57LKS7P6.js.map +1 -0
  19. package/dist/branch-W2MGMPSH.js +88 -0
  20. package/dist/branch-W2MGMPSH.js.map +1 -0
  21. package/dist/build-VNIQFKSP.js +23 -0
  22. package/dist/build-VNIQFKSP.js.map +1 -0
  23. package/dist/catalog-JLB5VCEV.js +137 -0
  24. package/dist/catalog-JLB5VCEV.js.map +1 -0
  25. package/dist/changelog-M7XGDYSY.js +220 -0
  26. package/dist/changelog-M7XGDYSY.js.map +1 -0
  27. package/dist/chunk-DGUM43GV.js +11 -0
  28. package/dist/chunk-DGUM43GV.js.map +1 -0
  29. package/dist/chunk-EWXM4KJN.js +25 -0
  30. package/dist/chunk-EWXM4KJN.js.map +1 -0
  31. package/dist/chunk-JP2EZLR5.js +50 -0
  32. package/dist/chunk-JP2EZLR5.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-ZWY4ZRHL.js +44 -0
  36. package/dist/chunk-ZWY4ZRHL.js.map +1 -0
  37. package/dist/cli.js +511 -19014
  38. package/dist/cli.js.map +1 -1
  39. package/dist/compare-5O6UTWPJ.js +405 -0
  40. package/dist/compare-5O6UTWPJ.js.map +1 -0
  41. package/dist/compare-profiles-7ZSNIW7B.js +218 -0
  42. package/dist/compare-profiles-7ZSNIW7B.js.map +1 -0
  43. package/dist/completion-I5U5VVAX.js +82 -0
  44. package/dist/completion-I5U5VVAX.js.map +1 -0
  45. package/dist/connection-GNTZDHXF.js +133 -0
  46. package/dist/connection-GNTZDHXF.js.map +1 -0
  47. package/dist/cost-estimate-TJDDH6TO.js +328 -0
  48. package/dist/cost-estimate-TJDDH6TO.js.map +1 -0
  49. package/dist/data-compare-UK2UXAS3.js +134 -0
  50. package/dist/data-compare-UK2UXAS3.js.map +1 -0
  51. package/dist/data-fit-Q45ENBRL.js +125 -0
  52. package/dist/data-fit-Q45ENBRL.js.map +1 -0
  53. package/dist/deploy-status-UUHKVDTI.js +58 -0
  54. package/dist/deploy-status-UUHKVDTI.js.map +1 -0
  55. package/dist/design-PO6UPBL7.js +138 -0
  56. package/dist/design-PO6UPBL7.js.map +1 -0
  57. package/dist/diagnose-6IFMELFR.js +145 -0
  58. package/dist/diagnose-6IFMELFR.js.map +1 -0
  59. package/dist/discover-A7OSZAHK.js +78 -0
  60. package/dist/discover-A7OSZAHK.js.map +1 -0
  61. package/dist/docs-CVRKGUSW.js +177 -0
  62. package/dist/docs-CVRKGUSW.js.map +1 -0
  63. package/dist/drift-XDA3BDYN.js +226 -0
  64. package/dist/drift-XDA3BDYN.js.map +1 -0
  65. package/dist/drift-gate-V7QSIOGZ.js +94 -0
  66. package/dist/drift-gate-V7QSIOGZ.js.map +1 -0
  67. package/dist/error-lookup-7ZWCZJ44.js +56 -0
  68. package/dist/error-lookup-7ZWCZJ44.js.map +1 -0
  69. package/dist/errorReporting-AQXKKGZH.js +109 -0
  70. package/dist/errorReporting-AQXKKGZH.js.map +1 -0
  71. package/dist/exec-PKBHLI7T.js +121 -0
  72. package/dist/exec-PKBHLI7T.js.map +1 -0
  73. package/dist/explain-LWKJOTL7.js +192 -0
  74. package/dist/explain-LWKJOTL7.js.map +1 -0
  75. package/dist/explorer-QOVM6VBD.js +61 -0
  76. package/dist/explorer-QOVM6VBD.js.map +1 -0
  77. package/dist/export-IYYBZ5HE.js +42 -0
  78. package/dist/export-IYYBZ5HE.js.map +1 -0
  79. package/dist/extract-VMMVRQVT.js +102 -0
  80. package/dist/extract-VMMVRQVT.js.map +1 -0
  81. package/dist/features-LE6BDZ2S.js +59 -0
  82. package/dist/features-LE6BDZ2S.js.map +1 -0
  83. package/dist/feedback-M7DM2EQC.js +161 -0
  84. package/dist/feedback-M7DM2EQC.js.map +1 -0
  85. package/dist/find-EME2JG2I.js +176 -0
  86. package/dist/find-EME2JG2I.js.map +1 -0
  87. package/dist/format-TRLWLMGS.js +141 -0
  88. package/dist/format-TRLWLMGS.js.map +1 -0
  89. package/dist/generate-6NAZGZDV.js +152 -0
  90. package/dist/generate-6NAZGZDV.js.map +1 -0
  91. package/dist/graph-QNQDAUO7.js +161 -0
  92. package/dist/graph-QNQDAUO7.js.map +1 -0
  93. package/dist/history-RONA7ZTI.js +199 -0
  94. package/dist/history-RONA7ZTI.js.map +1 -0
  95. package/dist/hosts-YBXY2ZG5.js +49 -0
  96. package/dist/hosts-YBXY2ZG5.js.map +1 -0
  97. package/dist/impact-T2JSANHS.js +59 -0
  98. package/dist/impact-T2JSANHS.js.map +1 -0
  99. package/dist/import-AELYLY6A.js +32 -0
  100. package/dist/import-AELYLY6A.js.map +1 -0
  101. package/dist/import-script-2OF5BI6A.js +83 -0
  102. package/dist/import-script-2OF5BI6A.js.map +1 -0
  103. package/dist/index.cjs +71 -12
  104. package/dist/index.cjs.map +1 -1
  105. package/dist/index.js +95 -31
  106. package/dist/index.js.map +1 -1
  107. package/dist/init-SWRRJMGI.js +57 -0
  108. package/dist/init-SWRRJMGI.js.map +1 -0
  109. package/dist/install-hooks-6SIAGTAF.js +109 -0
  110. package/dist/install-hooks-6SIAGTAF.js.map +1 -0
  111. package/dist/license-OAF22PLZ.js +46 -0
  112. package/dist/license-OAF22PLZ.js.map +1 -0
  113. package/dist/lineage-EW66XJ6O.js +552 -0
  114. package/dist/lineage-EW66XJ6O.js.map +1 -0
  115. package/dist/lint-FQ2OTYTQ.js +143 -0
  116. package/dist/lint-FQ2OTYTQ.js.map +1 -0
  117. package/dist/mcp-SARDMCDV.js +344 -0
  118. package/dist/mcp-SARDMCDV.js.map +1 -0
  119. package/dist/migrate-from-dbt-JVTXPWKQ.js +156 -0
  120. package/dist/migrate-from-dbt-JVTXPWKQ.js.map +1 -0
  121. package/dist/migrate-platform-NTRTOGNR.js +91 -0
  122. package/dist/migrate-platform-NTRTOGNR.js.map +1 -0
  123. package/dist/optimize-CJYWMAWA.js +105 -0
  124. package/dist/optimize-CJYWMAWA.js.map +1 -0
  125. package/dist/perf-LL2CPCJF.js +205 -0
  126. package/dist/perf-LL2CPCJF.js.map +1 -0
  127. package/dist/pii-FBDRDQ2E.js +136 -0
  128. package/dist/pii-FBDRDQ2E.js.map +1 -0
  129. package/dist/pilot-CCQERKPH.js +29 -0
  130. package/dist/pilot-CCQERKPH.js.map +1 -0
  131. package/dist/pr-comment-S5FF4QRX.js +79 -0
  132. package/dist/pr-comment-S5FF4QRX.js.map +1 -0
  133. package/dist/preview-5U4YVCRM.js +47 -0
  134. package/dist/preview-5U4YVCRM.js.map +1 -0
  135. package/dist/profile-7VC57KD2.js +101 -0
  136. package/dist/profile-7VC57KD2.js.map +1 -0
  137. package/dist/promote-AASEFTIA.js +408 -0
  138. package/dist/promote-AASEFTIA.js.map +1 -0
  139. package/dist/publish-UMVIWH6H.js +721 -0
  140. package/dist/publish-UMVIWH6H.js.map +1 -0
  141. package/dist/purge-QMXZKCMD.js +57 -0
  142. package/dist/purge-QMXZKCMD.js.map +1 -0
  143. package/dist/query-log-6OM4GI7W.js +112 -0
  144. package/dist/query-log-6OM4GI7W.js.map +1 -0
  145. package/dist/refactor-LTZQLJ35.js +5799 -0
  146. package/dist/refactor-LTZQLJ35.js.map +1 -0
  147. package/dist/refresh-4TY2AGOU.js +38 -0
  148. package/dist/refresh-4TY2AGOU.js.map +1 -0
  149. package/dist/replay-OOC25FZN.js +117 -0
  150. package/dist/replay-OOC25FZN.js.map +1 -0
  151. package/dist/revert-ODMUVJW6.js +110 -0
  152. package/dist/revert-ODMUVJW6.js.map +1 -0
  153. package/dist/review-XXPWOBFP.js +158 -0
  154. package/dist/review-XXPWOBFP.js.map +1 -0
  155. package/dist/rollback-suggest-6G2HEKFR.js +79 -0
  156. package/dist/rollback-suggest-6G2HEKFR.js.map +1 -0
  157. package/dist/safer-alternative-QFVNLG3L.js +89 -0
  158. package/dist/safer-alternative-QFVNLG3L.js.map +1 -0
  159. package/dist/safety-7QWRSUEZ.js +168 -0
  160. package/dist/safety-7QWRSUEZ.js.map +1 -0
  161. package/dist/savings-RHIXP6IT.js +95 -0
  162. package/dist/savings-RHIXP6IT.js.map +1 -0
  163. package/dist/scan-secrets-5YCQ4UCU.js +54 -0
  164. package/dist/scan-secrets-5YCQ4UCU.js.map +1 -0
  165. package/dist/schema-CIZXCQD2.js +429 -0
  166. package/dist/schema-CIZXCQD2.js.map +1 -0
  167. package/dist/script-K7CIN2P6.js +153 -0
  168. package/dist/script-K7CIN2P6.js.map +1 -0
  169. package/dist/search-BUZ5NXZZ.js +151 -0
  170. package/dist/search-BUZ5NXZZ.js.map +1 -0
  171. package/dist/seed-76QAK276.js +96 -0
  172. package/dist/seed-76QAK276.js.map +1 -0
  173. package/dist/sketch-PTLKDIK3.js +88 -0
  174. package/dist/sketch-PTLKDIK3.js.map +1 -0
  175. package/dist/snapshot-XLPR2OZ5.js +177 -0
  176. package/dist/snapshot-XLPR2OZ5.js.map +1 -0
  177. package/dist/snippets-EK4DK5CN.js +74 -0
  178. package/dist/snippets-EK4DK5CN.js.map +1 -0
  179. package/dist/standards-7T2UY6DD.js +241 -0
  180. package/dist/standards-7T2UY6DD.js.map +1 -0
  181. package/dist/suggest-VGRYSAR6.js +39 -0
  182. package/dist/suggest-VGRYSAR6.js.map +1 -0
  183. package/dist/suggest-constraints-MY5WKUHA.js +160 -0
  184. package/dist/suggest-constraints-MY5WKUHA.js.map +1 -0
  185. package/dist/suite-TRNGZWQM.js +88 -0
  186. package/dist/suite-TRNGZWQM.js.map +1 -0
  187. package/dist/telemetry-3U2QLA2S.js +75 -0
  188. package/dist/telemetry-3U2QLA2S.js.map +1 -0
  189. package/dist/template-ZERIXVXF.js +403 -0
  190. package/dist/template-ZERIXVXF.js.map +1 -0
  191. package/dist/test-5M2ED3WT.js +169 -0
  192. package/dist/test-5M2ED3WT.js.map +1 -0
  193. package/dist/trial-U732FONV.js +31 -0
  194. package/dist/trial-U732FONV.js.map +1 -0
  195. package/dist/validate-T6D2WCOK.js +106 -0
  196. package/dist/validate-T6D2WCOK.js.map +1 -0
  197. package/dist/verify-KXVASEEG.js +76 -0
  198. package/dist/verify-KXVASEEG.js.map +1 -0
  199. package/dist/watch-I6K4BNMA.js +80 -0
  200. package/dist/watch-I6K4BNMA.js.map +1 -0
  201. package/dist/xcompare-TPFLQO6W.js +87 -0
  202. package/dist/xcompare-TPFLQO6W.js.map +1 -0
  203. package/package.json +2 -2
  204. package/dist/cli.cjs +0 -19040
  205. package/dist/cli.cjs.map +0 -1
  206. package/dist/cli.d.cts +0 -1
  207. package/dist/cli.d.ts +0 -1
@@ -0,0 +1,429 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
3
+ // src/commands/schema.ts
4
+ import { promises as fs } from "fs";
5
+ import path from "path";
6
+ import { Command } from "commander";
7
+ import { interop, pac, project, schema, validate as validateNs } from "@sdt-tools/core";
8
+ function schemaCommand() {
9
+ const cmd = new Command("schema").description(
10
+ "Interop with third-party schema formats (DBML import/export; draw.io export). NOT a separate data modeler \u2014 SDT remains the canonical model."
11
+ );
12
+ cmd.command("import-dbml <file>").description("Import a DBML file and emit Snowflake CREATE TABLE files.").option("-o, --out <path>", "Output directory. Default ./imported/.").action(async (filePath, opts) => {
13
+ const text = await fs.readFile(path.resolve(String(filePath)), "utf8");
14
+ const doc = schema.parseDbml(text);
15
+ const out = opts.out ? path.resolve(String(opts.out)) : path.resolve("imported");
16
+ await fs.mkdir(out, { recursive: true });
17
+ let written = 0;
18
+ for (const t of doc.tables) {
19
+ const ddl = renderTableDdl(t, doc.refs);
20
+ const dir = path.join(out, "DEMO_DB", t.schema, "Tables");
21
+ await fs.mkdir(dir, { recursive: true });
22
+ const file = path.join(dir, `${t.name}.sql`);
23
+ await fs.writeFile(file, ddl, "utf8");
24
+ written++;
25
+ }
26
+ console.error(`Imported ${written} table(s) from ${filePath} into ${out}.`);
27
+ console.error(`Database name defaulted to DEMO_DB; rename the top-level folder if needed.`);
28
+ console.error(
29
+ `Inferred refs (${doc.refs.length}) were preserved as inline comments \u2014 review and add FOREIGN KEY constraints by hand.`
30
+ );
31
+ });
32
+ cmd.command("export-dbml").description(
33
+ "Emit DBML text from a project model. Lossy projection \u2014 Snowflake-specific features are emitted as comments."
34
+ ).requiredOption("--source <path>", ".sdtproj or .sdtpac to export.").option("-o, --out <path>", "Output file. Defaults to stdout.").action(async (opts) => {
35
+ const model = await loadModel(String(opts.source));
36
+ const text = schema.emitDbml(model);
37
+ await emit(text, opts.out);
38
+ });
39
+ cmd.command("export-drawio").description(
40
+ "Emit a draw.io / diagrams.net XML file from a project model. Open in any diagrams.net editor."
41
+ ).requiredOption("--source <path>", ".sdtproj or .sdtpac to export.").option("-o, --out <path>", "Output file. Defaults to ./schema.drawio.").option(
42
+ "--columns <n>",
43
+ "Grid columns (used when --auto-layout is off). Default 4.",
44
+ (v) => parseInt(v, 10)
45
+ ).option(
46
+ "--auto-layout",
47
+ "Apply force-directed layout \u2014 connected tables cluster together. Default: alphabetical grid."
48
+ ).option(
49
+ "--print",
50
+ "Print-friendly mode: monochrome palette, US Letter landscape page settings."
51
+ ).action(async (opts) => {
52
+ const model = await loadModel(String(opts.source));
53
+ const text = schema.emitDrawio(model, {
54
+ ...typeof opts.columns === "number" ? { columns: opts.columns } : {},
55
+ ...opts.autoLayout ? { autoLayout: true } : {},
56
+ ...opts.print ? { print: true } : {}
57
+ });
58
+ const outPath = opts.out ? path.resolve(String(opts.out)) : path.resolve("schema.drawio");
59
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
60
+ await fs.writeFile(outPath, text, "utf8");
61
+ const flags = [opts.autoLayout && "auto-layout", opts.print && "print-mode"].filter(Boolean).join(", ") || "default";
62
+ console.error(
63
+ `Wrote ${outPath} (${text.length} bytes). Flags: ${flags}. Open in any draw.io / diagrams.net editor.`
64
+ );
65
+ });
66
+ for (const fmt of [
67
+ {
68
+ name: "jsonschema",
69
+ emit: interop.emitJsonSchema,
70
+ ext: "json",
71
+ why: "API contracts, NoSQL, payload validation."
72
+ },
73
+ {
74
+ name: "avro",
75
+ emit: interop.emitAvro,
76
+ ext: "avsc",
77
+ why: "Kafka / streaming pipelines with schema-registry."
78
+ },
79
+ {
80
+ name: "protobuf",
81
+ emit: interop.emitProtobuf,
82
+ ext: "proto",
83
+ why: "gRPC services, cross-language data contracts."
84
+ },
85
+ {
86
+ name: "graphql",
87
+ emit: interop.emitGraphqlSdl,
88
+ ext: "graphql",
89
+ why: "GraphQL APIs that expose the schema."
90
+ },
91
+ {
92
+ name: "plantuml",
93
+ emit: interop.emitPlantumlEr,
94
+ ext: "puml",
95
+ why: "Text-based ER diagrams (alternative to Mermaid)."
96
+ },
97
+ {
98
+ name: "typescript",
99
+ emit: interop.emitTypescript,
100
+ ext: "ts",
101
+ why: "Generate TypeScript interfaces for app code."
102
+ },
103
+ {
104
+ name: "pydantic",
105
+ emit: interop.emitPydantic,
106
+ ext: "py",
107
+ why: "Generate Pydantic models for Python apps."
108
+ },
109
+ { name: "java", emit: interop.emitJavaDto, ext: "java", why: "Generate Java record DTOs." },
110
+ {
111
+ name: "markdown",
112
+ emit: interop.emitMarkdownDocs,
113
+ ext: "md",
114
+ why: "Schema docs rendered by GitHub / GitLab."
115
+ },
116
+ {
117
+ name: "html",
118
+ emit: interop.emitHtmlDocs,
119
+ ext: "html",
120
+ why: "Self-contained schema-docs page for distribution."
121
+ }
122
+ ]) {
123
+ cmd.command(`export-${fmt.name}`).description(`Emit ${fmt.name.toUpperCase()} from the project model. Use: ${fmt.why}`).requiredOption("--source <path>", ".sdtproj or .sdtpac to export.").option("-o, --out <path>", `Output file. Defaults to ./schema.${fmt.ext}.`).action(async (opts) => {
124
+ const model = await loadModel(String(opts.source));
125
+ const text = fmt.emit(model);
126
+ const outPath = opts.out ? path.resolve(String(opts.out)) : path.resolve(`schema.${fmt.ext}`);
127
+ await fs.mkdir(path.dirname(outPath), { recursive: true });
128
+ await fs.writeFile(outPath, text, "utf8");
129
+ console.error(`Wrote ${outPath} (${text.length} bytes).`);
130
+ });
131
+ }
132
+ cmd.command("validate-star").description(
133
+ "Validate a star schema rooted at a fact table. Classifies each connected dim by SCD type, reports FK coverage + naming issues."
134
+ ).requiredOption("--source <path>", ".sdtproj or .sdtpac containing the star.").requiredOption("--root <fqn>", "Fully-qualified fact-table FQN (database.schema.fact_name).").option("--format <fmt>", "table | json | markdown. Default table.", "table").option("-o, --out <path>", "Output file. Defaults to stdout.").action(async (opts) => {
135
+ const model = await loadModel(String(opts.source));
136
+ const report = validateNs.validateStar(model, String(opts.root), {
137
+ source: String(opts.source)
138
+ });
139
+ const fmt = String(opts.format ?? "table").toLowerCase();
140
+ let payload;
141
+ if (fmt === "json") {
142
+ payload = JSON.stringify(report, null, 2);
143
+ } else if (fmt === "markdown") {
144
+ payload = renderStarMarkdown(report);
145
+ } else if (fmt === "table") {
146
+ payload = validateNs.formatStarReport(report);
147
+ } else {
148
+ throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown.`);
149
+ }
150
+ await emit(payload, opts.out);
151
+ if (!report.factExists || report.issues.length > 0) {
152
+ process.exitCode = 1;
153
+ }
154
+ });
155
+ cmd.command("suggest-snowflake-schema").description(
156
+ "Propose snowflake-schema refactors: detect column groups on star dims that look like candidates for extraction (geography, category, org)."
157
+ ).requiredOption("--source <path>", ".sdtproj or .sdtpac containing the star.").requiredOption("--root <fqn>", "Fully-qualified fact-table FQN (database.schema.fact_name).").option("--format <fmt>", "table | json | markdown. Default table.", "table").option("-o, --out <path>", "Output file. Defaults to stdout.").action(async (opts) => {
158
+ const model = await loadModel(String(opts.source));
159
+ const proposal = validateNs.proposeSnowflakeSchema(model, String(opts.root), {
160
+ source: String(opts.source)
161
+ });
162
+ const fmt = String(opts.format ?? "table").toLowerCase();
163
+ let payload;
164
+ if (fmt === "json") {
165
+ payload = JSON.stringify(proposal, null, 2);
166
+ } else if (fmt === "markdown") {
167
+ payload = renderSnowflakeSchemaMarkdown(proposal);
168
+ } else if (fmt === "table") {
169
+ payload = validateNs.formatSnowflakeSchemaProposal(proposal);
170
+ } else {
171
+ throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown.`);
172
+ }
173
+ await emit(payload, opts.out);
174
+ });
175
+ cmd.command("infer-csv <file>").description(
176
+ "Read a CSV sample and emit a Snowflake CREATE TABLE with heuristic type inference. Review before deploy."
177
+ ).requiredOption(
178
+ "--name <fqn>",
179
+ "Fully-qualified table name (database.schema.table or schema.table)."
180
+ ).option("--delimiter <char>", "CSV delimiter. Default: comma.", ",").option(
181
+ "--no-header",
182
+ "Treat the first row as data, not header. Generated column names: column_1, column_2, \u2026"
183
+ ).option("--max-sample-rows <n>", "Cap on rows sampled. Default 1000.", (v) => parseInt(v, 10)).option(
184
+ "--or-replace",
185
+ "Emit CREATE OR REPLACE TABLE instead of CREATE TABLE IF NOT EXISTS.",
186
+ false
187
+ ).option("-o, --out <path>", "Output file. Defaults to stdout.").action(async (filePath, opts) => {
188
+ const text = await fs.readFile(path.resolve(String(filePath)), "utf8");
189
+ const inferred = schema.inferSchemaFromCsv(
190
+ text,
191
+ {
192
+ delimiter: String(opts.delimiter),
193
+ hasHeader: opts.header !== false,
194
+ ...typeof opts.maxSampleRows === "number" ? { maxSampleRows: opts.maxSampleRows } : {}
195
+ },
196
+ path.basename(String(filePath))
197
+ );
198
+ const parts = String(opts.name).split(".").filter(Boolean);
199
+ const fqn = parts.length === 3 ? { database: parts[0], schema: parts[1], name: parts[2] } : parts.length === 2 ? { schema: parts[0], name: parts[1] } : { name: parts[0] ?? "INFERRED_TABLE" };
200
+ const ddl = schema.renderCreateTable(inferred, { fqn, orReplace: !!opts.orReplace });
201
+ await emit(ddl, opts.out);
202
+ console.error(
203
+ `Sampled ${inferred.sampleRowCount} row(s); inferred ${inferred.columns.length} column(s).`
204
+ );
205
+ const allNull = inferred.columns.filter((c) => c.allNull);
206
+ if (allNull.length > 0) {
207
+ console.error(
208
+ `Warning: ${allNull.length} column(s) had no values in the sample \u2014 types defaulted to VARCHAR. Review the generated DDL.`
209
+ );
210
+ }
211
+ });
212
+ cmd.command("infer-parquet <file>").description(
213
+ "Read a Parquet file's metadata footer and emit a Snowflake CREATE TABLE. No data is read \u2014 only the schema header."
214
+ ).requiredOption(
215
+ "--name <fqn>",
216
+ "Fully-qualified table name (database.schema.table or schema.table)."
217
+ ).option(
218
+ "--or-replace",
219
+ "Emit CREATE OR REPLACE TABLE instead of CREATE TABLE IF NOT EXISTS.",
220
+ false
221
+ ).option("-o, --out <path>", "Output file. Defaults to stdout.").action(async (filePath, opts) => {
222
+ const buf = await fs.readFile(path.resolve(String(filePath)));
223
+ const inferred = await schema.inferSchemaFromParquet(buf, path.basename(String(filePath)));
224
+ const parts = String(opts.name).split(".").filter(Boolean);
225
+ const fqn = parts.length === 3 ? { database: parts[0], schema: parts[1], name: parts[2] } : parts.length === 2 ? { schema: parts[0], name: parts[1] } : { name: parts[0] ?? "INFERRED_TABLE" };
226
+ const ddl = schema.renderCreateTable(inferred, { fqn, orReplace: !!opts.orReplace });
227
+ await emit(ddl, opts.out);
228
+ console.error(
229
+ `Parquet schema: ${inferred.columns.length} column(s); reported ${inferred.sampleRowCount} row(s) in metadata.`
230
+ );
231
+ });
232
+ cmd.command("import-ddl <file>").description(
233
+ 'Universal DDL importer \u2014 parse any CREATE TABLE statements (erwin / ER/Studio / PowerDesigner / DbSchema / Hackolade / Visio / DataGrip all "Forward Engineer to Script"; we read it).'
234
+ ).option("-o, --out <path>", "Output directory. Default ./imported/.").action(async (filePath, opts) => {
235
+ const text = await fs.readFile(path.resolve(String(filePath)), "utf8");
236
+ const result = interop.parseUniversalDdl(text);
237
+ await writeImportedTables(
238
+ result,
239
+ opts.out ? path.resolve(String(opts.out)) : path.resolve("imported")
240
+ );
241
+ });
242
+ cmd.command("import-jsonschema <file>").description("Import a JSON Schema document; each top-level object schema becomes a table.").option("-o, --out <path>", "Output directory. Default ./imported/.").action(async (filePath, opts) => {
243
+ const text = await fs.readFile(path.resolve(String(filePath)), "utf8");
244
+ const result = interop.parseJsonSchema(text);
245
+ await writeImportedTables(
246
+ result,
247
+ opts.out ? path.resolve(String(opts.out)) : path.resolve("imported")
248
+ );
249
+ });
250
+ cmd.command("import-dbt <file>").description(
251
+ "Import a dbt-generated manifest.json (or catalog.json); each model/seed/source becomes a table."
252
+ ).option("-o, --out <path>", "Output directory. Default ./imported/.").action(async (filePath, opts) => {
253
+ const text = await fs.readFile(path.resolve(String(filePath)), "utf8");
254
+ const result = interop.parseDbtManifest(text);
255
+ await writeImportedTables(
256
+ result,
257
+ opts.out ? path.resolve(String(opts.out)) : path.resolve("imported")
258
+ );
259
+ });
260
+ return cmd;
261
+ }
262
+ async function writeImportedTables(result, outDir) {
263
+ await fs.mkdir(outDir, { recursive: true });
264
+ let written = 0;
265
+ for (const t of result.tables) {
266
+ const db = t.database ?? "DEMO_DB";
267
+ const sch = t.schema ?? "PUBLIC";
268
+ const dir = path.join(outDir, db, sch, "Tables");
269
+ await fs.mkdir(dir, { recursive: true });
270
+ const file = path.join(dir, `${t.name}.sql`);
271
+ const colDdl = t.columns.map((c) => {
272
+ const mods = [];
273
+ if (c.nullable === false) mods.push("NOT NULL");
274
+ if (c.default) mods.push(`DEFAULT ${c.default}`);
275
+ if (c.primaryKey) mods.push("PRIMARY KEY");
276
+ return ` ${c.name.padEnd(28)} ${snowflakeType(c.dataType)}${mods.length > 0 ? " " + mods.join(" ") : ""}${c.comment ? ` COMMENT '${c.comment.replace(/'/g, "''")}'` : ""}`;
277
+ }).join(",\n");
278
+ const ddl = `-- Imported by \`sdt schema import-*\` from source: ${result.source}.
279
+ -- Review and refine; SDT is the canonical model from here on.
280
+
281
+ CREATE OR ALTER TABLE ${db}.${sch}.${t.name} (
282
+ ${colDdl}
283
+ )${t.comment ? `
284
+ COMMENT = '${t.comment.replace(/'/g, "''")}'` : ""};
285
+ `;
286
+ await fs.writeFile(file, ddl, "utf8");
287
+ written++;
288
+ }
289
+ console.error(`Imported ${written} table(s) into ${outDir}.`);
290
+ if (result.warnings.length > 0) {
291
+ console.error("Warnings (review before deploy):");
292
+ for (const w of result.warnings) console.error(` - ${w}`);
293
+ }
294
+ }
295
+ function snowflakeType(dbmlType) {
296
+ const t = dbmlType.toLowerCase().trim();
297
+ if (t === "int" || t === "integer" || t === "serial") return "NUMBER(38,0)";
298
+ if (t === "bigint") return "NUMBER(38,0)";
299
+ if (t === "smallint") return "NUMBER(5,0)";
300
+ if (t === "decimal" || t === "numeric") return "NUMBER(38,9)";
301
+ if (t === "float" || t === "double") return "FLOAT";
302
+ if (t === "boolean" || t === "bool") return "BOOLEAN";
303
+ if (t === "date") return "DATE";
304
+ if (t === "datetime" || t === "timestamp" || t === "timestamp_ntz") return "TIMESTAMP_NTZ";
305
+ if (t === "time") return "TIME";
306
+ if (t.startsWith("varchar") || t.startsWith("number")) return dbmlType.toUpperCase();
307
+ if (t === "text" || t === "string") return "VARCHAR";
308
+ if (t === "json" || t === "jsonb" || t === "variant") return "VARIANT";
309
+ if (t === "array") return "ARRAY";
310
+ if (t === "uuid") return "VARCHAR(36)";
311
+ return dbmlType.toUpperCase();
312
+ }
313
+ function renderTableDdl(t, refs) {
314
+ const lines = [];
315
+ lines.push(`-- Imported from DBML by \`sdt schema import-dbml\`.`);
316
+ lines.push(`-- Review and refine; SDT is the canonical model from here on.`);
317
+ if (t.note) lines.push(`-- ${t.note}`);
318
+ lines.push("");
319
+ const colDdl = t.columns.map((c) => {
320
+ const mods = [];
321
+ if (c.notNull) mods.push("NOT NULL");
322
+ if (c.default) mods.push(`DEFAULT ${c.default}`);
323
+ if (c.pk) mods.push("PRIMARY KEY");
324
+ return ` ${c.name.padEnd(28)} ${snowflakeType(c.type)}${mods.length > 0 ? " " + mods.join(" ") : ""}${c.note ? ` COMMENT '${c.note.replace(/'/g, "''")}'` : ""}`;
325
+ });
326
+ const tableRefs = refs.filter(
327
+ (r) => r.from.toLowerCase().startsWith(`${t.schema.toLowerCase()}.${t.name.toLowerCase()}.`)
328
+ );
329
+ if (tableRefs.length > 0) {
330
+ lines.push(`-- Inferred references (review before adding as FOREIGN KEY constraints):`);
331
+ for (const r of tableRefs) lines.push(`-- ${r.from} ${r.cardinality} ${r.to}`);
332
+ lines.push("");
333
+ }
334
+ lines.push(`CREATE OR ALTER TABLE DEMO_DB.${t.schema}.${t.name} (`);
335
+ lines.push(colDdl.join(",\n"));
336
+ lines.push(")");
337
+ if (t.note) lines.push(`COMMENT = '${t.note.replace(/'/g, "''")}'`);
338
+ lines.push(";\n");
339
+ return lines.join("\n");
340
+ }
341
+ function renderSnowflakeSchemaMarkdown(p) {
342
+ const lines = [];
343
+ lines.push(`# Snowflake-schema refactor proposal \u2014 \`${p.fact}\``);
344
+ lines.push("");
345
+ lines.push(`Generated: ${p.generatedAt}`);
346
+ if (p.source) lines.push(`Source: \`${p.source}\``);
347
+ lines.push("");
348
+ if (!p.factExists) {
349
+ lines.push(`**Fact not found in the project.**`);
350
+ return lines.join("\n");
351
+ }
352
+ if (p.dims.length === 0) {
353
+ lines.push("_No refactor candidates detected._");
354
+ return lines.join("\n");
355
+ }
356
+ for (const d of p.dims) {
357
+ lines.push(`## \`${d.dim}\` (${d.scdType})`);
358
+ lines.push("");
359
+ for (const g of d.groups) {
360
+ lines.push(`### ${g.kind} \u2014 columns: \`${g.columns.join("`, `")}\``);
361
+ lines.push("");
362
+ if (g.proposedDim) {
363
+ lines.push(`**Proposal:** extract to \`${g.proposedDim}\`.`);
364
+ } else {
365
+ lines.push(`**Proposal:** keep on parent dim (audit metadata).`);
366
+ }
367
+ lines.push("");
368
+ lines.push(`*Why:* ${g.reasoning}`);
369
+ lines.push("");
370
+ }
371
+ }
372
+ return lines.join("\n");
373
+ }
374
+ function renderStarMarkdown(report) {
375
+ const lines = [];
376
+ lines.push(`# Star validation \u2014 \`${report.fact}\``);
377
+ lines.push("");
378
+ lines.push(`Generated: ${report.generatedAt}`);
379
+ if (report.source) lines.push(`Source: \`${report.source}\``);
380
+ lines.push("");
381
+ if (!report.factExists) {
382
+ lines.push(`**${report.issues[0]}**`);
383
+ return lines.join("\n");
384
+ }
385
+ lines.push(
386
+ `**Fan-out:** ${report.fanOut} \xB7 **CLUSTER BY:** ${report.clusterBy.length > 0 ? report.clusterBy.join(", ") : "_none_"}`
387
+ );
388
+ lines.push("");
389
+ if (report.dimensions.length > 0) {
390
+ lines.push("## Dimensions");
391
+ lines.push("");
392
+ lines.push("| Dim | SCD Type | Business Key | Notes |");
393
+ lines.push("| --- | --- | --- | --- |");
394
+ for (const d of report.dimensions) {
395
+ lines.push(
396
+ `| \`${d.fqn}\` | ${d.scdType} | ${d.bk ? `\`${d.bk}\`` : "_none_"} | ${d.reasons.join("; ")} |`
397
+ );
398
+ }
399
+ lines.push("");
400
+ }
401
+ if (report.issues.length > 0) {
402
+ lines.push("## Issues");
403
+ lines.push("");
404
+ for (const i of report.issues) lines.push(`- \u26A0\uFE0F ${i}`);
405
+ }
406
+ return lines.join("\n");
407
+ }
408
+ async function loadModel(sourcePath) {
409
+ if (sourcePath.endsWith(".sdtpac")) {
410
+ const c = await pac.readPac(sourcePath);
411
+ return c.model;
412
+ }
413
+ const loaded = await project.loadProject(sourcePath);
414
+ return await project.parseProjectModel(loaded);
415
+ }
416
+ async function emit(text, out) {
417
+ if (out) {
418
+ const p = path.resolve(String(out));
419
+ await fs.mkdir(path.dirname(p), { recursive: true });
420
+ await fs.writeFile(p, text + (text.endsWith("\n") ? "" : "\n"), "utf8");
421
+ console.error(`Wrote ${p}.`);
422
+ } else {
423
+ process.stdout.write(text + (text.endsWith("\n") ? "" : "\n"));
424
+ }
425
+ }
426
+ export {
427
+ schemaCommand
428
+ };
429
+ //# sourceMappingURL=schema-CIZXCQD2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/schema.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { interop, pac, project, schema, validate as validateNs } from '@sdt-tools/core';\n\n/**\n * `sdt schema` — interop with third-party schema-modeling formats.\n *\n * **What this is**: a thin import/export bridge between `.sdtproj`\n * and well-known interchange formats (DBML, draw.io XML). It exists\n * so users coming from `dbdiagram.io`, draw.io, or other modelers\n * can drop their work into SDT — and vice versa.\n *\n * **What this is NOT**: erwin Data Modeler, ER/Studio, DbSchema, or\n * Hackolade. We do not contain or redistribute any code from those\n * products. See root `NOTICE` for the interop attribution and the\n * \"what this product is NOT\" statement.\n *\n * Subcommands:\n * - `import-dbml <file>` — read a DBML file, emit `.sql` files\n * into <out>/.\n * - `export-dbml --source <pac|proj>` — emit DBML text from a\n * project model.\n * - `export-drawio --source <pac|proj>` — emit a `.drawio` XML\n * file ready to open in any diagrams.net editor.\n */\nexport function schemaCommand(): Command {\n const cmd = new Command('schema').description(\n 'Interop with third-party schema formats (DBML import/export; draw.io export). NOT a separate data modeler — SDT remains the canonical model.',\n );\n\n cmd\n .command('import-dbml <file>')\n .description('Import a DBML file and emit Snowflake CREATE TABLE files.')\n .option('-o, --out <path>', 'Output directory. Default ./imported/.')\n .action(async (filePath, opts) => {\n const text = await fs.readFile(path.resolve(String(filePath)), 'utf8');\n const doc = schema.parseDbml(text);\n const out = opts.out ? path.resolve(String(opts.out)) : path.resolve('imported');\n await fs.mkdir(out, { recursive: true });\n let written = 0;\n for (const t of doc.tables) {\n const ddl = renderTableDdl(t, doc.refs);\n const dir = path.join(out, 'DEMO_DB', t.schema, 'Tables');\n await fs.mkdir(dir, { recursive: true });\n const file = path.join(dir, `${t.name}.sql`);\n await fs.writeFile(file, ddl, 'utf8');\n written++;\n }\n console.error(`Imported ${written} table(s) from ${filePath} into ${out}.`);\n console.error(`Database name defaulted to DEMO_DB; rename the top-level folder if needed.`);\n console.error(\n `Inferred refs (${doc.refs.length}) were preserved as inline comments — review and add FOREIGN KEY constraints by hand.`,\n );\n });\n\n cmd\n .command('export-dbml')\n .description(\n 'Emit DBML text from a project model. Lossy projection — Snowflake-specific features are emitted as comments.',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to export.')\n .option('-o, --out <path>', 'Output file. Defaults to stdout.')\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const text = schema.emitDbml(model);\n await emit(text, opts.out);\n });\n\n cmd\n .command('export-drawio')\n .description(\n 'Emit a draw.io / diagrams.net XML file from a project model. Open in any diagrams.net editor.',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to export.')\n .option('-o, --out <path>', 'Output file. Defaults to ./schema.drawio.')\n .option('--columns <n>', 'Grid columns (used when --auto-layout is off). Default 4.', (v) =>\n parseInt(v, 10),\n )\n .option(\n '--auto-layout',\n 'Apply force-directed layout — connected tables cluster together. Default: alphabetical grid.',\n )\n .option(\n '--print',\n 'Print-friendly mode: monochrome palette, US Letter landscape page settings.',\n )\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const text = schema.emitDrawio(model, {\n ...(typeof opts.columns === 'number' ? { columns: opts.columns } : {}),\n ...(opts.autoLayout ? { autoLayout: true } : {}),\n ...(opts.print ? { print: true } : {}),\n });\n const outPath = opts.out ? path.resolve(String(opts.out)) : path.resolve('schema.drawio');\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, text, 'utf8');\n const flags =\n [opts.autoLayout && 'auto-layout', opts.print && 'print-mode'].filter(Boolean).join(', ') ||\n 'default';\n console.error(\n `Wrote ${outPath} (${text.length} bytes). Flags: ${flags}. Open in any draw.io / diagrams.net editor.`,\n );\n });\n\n // ─── Multi-format emitters (Phase A of the interop wave) ───\n for (const fmt of [\n {\n name: 'jsonschema',\n emit: interop.emitJsonSchema,\n ext: 'json',\n why: 'API contracts, NoSQL, payload validation.',\n },\n {\n name: 'avro',\n emit: interop.emitAvro,\n ext: 'avsc',\n why: 'Kafka / streaming pipelines with schema-registry.',\n },\n {\n name: 'protobuf',\n emit: interop.emitProtobuf,\n ext: 'proto',\n why: 'gRPC services, cross-language data contracts.',\n },\n {\n name: 'graphql',\n emit: interop.emitGraphqlSdl,\n ext: 'graphql',\n why: 'GraphQL APIs that expose the schema.',\n },\n {\n name: 'plantuml',\n emit: interop.emitPlantumlEr,\n ext: 'puml',\n why: 'Text-based ER diagrams (alternative to Mermaid).',\n },\n {\n name: 'typescript',\n emit: interop.emitTypescript,\n ext: 'ts',\n why: 'Generate TypeScript interfaces for app code.',\n },\n {\n name: 'pydantic',\n emit: interop.emitPydantic,\n ext: 'py',\n why: 'Generate Pydantic models for Python apps.',\n },\n { name: 'java', emit: interop.emitJavaDto, ext: 'java', why: 'Generate Java record DTOs.' },\n {\n name: 'markdown',\n emit: interop.emitMarkdownDocs,\n ext: 'md',\n why: 'Schema docs rendered by GitHub / GitLab.',\n },\n {\n name: 'html',\n emit: interop.emitHtmlDocs,\n ext: 'html',\n why: 'Self-contained schema-docs page for distribution.',\n },\n ]) {\n cmd\n .command(`export-${fmt.name}`)\n .description(`Emit ${fmt.name.toUpperCase()} from the project model. Use: ${fmt.why}`)\n .requiredOption('--source <path>', '.sdtproj or .sdtpac to export.')\n .option('-o, --out <path>', `Output file. Defaults to ./schema.${fmt.ext}.`)\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const text = fmt.emit(model);\n const outPath = opts.out\n ? path.resolve(String(opts.out))\n : path.resolve(`schema.${fmt.ext}`);\n await fs.mkdir(path.dirname(outPath), { recursive: true });\n await fs.writeFile(outPath, text, 'utf8');\n console.error(`Wrote ${outPath} (${text.length} bytes).`);\n });\n }\n\n // ─── Star-schema validator ───\n cmd\n .command('validate-star')\n .description(\n 'Validate a star schema rooted at a fact table. Classifies each connected dim by SCD type, reports FK coverage + naming issues.',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac containing the star.')\n .requiredOption('--root <fqn>', 'Fully-qualified fact-table FQN (database.schema.fact_name).')\n .option('--format <fmt>', 'table | json | markdown. Default table.', 'table')\n .option('-o, --out <path>', 'Output file. Defaults to stdout.')\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const report = validateNs.validateStar(model, String(opts.root), {\n source: String(opts.source),\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 = renderStarMarkdown(report);\n } else if (fmt === 'table') {\n payload = validateNs.formatStarReport(report);\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown.`);\n }\n await emit(payload, opts.out);\n\n // Non-zero exit when the fact wasn't found or there are issues — CI-gateable.\n if (!report.factExists || report.issues.length > 0) {\n process.exitCode = 1;\n }\n });\n\n // ─── Snowflake-schema refactor proposer ───\n cmd\n .command('suggest-snowflake-schema')\n .description(\n 'Propose snowflake-schema refactors: detect column groups on star dims that look like candidates for extraction (geography, category, org).',\n )\n .requiredOption('--source <path>', '.sdtproj or .sdtpac containing the star.')\n .requiredOption('--root <fqn>', 'Fully-qualified fact-table FQN (database.schema.fact_name).')\n .option('--format <fmt>', 'table | json | markdown. Default table.', 'table')\n .option('-o, --out <path>', 'Output file. Defaults to stdout.')\n .action(async (opts) => {\n const model = await loadModel(String(opts.source));\n const proposal = validateNs.proposeSnowflakeSchema(model, String(opts.root), {\n source: String(opts.source),\n });\n\n const fmt = String(opts.format ?? 'table').toLowerCase();\n let payload: string;\n if (fmt === 'json') {\n payload = JSON.stringify(proposal, null, 2);\n } else if (fmt === 'markdown') {\n payload = renderSnowflakeSchemaMarkdown(proposal);\n } else if (fmt === 'table') {\n payload = validateNs.formatSnowflakeSchemaProposal(proposal);\n } else {\n throw new Error(`Unknown --format: ${fmt}. Use table | json | markdown.`);\n }\n await emit(payload, opts.out);\n });\n\n // ─── Sample-data → CREATE TABLE inference ───\n cmd\n .command('infer-csv <file>')\n .description(\n 'Read a CSV sample and emit a Snowflake CREATE TABLE with heuristic type inference. Review before deploy.',\n )\n .requiredOption(\n '--name <fqn>',\n 'Fully-qualified table name (database.schema.table or schema.table).',\n )\n .option('--delimiter <char>', 'CSV delimiter. Default: comma.', ',')\n .option(\n '--no-header',\n 'Treat the first row as data, not header. Generated column names: column_1, column_2, …',\n )\n .option('--max-sample-rows <n>', 'Cap on rows sampled. Default 1000.', (v) => parseInt(v, 10))\n .option(\n '--or-replace',\n 'Emit CREATE OR REPLACE TABLE instead of CREATE TABLE IF NOT EXISTS.',\n false,\n )\n .option('-o, --out <path>', 'Output file. Defaults to stdout.')\n .action(async (filePath, opts) => {\n const text = await fs.readFile(path.resolve(String(filePath)), 'utf8');\n const inferred = schema.inferSchemaFromCsv(\n text,\n {\n delimiter: String(opts.delimiter),\n hasHeader: opts.header !== false,\n ...(typeof opts.maxSampleRows === 'number' ? { maxSampleRows: opts.maxSampleRows } : {}),\n },\n path.basename(String(filePath)),\n );\n const parts = String(opts.name).split('.').filter(Boolean);\n const fqn =\n parts.length === 3\n ? { database: parts[0]!, schema: parts[1]!, name: parts[2]! }\n : parts.length === 2\n ? { schema: parts[0]!, name: parts[1]! }\n : { name: parts[0] ?? 'INFERRED_TABLE' };\n const ddl = schema.renderCreateTable(inferred, { fqn, orReplace: !!opts.orReplace });\n await emit(ddl, opts.out);\n console.error(\n `Sampled ${inferred.sampleRowCount} row(s); inferred ${inferred.columns.length} column(s).`,\n );\n const allNull = inferred.columns.filter((c) => c.allNull);\n if (allNull.length > 0) {\n console.error(\n `Warning: ${allNull.length} column(s) had no values in the sample — types defaulted to VARCHAR. Review the generated DDL.`,\n );\n }\n });\n\n cmd\n .command('infer-parquet <file>')\n .description(\n \"Read a Parquet file's metadata footer and emit a Snowflake CREATE TABLE. No data is read — only the schema header.\",\n )\n .requiredOption(\n '--name <fqn>',\n 'Fully-qualified table name (database.schema.table or schema.table).',\n )\n .option(\n '--or-replace',\n 'Emit CREATE OR REPLACE TABLE instead of CREATE TABLE IF NOT EXISTS.',\n false,\n )\n .option('-o, --out <path>', 'Output file. Defaults to stdout.')\n .action(async (filePath, opts) => {\n const buf = await fs.readFile(path.resolve(String(filePath)));\n const inferred = await schema.inferSchemaFromParquet(buf, path.basename(String(filePath)));\n const parts = String(opts.name).split('.').filter(Boolean);\n const fqn =\n parts.length === 3\n ? { database: parts[0]!, schema: parts[1]!, name: parts[2]! }\n : parts.length === 2\n ? { schema: parts[0]!, name: parts[1]! }\n : { name: parts[0] ?? 'INFERRED_TABLE' };\n const ddl = schema.renderCreateTable(inferred, { fqn, orReplace: !!opts.orReplace });\n await emit(ddl, opts.out);\n console.error(\n `Parquet schema: ${inferred.columns.length} column(s); reported ${inferred.sampleRowCount} row(s) in metadata.`,\n );\n });\n\n // ─── Multi-format importers ───\n cmd\n .command('import-ddl <file>')\n .description(\n 'Universal DDL importer — parse any CREATE TABLE statements (erwin / ER/Studio / PowerDesigner / DbSchema / Hackolade / Visio / DataGrip all \"Forward Engineer to Script\"; we read it).',\n )\n .option('-o, --out <path>', 'Output directory. Default ./imported/.')\n .action(async (filePath, opts) => {\n const text = await fs.readFile(path.resolve(String(filePath)), 'utf8');\n const result = interop.parseUniversalDdl(text);\n await writeImportedTables(\n result,\n opts.out ? path.resolve(String(opts.out)) : path.resolve('imported'),\n );\n });\n\n cmd\n .command('import-jsonschema <file>')\n .description('Import a JSON Schema document; each top-level object schema becomes a table.')\n .option('-o, --out <path>', 'Output directory. Default ./imported/.')\n .action(async (filePath, opts) => {\n const text = await fs.readFile(path.resolve(String(filePath)), 'utf8');\n const result = interop.parseJsonSchema(text);\n await writeImportedTables(\n result,\n opts.out ? path.resolve(String(opts.out)) : path.resolve('imported'),\n );\n });\n\n cmd\n .command('import-dbt <file>')\n .description(\n 'Import a dbt-generated manifest.json (or catalog.json); each model/seed/source becomes a table.',\n )\n .option('-o, --out <path>', 'Output directory. Default ./imported/.')\n .action(async (filePath, opts) => {\n const text = await fs.readFile(path.resolve(String(filePath)), 'utf8');\n const result = interop.parseDbtManifest(text);\n await writeImportedTables(\n result,\n opts.out ? path.resolve(String(opts.out)) : path.resolve('imported'),\n );\n });\n\n return cmd;\n}\n\nasync function writeImportedTables(result: interop.ImportResult, outDir: string): Promise<void> {\n await fs.mkdir(outDir, { recursive: true });\n let written = 0;\n for (const t of result.tables) {\n const db = t.database ?? 'DEMO_DB';\n const sch = t.schema ?? 'PUBLIC';\n const dir = path.join(outDir, db, sch, 'Tables');\n await fs.mkdir(dir, { recursive: true });\n const file = path.join(dir, `${t.name}.sql`);\n const colDdl = t.columns\n .map((c) => {\n const mods: string[] = [];\n if (c.nullable === false) mods.push('NOT NULL');\n if (c.default) mods.push(`DEFAULT ${c.default}`);\n if (c.primaryKey) mods.push('PRIMARY KEY');\n return ` ${c.name.padEnd(28)} ${snowflakeType(c.dataType)}${mods.length > 0 ? ' ' + mods.join(' ') : ''}${c.comment ? ` COMMENT '${c.comment.replace(/'/g, \"''\")}'` : ''}`;\n })\n .join(',\\n');\n const ddl = `-- Imported by \\`sdt schema import-*\\` from source: ${result.source}.\\n-- Review and refine; SDT is the canonical model from here on.\\n\\nCREATE OR ALTER TABLE ${db}.${sch}.${t.name} (\\n${colDdl}\\n)${t.comment ? `\\nCOMMENT = '${t.comment.replace(/'/g, \"''\")}'` : ''};\\n`;\n await fs.writeFile(file, ddl, 'utf8');\n written++;\n }\n console.error(`Imported ${written} table(s) into ${outDir}.`);\n if (result.warnings.length > 0) {\n console.error('Warnings (review before deploy):');\n for (const w of result.warnings) console.error(` - ${w}`);\n }\n}\n\nfunction snowflakeType(dbmlType: string): string {\n const t = dbmlType.toLowerCase().trim();\n if (t === 'int' || t === 'integer' || t === 'serial') return 'NUMBER(38,0)';\n if (t === 'bigint') return 'NUMBER(38,0)';\n if (t === 'smallint') return 'NUMBER(5,0)';\n if (t === 'decimal' || t === 'numeric') return 'NUMBER(38,9)';\n if (t === 'float' || t === 'double') return 'FLOAT';\n if (t === 'boolean' || t === 'bool') return 'BOOLEAN';\n if (t === 'date') return 'DATE';\n if (t === 'datetime' || t === 'timestamp' || t === 'timestamp_ntz') return 'TIMESTAMP_NTZ';\n if (t === 'time') return 'TIME';\n if (t.startsWith('varchar') || t.startsWith('number')) return dbmlType.toUpperCase();\n if (t === 'text' || t === 'string') return 'VARCHAR';\n if (t === 'json' || t === 'jsonb' || t === 'variant') return 'VARIANT';\n if (t === 'array') return 'ARRAY';\n if (t === 'uuid') return 'VARCHAR(36)';\n return dbmlType.toUpperCase();\n}\n\nfunction renderTableDdl(t: schema.DbmlTable, refs: readonly schema.DbmlRef[]): string {\n const lines: string[] = [];\n lines.push(`-- Imported from DBML by \\`sdt schema import-dbml\\`.`);\n lines.push(`-- Review and refine; SDT is the canonical model from here on.`);\n if (t.note) lines.push(`-- ${t.note}`);\n lines.push('');\n const colDdl = t.columns.map((c) => {\n const mods: string[] = [];\n if (c.notNull) mods.push('NOT NULL');\n if (c.default) mods.push(`DEFAULT ${c.default}`);\n if (c.pk) mods.push('PRIMARY KEY');\n return ` ${c.name.padEnd(28)} ${snowflakeType(c.type)}${mods.length > 0 ? ' ' + mods.join(' ') : ''}${c.note ? ` COMMENT '${c.note.replace(/'/g, \"''\")}'` : ''}`;\n });\n const tableRefs = refs.filter((r) =>\n r.from.toLowerCase().startsWith(`${t.schema.toLowerCase()}.${t.name.toLowerCase()}.`),\n );\n if (tableRefs.length > 0) {\n lines.push(`-- Inferred references (review before adding as FOREIGN KEY constraints):`);\n for (const r of tableRefs) lines.push(`-- ${r.from} ${r.cardinality} ${r.to}`);\n lines.push('');\n }\n lines.push(`CREATE OR ALTER TABLE DEMO_DB.${t.schema}.${t.name} (`);\n lines.push(colDdl.join(',\\n'));\n lines.push(')');\n if (t.note) lines.push(`COMMENT = '${t.note.replace(/'/g, \"''\")}'`);\n lines.push(';\\n');\n return lines.join('\\n');\n}\n\n/**\n * Translate DBML's database-agnostic type names into the closest\n * Snowflake equivalent. Naive — a real translation needs the DBML\n * file's `Project` directive's database setting. This default works\n * for the most common types.\n */\nfunction renderSnowflakeSchemaMarkdown(p: validateNs.SnowflakeSchemaProposal): string {\n const lines: string[] = [];\n lines.push(`# Snowflake-schema refactor proposal — \\`${p.fact}\\``);\n lines.push('');\n lines.push(`Generated: ${p.generatedAt}`);\n if (p.source) lines.push(`Source: \\`${p.source}\\``);\n lines.push('');\n if (!p.factExists) {\n lines.push(`**Fact not found in the project.**`);\n return lines.join('\\n');\n }\n if (p.dims.length === 0) {\n lines.push('_No refactor candidates detected._');\n return lines.join('\\n');\n }\n for (const d of p.dims) {\n lines.push(`## \\`${d.dim}\\` (${d.scdType})`);\n lines.push('');\n for (const g of d.groups) {\n lines.push(`### ${g.kind} — columns: \\`${g.columns.join('`, `')}\\``);\n lines.push('');\n if (g.proposedDim) {\n lines.push(`**Proposal:** extract to \\`${g.proposedDim}\\`.`);\n } else {\n lines.push(`**Proposal:** keep on parent dim (audit metadata).`);\n }\n lines.push('');\n lines.push(`*Why:* ${g.reasoning}`);\n lines.push('');\n }\n }\n return lines.join('\\n');\n}\n\nfunction renderStarMarkdown(report: validateNs.StarValidationReport): string {\n const lines: string[] = [];\n lines.push(`# Star validation — \\`${report.fact}\\``);\n lines.push('');\n lines.push(`Generated: ${report.generatedAt}`);\n if (report.source) lines.push(`Source: \\`${report.source}\\``);\n lines.push('');\n if (!report.factExists) {\n lines.push(`**${report.issues[0]}**`);\n return lines.join('\\n');\n }\n lines.push(\n `**Fan-out:** ${report.fanOut} · **CLUSTER BY:** ${report.clusterBy.length > 0 ? report.clusterBy.join(', ') : '_none_'}`,\n );\n lines.push('');\n if (report.dimensions.length > 0) {\n lines.push('## Dimensions');\n lines.push('');\n lines.push('| Dim | SCD Type | Business Key | Notes |');\n lines.push('| --- | --- | --- | --- |');\n for (const d of report.dimensions) {\n lines.push(\n `| \\`${d.fqn}\\` | ${d.scdType} | ${d.bk ? `\\`${d.bk}\\`` : '_none_'} | ${d.reasons.join('; ')} |`,\n );\n }\n lines.push('');\n }\n if (report.issues.length > 0) {\n lines.push('## Issues');\n lines.push('');\n for (const i of report.issues) lines.push(`- ⚠️ ${i}`);\n }\n return lines.join('\\n');\n}\n\nasync function loadModel(sourcePath: string) {\n if (sourcePath.endsWith('.sdtpac')) {\n const c = await pac.readPac(sourcePath);\n return c.model;\n }\n const loaded = await project.loadProject(sourcePath);\n return await project.parseProjectModel(loaded);\n}\n\nasync function emit(text: string, out: unknown): Promise<void> {\n if (out) {\n const p = path.resolve(String(out));\n await fs.mkdir(path.dirname(p), { recursive: true });\n await fs.writeFile(p, text + (text.endsWith('\\n') ? '' : '\\n'), 'utf8');\n console.error(`Wrote ${p}.`);\n } else {\n process.stdout.write(text + (text.endsWith('\\n') ? '' : '\\n'));\n }\n}\n"],"mappings":"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","names":[]}