@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
package/dist/index.cjs CHANGED
@@ -28,8 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
33
  catalogCommand: () => catalogCommand,
34
34
  compareProfilesCommand: () => compareProfilesCommand,
35
35
  connectionCommand: () => connectionCommand,
@@ -42,20 +42,26 @@ __export(index_exports, {
42
42
  searchCommand: () => searchCommand,
43
43
  sketchCommand: () => sketchCommand
44
44
  });
45
- module.exports = __toCommonJS(index_exports);
45
+ module.exports = __toCommonJS(src_exports);
46
46
 
47
47
  // src/commands/connection.ts
48
48
  var import_commander = require("commander");
49
49
  var import_core = require("@ddt-tools/core");
50
50
  function connectionCommand() {
51
51
  const cmd = new import_commander.Command("connection").description("Manage Databricks connection profiles.");
52
- cmd.command("add <name>").description("Store a new connection profile.").option("--host <host>", "Workspace host, e.g. dbc-12345-abcd.cloud.databricks.com").option("--auth <method>", "One of: pat | oauth-m2m | oauth-u2m | azure-ad | google-idc", "pat").option(
52
+ cmd.command("add [name]").description("Store a new connection profile.").option("--name <name>", "Profile name (flag form of the positional name arg)").option("--host <host>", "Workspace host, e.g. dbc-12345-abcd.cloud.databricks.com").option("--auth <method>", "One of: pat | oauth-m2m | oauth-u2m | azure-ad | google-idc", "pat").option(
53
53
  "--token <token>",
54
54
  "PAT token \u2014 use env:DATABRICKS_TOKEN to reference an env var, never inline a secret"
55
55
  ).option("--client-id <id>", "OAuth M2M / Azure AD client ID").option("--client-secret <secret>", "OAuth M2M / Azure AD client secret").option("--tenant-id <id>", "Azure AD tenant ID").option(
56
56
  "--service-account-key-path <path>",
57
57
  "Path to a GCP service-account key JSON file (for google-idc auth)"
58
- ).requiredOption("--warehouse-id <id>", "SQL warehouse ID for DDL operations").option("--catalog <catalog>", "Default Unity Catalog catalog").option("--schema <schema>", "Default schema").action(async (name, opts) => {
58
+ ).requiredOption("--warehouse-id <id>", "SQL warehouse ID for DDL operations").option("--catalog <catalog>", "Default Unity Catalog catalog").option("--schema <schema>", "Default schema").action(async (nameArg, opts) => {
59
+ const name = opts.name ? String(opts.name) : nameArg ?? "";
60
+ if (!name) {
61
+ throw new Error(
62
+ "connection add needs a profile name \u2014 pass it positionally (`ddt connection add <name>`) or via `--name`."
63
+ );
64
+ }
59
65
  if (!opts.host) throw new Error("--host is required");
60
66
  const auth = buildAuth(opts);
61
67
  const profile = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/connection.ts","../src/commands/scaffold.ts","../src/commands/safety.ts","../src/commands/safer-alternative.ts","../src/commands/sketch.ts","../src/commands/compare-profiles.ts","../src/commands/explorer.ts","../src/commands/catalog.ts","../src/commands/exec.ts","../src/commands/search.ts","../src/commands/query-log.ts"],"sourcesContent":["export { connectionCommand } from './commands/connection.js';\nexport { scaffoldCommand } from './commands/scaffold.js';\nexport { safetyCommand } from './commands/safety.js';\nexport { saferAlternativeCommand } from './commands/safer-alternative.js';\nexport { sketchCommand } from './commands/sketch.js';\nexport { compareProfilesCommand } from './commands/compare-profiles.js';\nexport { explorerCommand } from './commands/explorer.js';\nexport { catalogCommand } from './commands/catalog.js';\nexport { execCommand } from './commands/exec.js';\nexport type { ExecResult, ExecFn } from './commands/exec.js';\nexport { searchCommand } from './commands/search.js';\nexport type { SearchMatch, SearchResult, SearchFn } from './commands/search.js';\nexport { queryLogCommand } from './commands/query-log.js';\n","import { Command } from 'commander';\nimport {\n createConnection,\n defaultProfilesPath,\n getProfile,\n loadProfiles,\n removeProfile,\n upsertProfile,\n type DatabricksConnectionProfile,\n type DatabricksAuth,\n} from '@ddt-tools/core';\n\n/**\n * `ddt connection` — manage Databricks workspace connection profiles.\n *\n * Profiles live at `~/.ddt/profiles.json` (overridable via `$DDT_PROFILES_PATH`).\n * add / list / get / remove are wired today. `test` (probe a profile via\n * the workspace REST API) waits on the OAuth U2M flow before it can land.\n */\nexport function connectionCommand(): Command {\n const cmd = new Command('connection').description('Manage Databricks connection profiles.');\n\n cmd\n .command('add <name>')\n .description('Store a new connection profile.')\n .option('--host <host>', 'Workspace host, e.g. dbc-12345-abcd.cloud.databricks.com')\n .option('--auth <method>', 'One of: pat | oauth-m2m | oauth-u2m | azure-ad | google-idc', 'pat')\n .option(\n '--token <token>',\n 'PAT token — use env:DATABRICKS_TOKEN to reference an env var, never inline a secret',\n )\n .option('--client-id <id>', 'OAuth M2M / Azure AD client ID')\n .option('--client-secret <secret>', 'OAuth M2M / Azure AD client secret')\n .option('--tenant-id <id>', 'Azure AD tenant ID')\n .option(\n '--service-account-key-path <path>',\n 'Path to a GCP service-account key JSON file (for google-idc auth)',\n )\n .requiredOption('--warehouse-id <id>', 'SQL warehouse ID for DDL operations')\n .option('--catalog <catalog>', 'Default Unity Catalog catalog')\n .option('--schema <schema>', 'Default schema')\n .action(async (name: string, opts) => {\n if (!opts.host) throw new Error('--host is required');\n const auth = buildAuth(opts);\n const profile: DatabricksConnectionProfile = {\n name,\n platform: 'Databricks',\n auth,\n warehouseId: String(opts.warehouseId),\n ...(opts.catalog ? { catalog: String(opts.catalog) } : {}),\n ...(opts.schema ? { schema: String(opts.schema) } : {}),\n };\n await upsertProfile(profile);\n console.log(`Saved profile \"${name}\" → ${defaultProfilesPath()}`);\n });\n\n cmd\n .command('list')\n .description('List configured Databricks profiles.')\n .action(async () => {\n const profiles = await loadProfiles();\n if (profiles.length === 0) {\n console.log(`(no profiles configured at ${defaultProfilesPath()})`);\n return;\n }\n for (const p of profiles) {\n console.log(`${p.name}\\t${p.auth.method}\\t${p.auth.host}\\twarehouse=${p.warehouseId}`);\n }\n });\n\n cmd\n .command('get <name>')\n .description('Print a profile (secrets are redacted).')\n .action(async (name: string) => {\n const p = await getProfile(name);\n const redacted: DatabricksConnectionProfile = {\n ...p,\n auth: redactAuth(p.auth),\n };\n console.log(JSON.stringify(redacted, null, 2));\n });\n\n cmd\n .command('remove <name>')\n .description('Delete a connection profile.')\n .action(async (name: string) => {\n const removed = await removeProfile(name);\n console.log(removed ? `Removed profile \"${name}\".` : `No profile \"${name}\" found.`);\n if (!removed) process.exitCode = 1;\n });\n\n cmd\n .command('test <name>')\n .description(\n 'Probe a connection profile via the workspace REST API (`/api/2.0/preview/scim/v2/Me`).',\n )\n .action(async (name: string) => {\n const profile = await getProfile(name);\n const conn = createConnection(profile);\n try {\n await conn.connect();\n const info = await conn.test();\n console.log(`OK ${name}`);\n console.log(` host: ${profile.auth.host}`);\n console.log(` account: ${info.account}`);\n console.log(` version: ${info.version}`);\n } catch (err) {\n console.error(`FAIL ${name}: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n } finally {\n await conn.disconnect();\n }\n });\n\n return cmd;\n}\n\nfunction buildAuth(opts: {\n host?: string;\n auth?: string;\n token?: string;\n clientId?: string;\n clientSecret?: string;\n tenantId?: string;\n serviceAccountKeyPath?: string;\n}): DatabricksAuth {\n const host = String(opts.host);\n const method = String(opts.auth ?? 'pat').toLowerCase();\n switch (method) {\n case 'pat':\n case 'personal_access_token':\n if (!opts.token) throw new Error('--token is required for PAT auth');\n return { method: 'PERSONAL_ACCESS_TOKEN', host, token: String(opts.token) };\n case 'oauth-m2m':\n case 'oauth_m2m':\n if (!opts.clientId || !opts.clientSecret) {\n throw new Error('--client-id and --client-secret are required for OAuth M2M');\n }\n return {\n method: 'OAUTH_M2M',\n host,\n clientId: String(opts.clientId),\n clientSecret: String(opts.clientSecret),\n };\n case 'oauth-u2m':\n case 'oauth_u2m':\n return { method: 'OAUTH_U2M', host };\n case 'azure-ad':\n case 'azure_ad':\n if (!opts.tenantId || !opts.clientId) {\n throw new Error('--tenant-id and --client-id are required for Azure AD');\n }\n return {\n method: 'AZURE_AD',\n host,\n tenantId: String(opts.tenantId),\n clientId: String(opts.clientId),\n ...(opts.clientSecret ? { clientSecret: String(opts.clientSecret) } : {}),\n };\n case 'google-idc':\n case 'google_idc':\n if (!opts.serviceAccountKeyPath) {\n throw new Error('--service-account-key-path is required for google-idc auth');\n }\n return {\n method: 'GOOGLE_IDC',\n host,\n serviceAccountKeyPath: String(opts.serviceAccountKeyPath),\n };\n default:\n throw new Error(`Unknown --auth value: ${method}`);\n }\n}\n\nfunction redactAuth(auth: DatabricksAuth): DatabricksAuth {\n if (auth.method === 'PERSONAL_ACCESS_TOKEN' && auth.token && !auth.token.startsWith('env:')) {\n return { ...auth, token: '<redacted>' };\n }\n if (auth.method === 'OAUTH_M2M' && auth.clientSecret && !auth.clientSecret.startsWith('env:')) {\n return { ...auth, clientSecret: '<redacted>' };\n }\n if (auth.method === 'AZURE_AD' && auth.clientSecret && !auth.clientSecret.startsWith('env:')) {\n return { ...auth, clientSecret: '<redacted>' };\n }\n return auth;\n}\n","import { Command } from 'commander';\n\n/**\n * Placeholder factory for commands whose backing engine is a later\n * deliverable. Prints a clear \"not yet implemented\" message and exits\n * non-zero so CI notices.\n *\n * Mirrors `sdt scaffold` — exported for embedders, not wired into the\n * DDT CLI itself.\n */\nexport function scaffoldCommand(name: string): Command {\n return new Command(name)\n .description(`${name} — Databricks (scaffold; later-release deliverable).`)\n .action(() => {\n console.error(\n `ddt ${name}: scaffold — the Databricks engine for this command is a later deliverable.\\n` +\n `Track progress at Databricks/docs/ROADMAP.md.`,\n );\n process.exitCode = 2;\n });\n}\n","/**\n * `ddt safety` — inspect safety-finding codes.\n *\n * Subcommands:\n * ddt safety list — list every known finding code with a one-line summary\n * ddt safety explain <code> — deep explainer for a single code: why it is dangerous,\n * what cannot be reversed, safer alternatives, required gates\n *\n * The finding codes are stable identifiers attached to every `SafetyFinding`\n * the classifier emits during `ddt compare` / `ddt publish`. When the user\n * sees a finding they don't understand, they can copy the code and ask:\n *\n * ddt safety explain DROP_UNRECOVERABLE\n *\n * Mirrors `Snowflake/packages/cli/src/commands/safety.ts` — paired-file rule.\n * See `docs/UX_PLAYBOOK.md` §3 (dangerous-op UX) and\n * `docs/AI_FEATURES.md` use case C2.\n */\nimport { Command } from 'commander';\nimport { safety as safetyApi, type safety as safetyNs } from '@ddt-tools/core';\n\ntype FindingExplanation = safetyNs.FindingExplanation;\ntype SafetyFindingCode = safetyNs.SafetyFindingCode;\n\nexport function safetyCommand(): Command {\n const cmd = new Command('safety');\n cmd.description(\n 'Inspect the safety-finding catalog. See `ddt safety list` and `ddt safety explain <code>`.',\n );\n\n cmd\n .command('list')\n .description('List every known finding code with category + one-line summary.')\n .option('--format <format>', 'Output format: table | json', 'table')\n .option(\n '--category <kind>',\n 'Filter to one category: unrecoverable | destructive | expensive | warning. Default: all.',\n )\n .action((opts: { format?: string; category?: string }) => {\n const codes = safetyApi.listFindingCodes();\n let entries = codes\n .map((c) => safetyApi.explainFinding(c))\n .filter((e): e is FindingExplanation => e !== undefined);\n if (opts.category) {\n const want = opts.category.toUpperCase();\n const valid = ['UNRECOVERABLE', 'DESTRUCTIVE', 'EXPENSIVE', 'WARNING'];\n if (!valid.includes(want)) {\n console.error(\n `Unknown --category \"${opts.category}\". Use one of: ${valid.join(' | ').toLowerCase()}.`,\n );\n process.exitCode = 1;\n return;\n }\n entries = entries.filter((e) => e.category === want);\n }\n if ((opts.format ?? 'table') === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n console.log('(no entries match the filter)');\n return;\n }\n printList(entries);\n });\n\n cmd\n .command('explain')\n .description('Expand a finding code into a deep \"why this is dangerous\" page.')\n .argument('<code>', 'The finding code (e.g. DROP_UNRECOVERABLE, COLUMN_TYPE_CHANGE)')\n .option('--format <format>', 'Output format: text | json | markdown', 'text')\n .action((codeArg: string, opts: { format?: string }) => {\n const code = codeArg.toUpperCase() as SafetyFindingCode;\n const entry = safetyApi.explainFinding(code);\n if (!entry) {\n console.error(`Unknown safety finding code: \"${codeArg}\"`);\n console.error(' Try: ddt safety list');\n process.exitCode = 1;\n return;\n }\n const format = (opts.format ?? 'text').toLowerCase();\n if (format === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n if (format === 'markdown') {\n process.stdout.write(renderMarkdown(entry) + '\\n');\n return;\n }\n printDeep(entry);\n });\n\n return cmd;\n}\n\nfunction printList(entries: readonly FindingExplanation[]): void {\n const byCategory = new Map<FindingExplanation['category'], FindingExplanation[]>();\n for (const e of entries) {\n const arr = byCategory.get(e.category) ?? [];\n arr.push(e);\n byCategory.set(e.category, arr);\n }\n const order: FindingExplanation['category'][] = [\n 'UNRECOVERABLE',\n 'DESTRUCTIVE',\n 'EXPENSIVE',\n 'WARNING',\n ];\n for (const cat of order) {\n const arr = byCategory.get(cat);\n if (!arr || arr.length === 0) continue;\n console.log(`# ${cat} (${arr.length})`);\n for (const e of arr) {\n console.log(` ${e.code}`);\n console.log(` ${e.title}`);\n console.log(` ${e.summary}`);\n }\n console.log('');\n }\n console.log('Use `ddt safety explain <code>` for the full per-finding write-up.');\n}\n\nfunction printDeep(entry: FindingExplanation): void {\n console.log(`${entry.code} [${entry.category}]`);\n console.log(entry.title);\n console.log('');\n console.log('Summary');\n console.log(` ${entry.summary}`);\n console.log('');\n console.log('Why this is dangerous');\n for (const line of wrap(entry.whyDangerous, 76)) {\n console.log(` ${line}`);\n }\n console.log('');\n console.log('What cannot be reversed');\n for (const item of entry.cannotBeReversed) console.log(` - ${item}`);\n console.log('');\n console.log('Safer alternatives');\n for (const item of entry.saferAlternatives) console.log(` - ${item}`);\n console.log('');\n if (entry.requiredGates.length > 0) {\n console.log('Required gates to allow this finding through');\n for (const g of entry.requiredGates) console.log(` - ${g}`);\n console.log('');\n }\n if (entry.example) {\n console.log('Example');\n console.log(` ${entry.example}`);\n }\n}\n\nfunction renderMarkdown(entry: FindingExplanation): string {\n const lines: string[] = [];\n lines.push(`## ${entry.code} — ${entry.title}`);\n lines.push('');\n lines.push(`**Category:** ${entry.category}`);\n lines.push('');\n lines.push(`**Summary:** ${entry.summary}`);\n lines.push('');\n lines.push('### Why this is dangerous');\n lines.push(entry.whyDangerous);\n lines.push('');\n lines.push('### What cannot be reversed');\n for (const item of entry.cannotBeReversed) lines.push(`- ${item}`);\n lines.push('');\n lines.push('### Safer alternatives');\n for (const item of entry.saferAlternatives) lines.push(`- ${item}`);\n if (entry.requiredGates.length > 0) {\n lines.push('');\n lines.push('### Required gates');\n for (const g of entry.requiredGates) lines.push(`- \\`${g}\\``);\n }\n if (entry.example) {\n lines.push('');\n lines.push('### Example');\n lines.push('```');\n lines.push(entry.example);\n lines.push('```');\n }\n return lines.join('\\n');\n}\n\nfunction wrap(text: string, width: number): string[] {\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let current = '';\n for (const word of words) {\n if (current.length === 0) {\n current = word;\n } else if (current.length + 1 + word.length <= width) {\n current += ' ' + word;\n } else {\n lines.push(current);\n current = word;\n }\n }\n if (current.length > 0) lines.push(current);\n return lines;\n}\n","/**\n * `ddt safer-alternative` — call the AI provider to suggest a safer DDL\n * alternative for a flagged-as-dangerous migration step.\n *\n * Composes `@ddt-tools/core/saferAlternative.suggestSaferAlternative` with the\n * configured AI provider (`@ddt-tools/core/ai.complete`). The CLI is the thin\n * adapter; all the prompt-building and parsing lives in core so the\n * VS Code CodeLens / MCP server / future hosts share the same behavior.\n *\n * Inputs (all surfaced as flags):\n * --code SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE)\n * --fqn Object FQN the finding refers to\n * --object-type Object type (e.g. MANAGED_TABLE, VIEW)\n * --reason Short reason from the safety classifier\n * --gate Optional SafetyGate (preserved on the suggestion)\n * --sql <path> Path to a file with the dangerous DDL (or \"-\" for stdin)\n * --context <path> Optional path to the surrounding source DDL\n * --intent <text> Optional human-authored intent notes\n * --format text | json (default text)\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, saferAlternative, type safety } from '@ddt-tools/core';\n\nexport function saferAlternativeCommand(): Command {\n const cmd = new Command('safer-alternative');\n cmd\n .description(\n 'AI-assist: propose a safer DDL alternative for a safety finding. Requires a configured AI provider (ddt ai status).',\n )\n .requiredOption('--code <code>', 'SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE).')\n .requiredOption('--fqn <fqn>', 'Object FQN the finding refers to.')\n .requiredOption('--object-type <type>', 'Object type (e.g. MANAGED_TABLE, VIEW, FUNCTION).')\n .requiredOption('--reason <text>', 'Short reason text from the safety classifier.')\n .option(\n '--gate <gate>',\n 'Optional SafetyGate the finding raised (e.g. REQUIRE_ALLOW_DROP_COLUMN).',\n )\n .option('--sql <path>', 'Path to a file with the dangerous DDL. Use \"-\" to read from stdin.')\n .option('--context <path>', 'Optional path to the surrounding source DDL.')\n .option('--intent <text>', 'Optional human-authored intent notes.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (opts) => {\n const dangerousSql = await readInput(\n opts.sql,\n '--sql is required (use a path or \"-\" for stdin).',\n );\n const contextSql = opts.context ? await fs.readFile(String(opts.context), 'utf8') : undefined;\n\n const finding: safety.SafetyFinding = {\n code: String(opts.code) as safety.SafetyFindingCode,\n category: 'DESTRUCTIVE',\n fqn: String(opts.fqn),\n objectType: String(opts.objectType) as safety.SafetyFinding['objectType'],\n reason: String(opts.reason),\n gate: opts.gate ? (String(opts.gate) as safety.SafetyGate) : undefined,\n };\n\n const result = await saferAlternative.suggestSaferAlternative(\n {\n finding,\n dangerousSql,\n contextSql,\n intentNotes: opts.intent ? String(opts.intent) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'safer-alternative',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n if (String(opts.format).toLowerCase() === 'json') {\n const { rawModelText: _omit, ...keep } = result;\n console.log(JSON.stringify(keep, null, 2));\n return;\n }\n\n console.log(`Confidence: ${result.confidence}${result.parseFailed ? ' (parse failed)' : ''}`);\n console.log(`Reasoning: ${result.reasoning}`);\n if (result.alternativeSql) {\n console.log('');\n console.log('--- Proposed safer DDL ---');\n console.log(result.alternativeSql);\n } else {\n console.warn('No safer alternative SQL was returned.');\n }\n if (result.requiredGates.length > 0) {\n console.log(`Required gates: ${result.requiredGates.join(', ')}`);\n }\n });\n return cmd;\n}\n\nasync function readInput(pathOrDash: unknown, missingMessage: string): Promise<string> {\n if (!pathOrDash) throw new Error(missingMessage);\n const p = String(pathOrDash);\n if (p === '-') {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n }\n return fs.readFile(p, 'utf8');\n}\n","/**\n * `ddt sketch <kind>` — generate idiomatic Databricks UC DDL from a free-form\n * prose description via the configured AI provider.\n *\n * Composes `@ddt-tools/core/objectSketch.sketchToDdl` with `@ddt-tools/core/ai.complete`.\n * Output is always wrapped in a \"REVIEW BEFORE DEPLOY\" header so the user\n * never confuses model output with hand-authored DDL.\n *\n * Inputs:\n * <kind> managed-table | external-table | streaming-table\n * | materialized-view | view | function | volume\n * --description <text> Free-form description (or \"-\" to read from stdin)\n * --target <fqn> Optional target FQN (e.g. analytics.public.orders)\n * --context <text> Optional additional context\n * --out <path> Optional output file. Default: stdout.\n * --format <fmt> text | json. Default text (just the DDL).\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, objectSketch } from '@ddt-tools/core';\n\nconst KINDS = [\n 'managed-table',\n 'external-table',\n 'streaming-table',\n 'materialized-view',\n 'view',\n 'function',\n 'volume',\n] as const;\n\ntype Kind = (typeof KINDS)[number];\n\nexport function sketchCommand(): Command {\n const cmd = new Command('sketch');\n cmd\n .description(\n 'AI-assist: scaffold idiomatic Databricks UC DDL from a prose description. Output always carries a REVIEW BEFORE DEPLOY header.',\n )\n .argument('<kind>', `Object kind: ${KINDS.join(' | ')}`)\n .requiredOption('--description <text>', 'Free-form description. Use \"-\" to read from stdin.')\n .option('--target <fqn>', 'Target FQN (e.g. analytics.public.orders).')\n .option('--context <text>', 'Optional additional context (e.g. \"use SQL warehouse small\").')\n .option('--out <path>', 'Output file. Default stdout.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (kindArg, opts) => {\n const kind = String(kindArg).toLowerCase() as Kind;\n if (!KINDS.includes(kind)) {\n throw new Error(`Unknown kind \"${kindArg}\". Use one of: ${KINDS.join(' | ')}`);\n }\n\n const description =\n String(opts.description) === '-' ? await readStdin() : String(opts.description);\n const targetFqn = opts.target ? splitFqn(String(opts.target)) : undefined;\n\n const result = await objectSketch.sketchToDdl(\n {\n description,\n objectKind: kind,\n targetFqn,\n additionalContext: opts.context ? String(opts.context) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'object-sketch',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n const output =\n String(opts.format).toLowerCase() === 'json'\n ? JSON.stringify({ ...result, rawModelText: undefined }, null, 2)\n : result.generatedSql;\n\n if (opts.out) {\n await fs.writeFile(String(opts.out), output, 'utf8');\n console.log(`Wrote ${String(opts.out)} (${output.length} bytes)`);\n } else {\n console.log(output);\n }\n\n if (result.assumptions.length > 0) {\n console.error('');\n console.error('Model assumptions:');\n for (const a of result.assumptions) console.error(` - ${a}`);\n }\n if (result.parseFailed) {\n console.warn('Model output could not be parsed — see the raw text via --format json.');\n }\n });\n return cmd;\n}\n\nfunction splitFqn(fqn: string): { catalog?: string; schema?: string; name: string } {\n const parts = fqn.split('.');\n if (parts.length === 1) return { name: parts[0]! };\n if (parts.length === 2) return { schema: parts[0], name: parts[1]! };\n if (parts.length === 3) return { catalog: parts[0], schema: parts[1], name: parts[2]! };\n throw new Error(`Invalid --target \"${fqn}\": expected 1, 2, or 3 dot-separated parts.`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `ddt compare-profiles` — manage saved comparison profiles.\n *\n * A profile is \"Source X (connection|pac|project) → Target Y, with these\n * mapping rules\", persisted to `<cwd>/.ddt/compare-profiles.json`. The\n * eventual VS Code webview reads/writes the same store; this CLI gives\n * power-users the same affordances headlessly.\n *\n * Subcommands:\n * list — list all saved profiles (table or JSON)\n * show <id> — print one profile (table or JSON)\n * save — upsert a profile from a JSON file (--json-file <path>) or stdin\n * remove <id> — delete a profile\n * preview <id> — run `previewMatch` over the saved profile's\n * source + target endpoints and report counts +\n * examples of matched / source-only / target-only\n * FQNs. Catches typo'd schema names before a\n * full extract + diff round-trip.\n *\n * `preview` resolves each endpoint locally:\n * - kind=connection — reads the EE1 catalog cache at\n * `<root>/.ddt/cache/<reference>/catalog.msgpack` (legacy\n * `catalog.json` also accepted). Run\n * `ddt catalog refresh --connection <reference>` first.\n * - kind=pac — reads the `.ddtpac` archive at `reference`.\n * - kind=project — reads the `.ddtproj` at `reference`.\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { catalog, compareProfiles, loadProject, pac, parseProjectModel } from '@ddt-tools/core';\nimport type { DatabricksObject, FullyQualifiedName } from '@ddt-tools/core/model';\n\nexport function compareProfilesCommand(): Command {\n const cmd = new Command('compare-profiles');\n cmd.description('Manage saved compare profiles (.ddt/compare-profiles.json).');\n\n cmd\n .command('list')\n .description('List every saved profile.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const all = await store.list();\n if (opts.json) {\n console.log(JSON.stringify(all, null, 2));\n return;\n }\n if (all.length === 0) {\n console.log('(no compare profiles saved yet)');\n console.log(` store: ${store.path}`);\n return;\n }\n console.log(`${all.length} compare profile(s):`);\n for (const p of all) {\n console.log(` ${p.id.padEnd(24)} ${p.name}`);\n console.log(` source: ${p.source.kind}=${p.source.reference}`);\n console.log(` target: ${p.target.kind}=${p.target.reference}`);\n console.log(` mappings: ${p.mappings.length} updated: ${p.updatedAt}`);\n }\n });\n\n cmd\n .command('show')\n .description('Show one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const p = await store.get(String(id));\n if (!p) {\n console.error(\n `No profile with id \"${id}\". Run \\`ddt compare-profiles list\\` to enumerate.`,\n );\n process.exitCode = 1;\n return;\n }\n if (opts.json) {\n console.log(JSON.stringify(p, null, 2));\n return;\n }\n console.log(`Profile: ${p.name} (${p.id})`);\n if (p.description) console.log(` ${p.description}`);\n console.log(\n ` source: ${p.source.kind}=${p.source.reference}${p.source.catalog ? ` cat=${p.source.catalog}` : ''}${p.source.schema ? ` schema=${p.source.schema}` : ''}`,\n );\n console.log(\n ` target: ${p.target.kind}=${p.target.reference}${p.target.catalog ? ` cat=${p.target.catalog}` : ''}${p.target.schema ? ` schema=${p.target.schema}` : ''}`,\n );\n console.log(` case-sensitive: ${p.caseSensitive ? 'yes' : 'no'}`);\n console.log(` rewrite-inside-strings: ${p.rewriteInsideStrings ? 'yes' : 'no'}`);\n console.log(` updatedAt: ${p.updatedAt}`);\n if (p.mappings.length === 0) {\n console.log(' mappings: (none — identity)');\n } else {\n console.log(` mappings (${p.mappings.length}):`);\n for (const m of p.mappings) console.log(` ${m.source} => ${m.target}`);\n }\n });\n\n cmd\n .command('save')\n .description('Upsert a profile from a JSON file or stdin.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json-file <path>', 'Path to a JSON file containing one profile. Use \"-\" for stdin.')\n .action(async (opts) => {\n if (!opts.jsonFile) {\n throw new Error('--json-file is required (use a path or \"-\" for stdin).');\n }\n const raw =\n String(opts.jsonFile) === '-'\n ? await readStdin()\n : await fs.readFile(String(opts.jsonFile), 'utf8');\n const parsed = JSON.parse(raw) as compareProfiles.CompareProfile;\n if (!parsed?.id || !parsed?.name || !parsed?.source || !parsed?.target) {\n throw new Error(\n 'Profile JSON must contain at minimum: id, name, source, target. mappings defaults to [].',\n );\n }\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const stamped = await store.upsert({ ...parsed, mappings: parsed.mappings ?? [] });\n console.log(`Saved profile \"${stamped.name}\" (${stamped.id})`);\n console.log(` store: ${store.path}`);\n });\n\n cmd\n .command('remove')\n .description('Delete one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const removed = await store.remove(String(id));\n if (removed) {\n console.log(`Removed profile \"${id}\".`);\n } else {\n console.warn(`No profile with id \"${id}\" — nothing to remove.`);\n }\n });\n\n cmd\n .command('preview')\n .description(\n \"Preview which FQNs match between the profile's source and target. Local-only — no workspace round-trip.\",\n )\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option(\n '--examples <n>',\n 'Max example FQNs to show per bucket in human output. Default 5.',\n (v) => parseInt(v, 10),\n 5,\n )\n .option('--json', 'Emit the full PreviewSummary as JSON.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const profile = await store.get(String(id));\n if (!profile) {\n console.error(\n `No profile with id \"${id}\". Run \\`ddt compare-profiles list\\` to enumerate.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const root = String(opts.root);\n const source = await resolveEndpointFqns(profile.source, root);\n const target = await resolveEndpointFqns(profile.target, root);\n\n const summary = compareProfiles.previewMatch({\n source: source.fqns,\n target: target.fqns,\n mappings: profile.mappings,\n ...(profile.caseSensitive ? { caseSensitive: true } : {}),\n });\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n profile: { id: profile.id, name: profile.name },\n source: {\n kind: profile.source.kind,\n reference: profile.source.reference,\n count: source.fqns.length,\n },\n target: {\n kind: profile.target.kind,\n reference: profile.target.reference,\n count: target.fqns.length,\n },\n summary,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Preview: ${profile.name} (${profile.id})`);\n console.log(\n ` source (${profile.source.kind}=${profile.source.reference}): ${source.fqns.length} object(s)${source.note ? ` — ${source.note}` : ''}`,\n );\n console.log(\n ` target (${profile.target.kind}=${profile.target.reference}): ${target.fqns.length} object(s)${target.note ? ` — ${target.note}` : ''}`,\n );\n console.log('');\n console.log(` matched: ${summary.matchedCount}`);\n console.log(` source-only: ${summary.sourceOnlyCount}`);\n console.log(` target-only: ${summary.targetOnlyCount}`);\n\n const exN = Math.max(0, Number(opts.examples));\n printBucket('matched', summary.matched, exN);\n printBucket('source-only', summary.sourceOnly, exN);\n printBucket('target-only', summary.targetOnly, exN);\n\n if (\n summary.matchedCount === 0 &&\n (summary.sourceOnlyCount > 0 || summary.targetOnlyCount > 0)\n ) {\n console.warn(\"No FQNs matched — check the profile's scope and mapping rules.\");\n }\n });\n\n return cmd;\n}\n\ninterface EndpointResolution {\n fqns: FullyQualifiedName[];\n note?: string;\n}\n\nasync function resolveEndpointFqns(\n endpoint: compareProfiles.CompareProfile['source'],\n root: string,\n): Promise<EndpointResolution> {\n if (endpoint.kind === 'connection') {\n const cache = new catalog.CatalogCache({ root, connection: endpoint.reference });\n const snapshot = await cache.get();\n if (snapshot.catalogs.length === 0) {\n return {\n fqns: [],\n note: `empty catalog cache at ${cache.path} — run \\`ddt catalog refresh --connection ${endpoint.reference}\\` first`,\n };\n }\n return { fqns: fqnsFromSnapshot(snapshot, endpoint.catalog, endpoint.schema) };\n }\n if (endpoint.kind === 'pac') {\n const contents = await pac.readPac(endpoint.reference);\n return { fqns: fqnsFromObjects(contents.model, endpoint.catalog, endpoint.schema) };\n }\n // kind === 'project'\n const loaded = await loadProject(endpoint.reference);\n const model = await parseProjectModel(loaded);\n return { fqns: fqnsFromObjects(model, endpoint.catalog, endpoint.schema) };\n}\n\nfunction fqnsFromSnapshot(\n snapshot: catalog.CatalogSnapshot,\n catalogScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const cat of snapshot.catalogs) {\n if (catalogScope && !sameId(cat.catalog, catalogScope)) continue;\n for (const sc of cat.schemas) {\n if (schemaScope && !sameId(sc.schema, schemaScope)) continue;\n for (const obj of sc.objects) {\n // FQN uses `database` for UC's catalog — paired-file convention.\n out.push({ database: obj.catalog, schema: obj.schema, name: obj.name });\n }\n }\n }\n return out;\n}\n\nfunction fqnsFromObjects(\n model: readonly DatabricksObject[],\n catalogScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const obj of model) {\n // FQN uses `database` for UC's catalog — paired-file convention.\n if (catalogScope && !sameId(obj.fqn.database, catalogScope)) continue;\n if (schemaScope && !sameId(obj.fqn.schema, schemaScope)) continue;\n out.push(obj.fqn);\n }\n return out;\n}\n\nfunction printBucket(label: string, items: readonly string[], exampleN: number): void {\n if (items.length === 0) return;\n console.log('');\n console.log(\n ` ${label} examples (showing ${Math.min(exampleN, items.length)} of ${items.length}):`,\n );\n for (const fqn of items.slice(0, exampleN)) console.log(` ${fqn}`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `ddt explorer` — ASCII tree dump of the live catalog/schema/object\n * hierarchy for a connected target, read from the EE1 catalog cache.\n *\n * The eventual VS Code TreeDataProvider walks the same `treeForSnapshot`\n * shape; this CLI gives non-VS-Code users the same browsable view of the\n * cached catalog. No live queries are issued — the cache is read-only.\n * Run `ddt catalog refresh --connection <name>` first to populate it.\n *\n * Inputs:\n * --connection <name> Required. Connection profile name to load the cache for.\n * --root <path> Project root (where .ddt/cache/ lives). Default cwd.\n * --filter <query> Typeahead filter; case-insensitive substring match.\n * Keeps every ancestor of a leaf match.\n * --json Emit the tree as JSON instead of an ASCII tree.\n */\nimport { Command } from 'commander';\nimport { catalog, objectExplorer } from '@ddt-tools/core';\n\nexport function explorerCommand(): Command {\n const cmd = new Command('explorer');\n cmd\n .description(\n 'ASCII tree dump of the cached catalog for a connection. Run `ddt catalog refresh` first to populate.',\n )\n .requiredOption('--connection <name>', 'Connection profile name (the cache subfolder).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--filter <query>', 'Typeahead substring filter (case-insensitive).')\n .option(\n '--depth <n>',\n 'Truncate tree at depth N (0 = root only, 1 = +catalogs, 2 = +schemas, 3 = +object-groups, 4 = +objects). Default unlimited.',\n (v) => parseInt(v, 10),\n )\n .option('--json', 'Emit tree as JSON instead of ASCII.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n let tree = objectExplorer.treeForSnapshot(snapshot);\n if (opts.filter) tree = objectExplorer.filterTree(tree, String(opts.filter));\n if (typeof opts.depth === 'number') tree = objectExplorer.truncateTree(tree, opts.depth);\n\n if (snapshot.catalogs.length === 0) {\n console.warn(`Catalog cache is empty for connection \"${opts.connection}\".`);\n console.warn(` Cache file: ${cache.path}`);\n console.warn(` Run \\`ddt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n\n if (opts.json) {\n console.log(JSON.stringify(tree, null, 2));\n return;\n }\n\n renderAsciiTree(tree);\n });\n return cmd;\n}\n\n/**\n * Render the explorer tree as an ASCII tree (├──, │, └──). Mirrors the\n * GNU `tree`(1) glyph set for familiarity. Root prints without a\n * connector; descendants get the standard branch glyphs.\n */\nfunction renderAsciiTree(root: objectExplorer.ExplorerNode): void {\n const desc = root.description ? ` (${root.description})` : '';\n console.log(`${root.label}${desc}`);\n const children = root.children ?? [];\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, '', i === children.length - 1);\n }\n}\n\nfunction renderChild(node: objectExplorer.ExplorerNode, prefix: string, isLast: boolean): void {\n const connector = isLast ? '└── ' : '├── ';\n const desc = node.description ? ` (${node.description})` : '';\n console.log(`${prefix}${connector}${node.label}${desc}`);\n const children = node.children ?? [];\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, childPrefix, i === children.length - 1);\n }\n}\n","/**\n * `ddt catalog` — manage the per-connection catalog cache (EE1 substrate).\n *\n * ddt catalog refresh --connection <name> [--catalogs <csv>] [--concurrency <n>]\n * ddt catalog show --connection <name> [--json]\n * ddt catalog clear --connection <name>\n *\n * `refresh` opens a live Databricks SQL warehouse connection, discovers\n * catalogs via `SHOW CATALOGS`, runs the bulk-scan SQL per catalog via\n * the bounded promise pool, and writes the assembled snapshot to\n * `<root>/.ddt/cache/<conn>/catalog.msgpack` (RES.1 — was `catalog.json`\n * before 2026-05-16; the cache reader still accepts the legacy form for\n * one major version). Schema fingerprints (`MAX(LAST_ALTERED)`) are\n * checked first; catalogs that haven't changed since the last refresh\n * are skipped.\n *\n * `show` reads the cache file and pretty-prints (or emits JSON).\n * `clear` deletes the cache file (and its parent dir if empty).\n *\n * Object Explorer (`ddt explorer`) and the eventual EE2 intellisense\n * provider both consume this cache.\n */\nimport { Command } from 'commander';\nimport { catalog, createConnection, getProfile, type DatabricksConnection } from '@ddt-tools/core';\n\n/**\n * Built-in catalogs that almost no one wants in their cache. Pass\n * `--include-builtins` to keep them. `system` is intentionally excluded\n * because the bulk-scan SQL filters out `information_schema` already.\n */\nconst BUILTIN_CATALOGS = new Set(['system', 'samples', '__databricks_internal']);\n\ninterface ShowCatalogsRow {\n catalog?: string;\n catalog_name?: string;\n CATALOG?: string;\n CATALOG_NAME?: string;\n}\n\nexport function catalogCommand(): Command {\n const cmd = new Command('catalog');\n cmd.description(\n 'Manage the per-connection catalog cache used by the Object Explorer + EE2 intellisense.',\n );\n\n cmd\n .command('refresh')\n .description('Open the connection, scan every (non-builtin) catalog, write the catalog cache.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--catalogs <csv>', 'Comma-separated list. Default: every non-builtin catalog.')\n .option('--include-builtins', 'Include system / samples / __databricks_internal.', false)\n .option(\n '--concurrency <n>',\n 'Bounded-concurrency cap for the bulk-scan pool. Default 10.',\n '10',\n )\n .option('--no-fingerprint-skip', 'Force a full scan even when fingerprints are unchanged.')\n .action(async (opts) => {\n const profile = await getProfile(String(opts.connection));\n const conn = createConnection(profile);\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: profile.name,\n });\n\n console.log(`Connecting to ${profile.auth.host}…`);\n await conn.connect();\n try {\n const cats = await resolveCatalogs(conn, opts);\n if (cats.length === 0) {\n console.warn('No catalogs to scan. Pass --catalogs or --include-builtins.');\n return;\n }\n console.log(\n `Scanning ${cats.length} catalog(s) with concurrency ${Number(opts.concurrency)}.`,\n );\n\n const cached = await cache.get();\n const cachedByCat = new Map(cached.catalogs.map((c) => [c.catalog, c] as const));\n\n const concurrency = Math.max(1, Number(opts.concurrency) || 10);\n const fingerprintSkip = opts.fingerprintSkip !== false;\n\n const { results, errors } = await catalog.mapPool(\n cats,\n async (cat) => {\n let freshFingerprint: number | null = null;\n try {\n const fpRes = await conn.query<{ MAX_LAST_ALTERED: unknown }>(\n catalog.fingerprintSqlForCatalog(cat),\n );\n freshFingerprint = catalog.parseFingerprintRow(fpRes.rows);\n } catch (err) {\n console.warn(\n `fingerprint(${cat}) failed; falling through to full scan: ${(err as Error).message}`,\n );\n }\n\n const cachedCat = cachedByCat.get(cat);\n if (\n fingerprintSkip &&\n cachedCat &&\n cachedCat.fingerprint != null &&\n freshFingerprint != null &&\n catalog.isFresh(cachedCat.fingerprint, freshFingerprint)\n ) {\n console.log(` ${cat}: fresh; reusing cache`);\n return {\n catalog: cat,\n fingerprint: cachedCat.fingerprint,\n schemas: cachedCat.schemas,\n };\n }\n\n const scanRes = await conn.query(catalog.bulkScanSqlForCatalog(cat));\n const schemas = catalog.parseBulkScanRows(cat, scanRes.rows);\n const fingerprint = freshFingerprint ?? null;\n console.log(\n ` ${cat}: ${schemas.length} schemas / ${schemas.reduce((sum, s) => sum + s.objects.length, 0)} objects`,\n );\n return { catalog: cat, fingerprint, schemas };\n },\n { concurrency },\n );\n\n for (const e of errors) {\n console.warn(`scan failed for \"${cats[e.index]}\": ${(e.error as Error).message}`);\n }\n\n const snapshot = catalog.refreshFingerprints({\n version: catalog.CATALOG_SNAPSHOT_VERSION,\n connection: profile.name,\n snapshotAt: new Date().toISOString(),\n fingerprint: null,\n catalogs: results.filter((r): r is NonNullable<typeof r> => !!r),\n });\n await cache.set(snapshot);\n\n console.log(`Wrote ${snapshot.catalogs.length} catalogs to ${cache.path}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n cmd\n .command('show')\n .description('Pretty-print or JSON-dump the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of summary.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n if (opts.json) {\n console.log(JSON.stringify(snapshot, null, 2));\n return;\n }\n if (snapshot.catalogs.length === 0) {\n console.warn(`Catalog cache is empty for \"${opts.connection}\".`);\n console.warn(` Cache file: ${cache.path}`);\n console.warn(` Run \\`ddt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n console.log(`Snapshot for \"${snapshot.connection}\" — ${snapshot.snapshotAt}`);\n console.log(\n ` Top-level fingerprint: ${snapshot.fingerprint != null ? new Date(snapshot.fingerprint).toISOString() : '(none)'}`,\n );\n for (const cat of snapshot.catalogs) {\n const objCount = cat.schemas.reduce((sum, s) => sum + s.objects.length, 0);\n console.log(\n ` ${cat.catalog.padEnd(32)} ${cat.schemas.length} schemas / ${objCount} objects`,\n );\n }\n });\n\n cmd\n .command('clear')\n .description('Delete the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n await cache.clear();\n console.log(`Cleared cache for \"${opts.connection}\".`);\n console.log(` was: ${cache.path}`);\n });\n\n return cmd;\n}\n\nasync function resolveCatalogs(\n conn: DatabricksConnection,\n opts: { catalogs?: unknown; includeBuiltins?: unknown },\n): Promise<string[]> {\n if (opts.catalogs) {\n return String(opts.catalogs)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n const res = await conn.query<ShowCatalogsRow>('SHOW CATALOGS');\n const names = res.rows\n .map((r) => String(r.catalog ?? r.catalog_name ?? r.CATALOG ?? r.CATALOG_NAME ?? ''))\n .filter(Boolean);\n if (opts.includeBuiltins) return names;\n return names.filter((n) => !BUILTIN_CATALOGS.has(n.toLowerCase()));\n}\n","/**\n * `ddt exec <file.sql> --profiles <list>` — AUTH.3.\n *\n * Runs a SQL / DeltaSQL script on one or more connection profiles in\n * parallel and prints a merged report. Guarded against any profile\n * whose name matches \"prod\" or \"production\" (case-insensitive) unless\n * `--yes` is passed.\n *\n * Mirrors `Snowflake/packages/cli/src/commands/exec.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport { getProfile, createConnection } from '@ddt-tools/core/connection';\nimport { queryExecution } from '@ddt-tools/core';\n\nexport interface ExecResult {\n profile: string;\n status: 'success' | 'error';\n rowsAffected?: number;\n durationMs: number;\n error?: string;\n}\n\nexport type ExecFn = (\n profile: string,\n sql: string,\n timeoutMs: number,\n) => Promise<Omit<ExecResult, 'profile' | 'durationMs'>>;\n\nconst PROD_PATTERN = /\\bprod(uction)?\\b/i;\n\nfunction isProductionProfile(name: string): boolean {\n return PROD_PATTERN.test(name);\n}\n\nasync function runOnProfile(\n execFn: ExecFn,\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<ExecResult> {\n const start = Date.now();\n try {\n const res = await execFn(profile, sql, timeoutMs);\n return { ...res, profile, durationMs: Date.now() - start };\n } catch (err) {\n return {\n profile,\n status: 'error',\n durationMs: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction renderText(results: ExecResult[]): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.status === 'success') {\n const rows = r.rowsAffected !== undefined ? ` (${r.rowsAffected} rows)` : '';\n lines.push(` ${r.profile}: ✓${rows} — ${(r.durationMs / 1000).toFixed(1)}s`);\n } else {\n lines.push(` ${r.profile}: ✗ ${r.error ?? 'unknown error'}`);\n }\n }\n const total = results.length;\n const succeeded = results.filter((r) => r.status === 'success').length;\n lines.push(`\\n${succeeded}/${total} profiles succeeded.`);\n return lines.join('\\n');\n}\n\n/**\n * Wire to the real Databricks connection layer:\n * 1. Resolve the named profile (`~/.ddt/profiles.json`).\n * 2. Open a connection (PAT bearer or OAuth, per profile.auth).\n * 3. Split the SQL via the shared `queryExecution.splitStatements`\n * (Databricks dialect: backtick identifiers, no dollar-quotes)\n * and run each statement sequentially through\n * `DatabricksConnection.query`. We do NOT `failFast` so a script\n * with N statements surfaces every error.\n * 4. Aggregate: success iff every statement succeeded; the first\n * error's message becomes the profile-level error. Total\n * `rowsAffected` is the sum of rowCount across statements.\n *\n * Injectable for tests via the `execFn` parameter on `execCommand`.\n */\nasync function defaultExecFn(\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<Omit<ExecResult, 'profile' | 'durationMs'>> {\n const profileObj = await getProfile(profile);\n const conn = createConnection(profileObj);\n await conn.connect();\n try {\n const timeoutSeconds = Math.max(1, Math.ceil(timeoutMs / 1000));\n const runner: queryExecution.QueryRunner = {\n executeStatement: async (statement: string) => {\n const result = await conn.query(statement, { timeoutSeconds });\n return {\n rows: result.rows as Record<string, unknown>[],\n durationMs: result.durationMs,\n };\n },\n };\n const result = await queryExecution.executeStatements(sql, runner, {\n failFast: false,\n splitOptions: { dialect: 'databricks' },\n toolName: 'ddt',\n });\n const firstError = result.statements.find((s) => s.error);\n if (firstError && firstError.error) {\n throw new Error(firstError.error.message);\n }\n const rowsAffected = result.statements.reduce((acc, s) => acc + (s.rowCount ?? 0), 0);\n return { status: 'success', rowsAffected };\n } finally {\n await conn.disconnect().catch(() => {\n /* best-effort cleanup */\n });\n }\n}\n\nexport function execCommand(execFn: ExecFn = defaultExecFn): Command {\n const cmd = new Command('exec');\n cmd\n .description('Run a SQL script on one or more connection profiles in parallel.')\n .argument('<file>', 'Path to the .sql file to execute.')\n .requiredOption('--profiles <list>', 'Comma-separated connection profile names.')\n .option('--yes', 'Confirm execution against production profiles without prompting.')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--timeout <ms>', 'Per-profile timeout in milliseconds.', '30000')\n .action(async (file: string, opts) => {\n const profiles = (opts.profiles as string)\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n if (profiles.length === 0) throw new Error('--profiles must list at least one profile.');\n\n const prodProfiles = profiles.filter(isProductionProfile);\n if (prodProfiles.length > 0 && !opts.yes) {\n throw new Error(\n `Profile(s) look like production: ${prodProfiles.join(', ')}. ` +\n `Pass --yes to confirm.`,\n );\n }\n\n let sql: string;\n try {\n sql = await fs.readFile(file, 'utf8');\n } catch {\n throw new Error(`Cannot read file: ${file}`);\n }\n if (!sql.trim()) throw new Error(`File is empty: ${file}`);\n\n const timeoutMs = parseInt(String(opts.timeout ?? '30000'), 10);\n const results = await Promise.all(\n profiles.map((p) => runOnProfile(execFn, p, sql, timeoutMs)),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n const failed = results.filter((r) => r.status === 'error').length;\n process.stdout.write(\n JSON.stringify(\n {\n results,\n summary: {\n total: results.length,\n succeeded: results.length - failed,\n failed,\n },\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n process.stdout.write(renderText(results) + '\\n');\n });\n return cmd;\n}\n","/**\n * `ddt search <pattern> --profiles <list|all>` — AUTH.4.\n *\n * Finds objects whose name matches a pattern across one or more connection\n * profiles. Surfaces presence/absence drift: if an object exists in some\n * profiles but not others, those profiles are flagged.\n *\n * The search is case-insensitive substring match by default; --exact\n * switches to exact name match; --type filters by objectType.\n *\n * Mirrors `Snowflake/packages/cli/src/commands/search.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { catalog } from '@ddt-tools/core';\n\nexport interface SearchMatch {\n profile: string;\n fqn: string;\n objectType: string;\n}\n\nexport interface SearchResult {\n profile: string;\n matches: SearchMatch[];\n error?: string;\n}\n\nexport interface SearchFnOptions {\n exact: boolean;\n objectType?: string;\n /** Project / cache root. Defaults to `process.cwd()`. */\n root?: string;\n}\n\nexport type SearchFn = (\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n) => Promise<SearchMatch[]>;\n\nfunction buildDriftReport(results: SearchResult[]): string {\n const allFqns = new Set<string>();\n const byFqn = new Map<string, Set<string>>();\n for (const r of results) {\n if (r.error) continue;\n for (const m of r.matches) {\n allFqns.add(m.fqn);\n if (!byFqn.has(m.fqn)) byFqn.set(m.fqn, new Set());\n byFqn.get(m.fqn)!.add(r.profile);\n }\n }\n const successProfiles = results.filter((r) => !r.error).map((r) => r.profile);\n const driftLines: string[] = [];\n for (const fqn of allFqns) {\n const present = byFqn.get(fqn)!;\n if (present.size < successProfiles.length) {\n const absent = successProfiles.filter((p) => !present.has(p));\n driftLines.push(\n ` DRIFT ${fqn} [present: ${[...present].join(', ')} absent: ${absent.join(', ')}]`,\n );\n }\n }\n return driftLines.join('\\n');\n}\n\nfunction renderText(results: SearchResult[], showDrift: boolean): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.error) {\n lines.push(`[${r.profile}] ERROR: ${r.error}`);\n continue;\n }\n if (r.matches.length === 0) {\n lines.push(`[${r.profile}] no matches`);\n } else {\n for (const m of r.matches) {\n lines.push(`[${r.profile}] ${m.fqn} (${m.objectType})`);\n }\n }\n }\n if (showDrift) {\n const drift = buildDriftReport(results);\n if (drift) {\n lines.push('');\n lines.push('--- Drift detected ---');\n lines.push(drift);\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadProfileNames(profilesOpt: string, profilesDir: string): Promise<string[]> {\n if (profilesOpt.toLowerCase() !== 'all') {\n return profilesOpt\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n }\n try {\n const entries = await fs.readdir(profilesDir);\n return entries\n .filter((e) => e.endsWith('.json') || e.endsWith('.toml'))\n .map((e) => path.basename(e, path.extname(e)));\n } catch {\n return [];\n }\n}\n\n/**\n * Wire to the on-disk catalog cache (`<root>/.ddt/cache/<profile>/catalog.msgpack`\n * written by `ddt catalog refresh` / `ddt extract --write-catalog-cache`).\n *\n * 1. Open `catalog.CatalogCache({root, connection: profile})`.\n * 2. Read the snapshot — `get()` returns an empty snapshot when the\n * file is absent / corrupt / version-mismatched.\n * 3. If the snapshot is empty, surface an actionable error naming\n * the expected file path and the two commands that populate it.\n * 4. Walk every (catalog, schema, object), filter by `--type`, then\n * match the name (case-insensitive substring by default, exact\n * when `--exact` is set), and return `SearchMatch[]` with the\n * fully-qualified `catalog.schema.name`.\n *\n * Injectable for tests via the `searchFn` parameter on `searchCommand`.\n */\nasync function defaultSearchFn(\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n): Promise<SearchMatch[]> {\n const root = opts.root ?? process.cwd();\n const cache = new catalog.CatalogCache({ root, connection: profile });\n const snapshot = await cache.get();\n if (snapshot.catalogs.length === 0) {\n throw new Error(\n `No catalog cache for profile \"${profile}\" at ${cache.path}. ` +\n `Run \\`ddt catalog refresh --connection ${profile} --root ${root}\\` ` +\n `or \\`ddt extract --connection ${profile} --output ${root} --write-catalog-cache\\` first.`,\n );\n }\n const needle = pattern.toLowerCase();\n const typeFilter = opts.objectType ? opts.objectType.toUpperCase() : undefined;\n const matches: SearchMatch[] = [];\n for (const cat of snapshot.catalogs) {\n for (const schema of cat.schemas) {\n for (const obj of schema.objects) {\n if (typeFilter && obj.objectType !== typeFilter) continue;\n const name = obj.name.toLowerCase();\n const hit = opts.exact ? name === needle : name.includes(needle);\n if (hit) {\n matches.push({\n profile,\n fqn: `${obj.catalog}.${obj.schema}.${obj.name}`,\n objectType: obj.objectType,\n });\n }\n }\n }\n }\n return matches;\n}\n\nexport function searchCommand(searchFn: SearchFn = defaultSearchFn): Command {\n const cmd = new Command('search');\n cmd\n .description('Find objects matching a name pattern across one or more connection profiles.')\n .argument('<pattern>', 'Name pattern to search for (case-insensitive substring).')\n .requiredOption(\n '--profiles <list|all>',\n 'Comma-separated profile names, or \"all\" to scan every configured profile.',\n )\n .option('--exact', 'Exact name match instead of substring.', false)\n .option('--type <objectType>', 'Filter results to a specific object type (e.g. TABLE, VIEW).')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option(\n '--profiles-dir <dir>',\n 'Directory to scan when --profiles all is used.',\n path.join(os.homedir(), '.ddt', 'connections'),\n )\n .option(\n '--root <dir>',\n 'Project / cache root containing the .ddt/cache directory. Default: cwd.',\n process.cwd(),\n )\n .option('--no-drift', 'Suppress the drift section in text output.')\n .action(async (pattern: string, opts) => {\n const profiles = await loadProfileNames(opts.profiles as string, opts.profilesDir as string);\n if (profiles.length === 0) {\n throw new Error(\n opts.profiles.toLowerCase() === 'all'\n ? `No profiles found in ${opts.profilesDir}. Run \\`ddt connection add\\` first.`\n : '--profiles must list at least one profile.',\n );\n }\n\n const results: SearchResult[] = await Promise.all(\n profiles.map(async (p) => {\n try {\n const matches = await searchFn(p, pattern, {\n exact: opts.exact as boolean,\n objectType: opts.type as string | undefined,\n root: opts.root as string,\n });\n return { profile: p, matches };\n } catch (err) {\n return {\n profile: p,\n matches: [],\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(results, null, 2) + '\\n');\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n const text = renderText(results, opts.drift !== false);\n process.stdout.write(text ? text + '\\n' : 'No results.\\n');\n });\n return cmd;\n}\n","/**\n * `ddt query-log` — AUTH.5 local query log CLI.\n *\n * Subcommands:\n * ddt query-log list [--profile <p>] [--limit N] [--format text|json]\n * ddt query-log show <id> [--format text|json|sql]\n * ddt query-log add <sql> --profile <p> [--status success|error] [--store <path>]\n * ddt query-log clear [--profile <p>] [--yes]\n *\n * The log is stored at `~/.ddt/query-log.json` (override with --store).\n * EE3 will call `appendEntry()` on the substrate directly when a query\n * is executed. This CLI surfaces it for ad-hoc review + rerun.\n *\n * Mirrors `Snowflake/packages/cli/src/commands/query-log.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { queryLog } from '@ddt-tools/core';\n\nconst DEFAULT_STORE = path.join(os.homedir(), '.ddt', 'query-log.json');\n\nasync function loadStore(storePath: string): Promise<queryLog.QueryLogStore> {\n try {\n const raw = await fs.readFile(storePath, 'utf8');\n return queryLog.QueryLogStore.deserialize(JSON.parse(raw));\n } catch {\n return new queryLog.QueryLogStore();\n }\n}\n\nasync function saveStore(storePath: string, store: queryLog.QueryLogStore): Promise<void> {\n await fs.mkdir(path.dirname(storePath), { recursive: true });\n await fs.writeFile(storePath, JSON.stringify(store.serialize(), null, 2), 'utf8');\n}\n\nexport function queryLogCommand(): Command {\n const cmd = new Command('query-log');\n cmd.description('Browse and manage the local query log from the EE3 query window (AUTH.5).');\n\n cmd\n .command('list')\n .description('List recent query log entries (newest first).')\n .option('--profile <p>', 'Filter to a specific connection profile.')\n .option('--limit <n>', 'Maximum entries to show (default 100).', '100')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n const store = await loadStore(opts.store as string);\n const entries = store.listEntries({\n profile: opts.profile as string | undefined,\n limit: parseInt(String(opts.limit ?? '100'), 10),\n });\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n process.stdout.write('No query log entries.\\n');\n return;\n }\n for (const e of entries) {\n const when = e.executedAt.slice(0, 19).replace('T', ' ');\n const dur = e.durationMs !== undefined ? ` ${e.durationMs}ms` : '';\n const rows = e.rowCount !== undefined ? ` ${e.rowCount} rows` : '';\n const status = e.status === 'error' ? ' ✗' : ' ✓';\n const sql = e.sql.replace(/\\s+/g, ' ').slice(0, 80);\n process.stdout.write(`[${e.id}] ${when} [${e.profile}]${status}${dur}${rows} ${sql}\\n`);\n }\n });\n\n cmd\n .command('show <id>')\n .description('Show a single query log entry by id.')\n .option('--format <fmt>', 'text | json | sql (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (id: string, opts) => {\n const store = await loadStore(opts.store as string);\n const entry = store.getEntry(id);\n if (!entry) throw new Error(`No entry with id '${id}'.`);\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'sql') {\n process.stdout.write(entry.sql + '\\n');\n return;\n }\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`id: ${entry.id}\\n`);\n process.stdout.write(`profile: ${entry.profile}\\n`);\n process.stdout.write(`executed: ${entry.executedAt}\\n`);\n process.stdout.write(`status: ${entry.status}\\n`);\n if (entry.durationMs !== undefined) process.stdout.write(`duration: ${entry.durationMs}ms\\n`);\n if (entry.rowCount !== undefined) process.stdout.write(`rows: ${entry.rowCount}\\n`);\n if (entry.error) process.stdout.write(`error: ${entry.error}\\n`);\n process.stdout.write(`\\n${entry.sql}\\n`);\n });\n\n cmd\n .command('add <sql>')\n .description('Manually append a query to the log (used by EE3 and for testing).')\n .requiredOption('--profile <p>', 'Connection profile the query was run against.')\n .option('--status <s>', 'success | error (default success).', 'success')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (sql: string, opts) => {\n if (opts.status !== 'success' && opts.status !== 'error') {\n throw new Error(`--status must be success or error, got: ${opts.status}`);\n }\n const store = await loadStore(opts.store as string);\n const entry = store.appendEntry({\n profile: opts.profile as string,\n sql,\n executedAt: new Date().toISOString(),\n status: opts.status as 'success' | 'error',\n });\n await saveStore(opts.store as string, store);\n process.stdout.write(`Added entry ${entry.id}.\\n`);\n });\n\n cmd\n .command('clear')\n .description('Remove query log entries.')\n .option('--profile <p>', 'Remove only entries for this profile (omit for all).')\n .option('--yes', 'Skip confirmation prompt.')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n if (!opts.yes) {\n const target = opts.profile ? `profile '${opts.profile as string}'` : 'all profiles';\n throw new Error(`Pass --yes to confirm clearing the query log for ${target}.`);\n }\n const store = await loadStore(opts.store as string);\n const removed = store.clearEntries(opts.profile as string | undefined);\n await saveStore(opts.store as string, store);\n process.stdout.write(`Cleared ${removed} entries.\\n`);\n });\n\n return cmd;\n}\n"],"mappings":"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","names":["import_commander","import_commander","import_core","safetyApi","import_commander","import_core","fs","import_node_fs","import_commander","import_core","fs","import_node_fs","import_commander","import_core","readStdin","fs","import_commander","import_core","import_commander","import_core","import_commander","import_node_fs","import_core","result","fs","import_commander","import_node_fs","import_core","renderText","fs","path","os","import_commander","import_node_fs","import_node_os","import_node_path","import_core","path","os","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/connection.ts","../src/commands/scaffold.ts","../src/commands/safety.ts","../src/commands/safer-alternative.ts","../src/commands/sketch.ts","../src/commands/compare-profiles.ts","../src/commands/explorer.ts","../src/commands/catalog.ts","../src/commands/exec.ts","../src/commands/search.ts","../src/commands/query-log.ts"],"sourcesContent":["export { connectionCommand } from './commands/connection.js';\nexport { scaffoldCommand } from './commands/scaffold.js';\nexport { safetyCommand } from './commands/safety.js';\nexport { saferAlternativeCommand } from './commands/safer-alternative.js';\nexport { sketchCommand } from './commands/sketch.js';\nexport { compareProfilesCommand } from './commands/compare-profiles.js';\nexport { explorerCommand } from './commands/explorer.js';\nexport { catalogCommand } from './commands/catalog.js';\nexport { execCommand } from './commands/exec.js';\nexport type { ExecResult, ExecFn } from './commands/exec.js';\nexport { searchCommand } from './commands/search.js';\nexport type { SearchMatch, SearchResult, SearchFn } from './commands/search.js';\nexport { queryLogCommand } from './commands/query-log.js';\n","import { Command } from 'commander';\nimport {\n createConnection,\n defaultProfilesPath,\n getProfile,\n loadProfiles,\n removeProfile,\n upsertProfile,\n type DatabricksConnectionProfile,\n type DatabricksAuth,\n} from '@ddt-tools/core';\n\n/**\n * `ddt connection` — manage Databricks workspace connection profiles.\n *\n * Profiles live at `~/.ddt/profiles.json` (overridable via `$DDT_PROFILES_PATH`).\n * add / list / get / remove are wired today. `test` (probe a profile via\n * the workspace REST API) waits on the OAuth U2M flow before it can land.\n */\nexport function connectionCommand(): Command {\n const cmd = new Command('connection').description('Manage Databricks connection profiles.');\n\n cmd\n .command('add [name]')\n .description('Store a new connection profile.')\n .option('--name <name>', 'Profile name (flag form of the positional name arg)')\n .option('--host <host>', 'Workspace host, e.g. dbc-12345-abcd.cloud.databricks.com')\n .option('--auth <method>', 'One of: pat | oauth-m2m | oauth-u2m | azure-ad | google-idc', 'pat')\n .option(\n '--token <token>',\n 'PAT token — use env:DATABRICKS_TOKEN to reference an env var, never inline a secret',\n )\n .option('--client-id <id>', 'OAuth M2M / Azure AD client ID')\n .option('--client-secret <secret>', 'OAuth M2M / Azure AD client secret')\n .option('--tenant-id <id>', 'Azure AD tenant ID')\n .option(\n '--service-account-key-path <path>',\n 'Path to a GCP service-account key JSON file (for google-idc auth)',\n )\n .requiredOption('--warehouse-id <id>', 'SQL warehouse ID for DDL operations')\n .option('--catalog <catalog>', 'Default Unity Catalog catalog')\n .option('--schema <schema>', 'Default schema')\n .action(async (nameArg: string | undefined, opts) => {\n // Accept the profile name either positionally (`ddt connection add prod`)\n // or via `--name prod` (the flag form `sdt connection add` uses, and what\n // GETTING_STARTED documents canonically). Flag wins when both are given.\n const name = opts.name ? String(opts.name) : (nameArg ?? '');\n if (!name) {\n throw new Error(\n 'connection add needs a profile name — pass it positionally (`ddt connection add <name>`) or via `--name`.',\n );\n }\n if (!opts.host) throw new Error('--host is required');\n const auth = buildAuth(opts);\n const profile: DatabricksConnectionProfile = {\n name,\n platform: 'Databricks',\n auth,\n warehouseId: String(opts.warehouseId),\n ...(opts.catalog ? { catalog: String(opts.catalog) } : {}),\n ...(opts.schema ? { schema: String(opts.schema) } : {}),\n };\n await upsertProfile(profile);\n console.log(`Saved profile \"${name}\" → ${defaultProfilesPath()}`);\n });\n\n cmd\n .command('list')\n .description('List configured Databricks profiles.')\n .action(async () => {\n const profiles = await loadProfiles();\n if (profiles.length === 0) {\n console.log(`(no profiles configured at ${defaultProfilesPath()})`);\n return;\n }\n for (const p of profiles) {\n console.log(`${p.name}\\t${p.auth.method}\\t${p.auth.host}\\twarehouse=${p.warehouseId}`);\n }\n });\n\n cmd\n .command('get <name>')\n .description('Print a profile (secrets are redacted).')\n .action(async (name: string) => {\n const p = await getProfile(name);\n const redacted: DatabricksConnectionProfile = {\n ...p,\n auth: redactAuth(p.auth),\n };\n console.log(JSON.stringify(redacted, null, 2));\n });\n\n cmd\n .command('remove <name>')\n .description('Delete a connection profile.')\n .action(async (name: string) => {\n const removed = await removeProfile(name);\n console.log(removed ? `Removed profile \"${name}\".` : `No profile \"${name}\" found.`);\n if (!removed) process.exitCode = 1;\n });\n\n cmd\n .command('test <name>')\n .description(\n 'Probe a connection profile via the workspace REST API (`/api/2.0/preview/scim/v2/Me`).',\n )\n .action(async (name: string) => {\n const profile = await getProfile(name);\n const conn = createConnection(profile);\n try {\n await conn.connect();\n const info = await conn.test();\n console.log(`OK ${name}`);\n console.log(` host: ${profile.auth.host}`);\n console.log(` account: ${info.account}`);\n console.log(` version: ${info.version}`);\n } catch (err) {\n console.error(`FAIL ${name}: ${err instanceof Error ? err.message : String(err)}`);\n process.exitCode = 1;\n } finally {\n await conn.disconnect();\n }\n });\n\n return cmd;\n}\n\nfunction buildAuth(opts: {\n host?: string;\n auth?: string;\n token?: string;\n clientId?: string;\n clientSecret?: string;\n tenantId?: string;\n serviceAccountKeyPath?: string;\n}): DatabricksAuth {\n const host = String(opts.host);\n const method = String(opts.auth ?? 'pat').toLowerCase();\n switch (method) {\n case 'pat':\n case 'personal_access_token':\n if (!opts.token) throw new Error('--token is required for PAT auth');\n return { method: 'PERSONAL_ACCESS_TOKEN', host, token: String(opts.token) };\n case 'oauth-m2m':\n case 'oauth_m2m':\n if (!opts.clientId || !opts.clientSecret) {\n throw new Error('--client-id and --client-secret are required for OAuth M2M');\n }\n return {\n method: 'OAUTH_M2M',\n host,\n clientId: String(opts.clientId),\n clientSecret: String(opts.clientSecret),\n };\n case 'oauth-u2m':\n case 'oauth_u2m':\n return { method: 'OAUTH_U2M', host };\n case 'azure-ad':\n case 'azure_ad':\n if (!opts.tenantId || !opts.clientId) {\n throw new Error('--tenant-id and --client-id are required for Azure AD');\n }\n return {\n method: 'AZURE_AD',\n host,\n tenantId: String(opts.tenantId),\n clientId: String(opts.clientId),\n ...(opts.clientSecret ? { clientSecret: String(opts.clientSecret) } : {}),\n };\n case 'google-idc':\n case 'google_idc':\n if (!opts.serviceAccountKeyPath) {\n throw new Error('--service-account-key-path is required for google-idc auth');\n }\n return {\n method: 'GOOGLE_IDC',\n host,\n serviceAccountKeyPath: String(opts.serviceAccountKeyPath),\n };\n default:\n throw new Error(`Unknown --auth value: ${method}`);\n }\n}\n\nfunction redactAuth(auth: DatabricksAuth): DatabricksAuth {\n if (auth.method === 'PERSONAL_ACCESS_TOKEN' && auth.token && !auth.token.startsWith('env:')) {\n return { ...auth, token: '<redacted>' };\n }\n if (auth.method === 'OAUTH_M2M' && auth.clientSecret && !auth.clientSecret.startsWith('env:')) {\n return { ...auth, clientSecret: '<redacted>' };\n }\n if (auth.method === 'AZURE_AD' && auth.clientSecret && !auth.clientSecret.startsWith('env:')) {\n return { ...auth, clientSecret: '<redacted>' };\n }\n return auth;\n}\n","import { Command } from 'commander';\n\n/**\n * Placeholder factory for commands whose backing engine is a later\n * deliverable. Prints a clear \"not yet implemented\" message and exits\n * non-zero so CI notices.\n *\n * Mirrors `sdt scaffold` — exported for embedders, not wired into the\n * DDT CLI itself.\n */\nexport function scaffoldCommand(name: string): Command {\n return new Command(name)\n .description(`${name} — Databricks (scaffold; later-release deliverable).`)\n .action(() => {\n console.error(\n `ddt ${name}: scaffold — the Databricks engine for this command is a later deliverable.\\n` +\n `Track progress at Databricks/docs/ROADMAP.md.`,\n );\n process.exitCode = 2;\n });\n}\n","/**\n * `ddt safety` — inspect safety-finding codes.\n *\n * Subcommands:\n * ddt safety list — list every known finding code with a one-line summary\n * ddt safety explain <code> — deep explainer for a single code: why it is dangerous,\n * what cannot be reversed, safer alternatives, required gates\n *\n * The finding codes are stable identifiers attached to every `SafetyFinding`\n * the classifier emits during `ddt compare` / `ddt publish`. When the user\n * sees a finding they don't understand, they can copy the code and ask:\n *\n * ddt safety explain DROP_UNRECOVERABLE\n *\n * Mirrors `Snowflake/packages/cli/src/commands/safety.ts` — paired-file rule.\n * See `docs/UX_PLAYBOOK.md` §3 (dangerous-op UX) and\n * `docs/AI_FEATURES.md` use case C2.\n */\nimport { Command } from 'commander';\nimport { safety as safetyApi, type safety as safetyNs } from '@ddt-tools/core';\n\ntype FindingExplanation = safetyNs.FindingExplanation;\ntype SafetyFindingCode = safetyNs.SafetyFindingCode;\n\nexport function safetyCommand(): Command {\n const cmd = new Command('safety');\n cmd.description(\n 'Inspect the safety-finding catalog. See `ddt safety list` and `ddt safety explain <code>`.',\n );\n\n cmd\n .command('list')\n .description('List every known finding code with category + one-line summary.')\n .option('--format <format>', 'Output format: table | json', 'table')\n .option(\n '--category <kind>',\n 'Filter to one category: unrecoverable | destructive | expensive | warning. Default: all.',\n )\n .action((opts: { format?: string; category?: string }) => {\n const codes = safetyApi.listFindingCodes();\n let entries = codes\n .map((c) => safetyApi.explainFinding(c))\n .filter((e): e is FindingExplanation => e !== undefined);\n if (opts.category) {\n const want = opts.category.toUpperCase();\n const valid = ['UNRECOVERABLE', 'DESTRUCTIVE', 'EXPENSIVE', 'WARNING'];\n if (!valid.includes(want)) {\n console.error(\n `Unknown --category \"${opts.category}\". Use one of: ${valid.join(' | ').toLowerCase()}.`,\n );\n process.exitCode = 1;\n return;\n }\n entries = entries.filter((e) => e.category === want);\n }\n if ((opts.format ?? 'table') === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n console.log('(no entries match the filter)');\n return;\n }\n printList(entries);\n });\n\n cmd\n .command('explain')\n .description('Expand a finding code into a deep \"why this is dangerous\" page.')\n .argument('<code>', 'The finding code (e.g. DROP_UNRECOVERABLE, COLUMN_TYPE_CHANGE)')\n .option('--format <format>', 'Output format: text | json | markdown', 'text')\n .action((codeArg: string, opts: { format?: string }) => {\n const code = codeArg.toUpperCase() as SafetyFindingCode;\n const entry = safetyApi.explainFinding(code);\n if (!entry) {\n console.error(`Unknown safety finding code: \"${codeArg}\"`);\n console.error(' Try: ddt safety list');\n process.exitCode = 1;\n return;\n }\n const format = (opts.format ?? 'text').toLowerCase();\n if (format === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n if (format === 'markdown') {\n process.stdout.write(renderMarkdown(entry) + '\\n');\n return;\n }\n printDeep(entry);\n });\n\n return cmd;\n}\n\nfunction printList(entries: readonly FindingExplanation[]): void {\n const byCategory = new Map<FindingExplanation['category'], FindingExplanation[]>();\n for (const e of entries) {\n const arr = byCategory.get(e.category) ?? [];\n arr.push(e);\n byCategory.set(e.category, arr);\n }\n const order: FindingExplanation['category'][] = [\n 'UNRECOVERABLE',\n 'DESTRUCTIVE',\n 'EXPENSIVE',\n 'WARNING',\n ];\n for (const cat of order) {\n const arr = byCategory.get(cat);\n if (!arr || arr.length === 0) continue;\n console.log(`# ${cat} (${arr.length})`);\n for (const e of arr) {\n console.log(` ${e.code}`);\n console.log(` ${e.title}`);\n console.log(` ${e.summary}`);\n }\n console.log('');\n }\n console.log('Use `ddt safety explain <code>` for the full per-finding write-up.');\n}\n\nfunction printDeep(entry: FindingExplanation): void {\n console.log(`${entry.code} [${entry.category}]`);\n console.log(entry.title);\n console.log('');\n console.log('Summary');\n console.log(` ${entry.summary}`);\n console.log('');\n console.log('Why this is dangerous');\n for (const line of wrap(entry.whyDangerous, 76)) {\n console.log(` ${line}`);\n }\n console.log('');\n console.log('What cannot be reversed');\n for (const item of entry.cannotBeReversed) console.log(` - ${item}`);\n console.log('');\n console.log('Safer alternatives');\n for (const item of entry.saferAlternatives) console.log(` - ${item}`);\n console.log('');\n if (entry.requiredGates.length > 0) {\n console.log('Required gates to allow this finding through');\n for (const g of entry.requiredGates) console.log(` - ${g}`);\n console.log('');\n }\n if (entry.example) {\n console.log('Example');\n console.log(` ${entry.example}`);\n }\n}\n\nfunction renderMarkdown(entry: FindingExplanation): string {\n const lines: string[] = [];\n lines.push(`## ${entry.code} — ${entry.title}`);\n lines.push('');\n lines.push(`**Category:** ${entry.category}`);\n lines.push('');\n lines.push(`**Summary:** ${entry.summary}`);\n lines.push('');\n lines.push('### Why this is dangerous');\n lines.push(entry.whyDangerous);\n lines.push('');\n lines.push('### What cannot be reversed');\n for (const item of entry.cannotBeReversed) lines.push(`- ${item}`);\n lines.push('');\n lines.push('### Safer alternatives');\n for (const item of entry.saferAlternatives) lines.push(`- ${item}`);\n if (entry.requiredGates.length > 0) {\n lines.push('');\n lines.push('### Required gates');\n for (const g of entry.requiredGates) lines.push(`- \\`${g}\\``);\n }\n if (entry.example) {\n lines.push('');\n lines.push('### Example');\n lines.push('```');\n lines.push(entry.example);\n lines.push('```');\n }\n return lines.join('\\n');\n}\n\nfunction wrap(text: string, width: number): string[] {\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let current = '';\n for (const word of words) {\n if (current.length === 0) {\n current = word;\n } else if (current.length + 1 + word.length <= width) {\n current += ' ' + word;\n } else {\n lines.push(current);\n current = word;\n }\n }\n if (current.length > 0) lines.push(current);\n return lines;\n}\n","/**\n * `ddt safer-alternative` — call the AI provider to suggest a safer DDL\n * alternative for a flagged-as-dangerous migration step.\n *\n * Composes `@ddt-tools/core/saferAlternative.suggestSaferAlternative` with the\n * configured AI provider (`@ddt-tools/core/ai.complete`). The CLI is the thin\n * adapter; all the prompt-building and parsing lives in core so the\n * VS Code CodeLens / MCP server / future hosts share the same behavior.\n *\n * Inputs (all surfaced as flags):\n * --code SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE)\n * --fqn Object FQN the finding refers to\n * --object-type Object type (e.g. MANAGED_TABLE, VIEW)\n * --reason Short reason from the safety classifier\n * --gate Optional SafetyGate (preserved on the suggestion)\n * --sql <path> Path to a file with the dangerous DDL (or \"-\" for stdin)\n * --context <path> Optional path to the surrounding source DDL\n * --intent <text> Optional human-authored intent notes\n * --format text | json (default text)\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, saferAlternative, type safety } from '@ddt-tools/core';\n\nexport function saferAlternativeCommand(): Command {\n const cmd = new Command('safer-alternative');\n cmd\n .description(\n 'AI-assist: propose a safer DDL alternative for a safety finding. Requires a configured AI provider (ddt ai status).',\n )\n .requiredOption('--code <code>', 'SafetyFindingCode (e.g. COLUMN_DROP, DROP_UNRECOVERABLE).')\n .requiredOption('--fqn <fqn>', 'Object FQN the finding refers to.')\n .requiredOption('--object-type <type>', 'Object type (e.g. MANAGED_TABLE, VIEW, FUNCTION).')\n .requiredOption('--reason <text>', 'Short reason text from the safety classifier.')\n .option(\n '--gate <gate>',\n 'Optional SafetyGate the finding raised (e.g. REQUIRE_ALLOW_DROP_COLUMN).',\n )\n .option('--sql <path>', 'Path to a file with the dangerous DDL. Use \"-\" to read from stdin.')\n .option('--context <path>', 'Optional path to the surrounding source DDL.')\n .option('--intent <text>', 'Optional human-authored intent notes.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (opts) => {\n const dangerousSql = await readInput(\n opts.sql,\n '--sql is required (use a path or \"-\" for stdin).',\n );\n const contextSql = opts.context ? await fs.readFile(String(opts.context), 'utf8') : undefined;\n\n const finding: safety.SafetyFinding = {\n code: String(opts.code) as safety.SafetyFindingCode,\n category: 'DESTRUCTIVE',\n fqn: String(opts.fqn),\n objectType: String(opts.objectType) as safety.SafetyFinding['objectType'],\n reason: String(opts.reason),\n gate: opts.gate ? (String(opts.gate) as safety.SafetyGate) : undefined,\n };\n\n const result = await saferAlternative.suggestSaferAlternative(\n {\n finding,\n dangerousSql,\n contextSql,\n intentNotes: opts.intent ? String(opts.intent) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'safer-alternative',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n if (String(opts.format).toLowerCase() === 'json') {\n const { rawModelText: _omit, ...keep } = result;\n console.log(JSON.stringify(keep, null, 2));\n return;\n }\n\n console.log(`Confidence: ${result.confidence}${result.parseFailed ? ' (parse failed)' : ''}`);\n console.log(`Reasoning: ${result.reasoning}`);\n if (result.alternativeSql) {\n console.log('');\n console.log('--- Proposed safer DDL ---');\n console.log(result.alternativeSql);\n } else {\n console.warn('No safer alternative SQL was returned.');\n }\n if (result.requiredGates.length > 0) {\n console.log(`Required gates: ${result.requiredGates.join(', ')}`);\n }\n });\n return cmd;\n}\n\nasync function readInput(pathOrDash: unknown, missingMessage: string): Promise<string> {\n if (!pathOrDash) throw new Error(missingMessage);\n const p = String(pathOrDash);\n if (p === '-') {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n }\n return fs.readFile(p, 'utf8');\n}\n","/**\n * `ddt sketch <kind>` — generate idiomatic Databricks UC DDL from a free-form\n * prose description via the configured AI provider.\n *\n * Composes `@ddt-tools/core/objectSketch.sketchToDdl` with `@ddt-tools/core/ai.complete`.\n * Output is always wrapped in a \"REVIEW BEFORE DEPLOY\" header so the user\n * never confuses model output with hand-authored DDL.\n *\n * Inputs:\n * <kind> managed-table | external-table | streaming-table\n * | materialized-view | view | function | volume\n * --description <text> Free-form description (or \"-\" to read from stdin)\n * --target <fqn> Optional target FQN (e.g. analytics.public.orders)\n * --context <text> Optional additional context\n * --out <path> Optional output file. Default: stdout.\n * --format <fmt> text | json. Default text (just the DDL).\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { ai, objectSketch } from '@ddt-tools/core';\n\nconst KINDS = [\n 'managed-table',\n 'external-table',\n 'streaming-table',\n 'materialized-view',\n 'view',\n 'function',\n 'volume',\n] as const;\n\ntype Kind = (typeof KINDS)[number];\n\nexport function sketchCommand(): Command {\n const cmd = new Command('sketch');\n cmd\n .description(\n 'AI-assist: scaffold idiomatic Databricks UC DDL from a prose description. Output always carries a REVIEW BEFORE DEPLOY header.',\n )\n .argument('<kind>', `Object kind: ${KINDS.join(' | ')}`)\n .requiredOption('--description <text>', 'Free-form description. Use \"-\" to read from stdin.')\n .option('--target <fqn>', 'Target FQN (e.g. analytics.public.orders).')\n .option('--context <text>', 'Optional additional context (e.g. \"use SQL warehouse small\").')\n .option('--out <path>', 'Output file. Default stdout.')\n .option('--format <fmt>', 'Output format: text | json. Default text.', 'text')\n .option(\n '--ai-max-spend <usd>',\n \"Refuse the call if today's estimated spend ≥ this (USD). 0 = no cap.\",\n '0',\n )\n .action(async (kindArg, opts) => {\n const kind = String(kindArg).toLowerCase() as Kind;\n if (!KINDS.includes(kind)) {\n throw new Error(`Unknown kind \"${kindArg}\". Use one of: ${KINDS.join(' | ')}`);\n }\n\n const description =\n String(opts.description) === '-' ? await readStdin() : String(opts.description);\n const targetFqn = opts.target ? splitFqn(String(opts.target)) : undefined;\n\n const result = await objectSketch.sketchToDdl(\n {\n description,\n objectKind: kind,\n targetFqn,\n additionalContext: opts.context ? String(opts.context) : undefined,\n },\n {\n completeFn: async (prompt) => {\n const r = await ai.complete([{ role: 'user', content: prompt }], {\n feature: 'object-sketch',\n maxSpendUsd: Number(opts.aiMaxSpend ?? '0') || 0,\n });\n return r.text;\n },\n },\n );\n\n const output =\n String(opts.format).toLowerCase() === 'json'\n ? JSON.stringify({ ...result, rawModelText: undefined }, null, 2)\n : result.generatedSql;\n\n if (opts.out) {\n await fs.writeFile(String(opts.out), output, 'utf8');\n console.log(`Wrote ${String(opts.out)} (${output.length} bytes)`);\n } else {\n console.log(output);\n }\n\n if (result.assumptions.length > 0) {\n console.error('');\n console.error('Model assumptions:');\n for (const a of result.assumptions) console.error(` - ${a}`);\n }\n if (result.parseFailed) {\n console.warn('Model output could not be parsed — see the raw text via --format json.');\n }\n });\n return cmd;\n}\n\nfunction splitFqn(fqn: string): { catalog?: string; schema?: string; name: string } {\n const parts = fqn.split('.');\n if (parts.length === 1) return { name: parts[0]! };\n if (parts.length === 2) return { schema: parts[0], name: parts[1]! };\n if (parts.length === 3) return { catalog: parts[0], schema: parts[1], name: parts[2]! };\n throw new Error(`Invalid --target \"${fqn}\": expected 1, 2, or 3 dot-separated parts.`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `ddt compare-profiles` — manage saved comparison profiles.\n *\n * A profile is \"Source X (connection|pac|project) → Target Y, with these\n * mapping rules\", persisted to `<cwd>/.ddt/compare-profiles.json`. The\n * eventual VS Code webview reads/writes the same store; this CLI gives\n * power-users the same affordances headlessly.\n *\n * Subcommands:\n * list — list all saved profiles (table or JSON)\n * show <id> — print one profile (table or JSON)\n * save — upsert a profile from a JSON file (--json-file <path>) or stdin\n * remove <id> — delete a profile\n * preview <id> — run `previewMatch` over the saved profile's\n * source + target endpoints and report counts +\n * examples of matched / source-only / target-only\n * FQNs. Catches typo'd schema names before a\n * full extract + diff round-trip.\n *\n * `preview` resolves each endpoint locally:\n * - kind=connection — reads the EE1 catalog cache at\n * `<root>/.ddt/cache/<reference>/catalog.msgpack` (legacy\n * `catalog.json` also accepted). Run\n * `ddt catalog refresh --connection <reference>` first.\n * - kind=pac — reads the `.ddtpac` archive at `reference`.\n * - kind=project — reads the `.ddtproj` at `reference`.\n */\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { catalog, compareProfiles, loadProject, pac, parseProjectModel } from '@ddt-tools/core';\nimport type { DatabricksObject, FullyQualifiedName } from '@ddt-tools/core/model';\n\nexport function compareProfilesCommand(): Command {\n const cmd = new Command('compare-profiles');\n cmd.description('Manage saved compare profiles (.ddt/compare-profiles.json).');\n\n cmd\n .command('list')\n .description('List every saved profile.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const all = await store.list();\n if (opts.json) {\n console.log(JSON.stringify(all, null, 2));\n return;\n }\n if (all.length === 0) {\n console.log('(no compare profiles saved yet)');\n console.log(` store: ${store.path}`);\n return;\n }\n console.log(`${all.length} compare profile(s):`);\n for (const p of all) {\n console.log(` ${p.id.padEnd(24)} ${p.name}`);\n console.log(` source: ${p.source.kind}=${p.source.reference}`);\n console.log(` target: ${p.target.kind}=${p.target.reference}`);\n console.log(` mappings: ${p.mappings.length} updated: ${p.updatedAt}`);\n }\n });\n\n cmd\n .command('show')\n .description('Show one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of a human table.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const p = await store.get(String(id));\n if (!p) {\n console.error(\n `No profile with id \"${id}\". Run \\`ddt compare-profiles list\\` to enumerate.`,\n );\n process.exitCode = 1;\n return;\n }\n if (opts.json) {\n console.log(JSON.stringify(p, null, 2));\n return;\n }\n console.log(`Profile: ${p.name} (${p.id})`);\n if (p.description) console.log(` ${p.description}`);\n console.log(\n ` source: ${p.source.kind}=${p.source.reference}${p.source.catalog ? ` cat=${p.source.catalog}` : ''}${p.source.schema ? ` schema=${p.source.schema}` : ''}`,\n );\n console.log(\n ` target: ${p.target.kind}=${p.target.reference}${p.target.catalog ? ` cat=${p.target.catalog}` : ''}${p.target.schema ? ` schema=${p.target.schema}` : ''}`,\n );\n console.log(` case-sensitive: ${p.caseSensitive ? 'yes' : 'no'}`);\n console.log(` rewrite-inside-strings: ${p.rewriteInsideStrings ? 'yes' : 'no'}`);\n console.log(` updatedAt: ${p.updatedAt}`);\n if (p.mappings.length === 0) {\n console.log(' mappings: (none — identity)');\n } else {\n console.log(` mappings (${p.mappings.length}):`);\n for (const m of p.mappings) console.log(` ${m.source} => ${m.target}`);\n }\n });\n\n cmd\n .command('save')\n .description('Upsert a profile from a JSON file or stdin.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json-file <path>', 'Path to a JSON file containing one profile. Use \"-\" for stdin.')\n .action(async (opts) => {\n if (!opts.jsonFile) {\n throw new Error('--json-file is required (use a path or \"-\" for stdin).');\n }\n const raw =\n String(opts.jsonFile) === '-'\n ? await readStdin()\n : await fs.readFile(String(opts.jsonFile), 'utf8');\n const parsed = JSON.parse(raw) as compareProfiles.CompareProfile;\n if (!parsed?.id || !parsed?.name || !parsed?.source || !parsed?.target) {\n throw new Error(\n 'Profile JSON must contain at minimum: id, name, source, target. mappings defaults to [].',\n );\n }\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const stamped = await store.upsert({ ...parsed, mappings: parsed.mappings ?? [] });\n console.log(`Saved profile \"${stamped.name}\" (${stamped.id})`);\n console.log(` store: ${store.path}`);\n });\n\n cmd\n .command('remove')\n .description('Delete one profile by id.')\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const removed = await store.remove(String(id));\n if (removed) {\n console.log(`Removed profile \"${id}\".`);\n } else {\n console.warn(`No profile with id \"${id}\" — nothing to remove.`);\n }\n });\n\n cmd\n .command('preview')\n .description(\n \"Preview which FQNs match between the profile's source and target. Local-only — no workspace round-trip.\",\n )\n .argument('<id>', 'Profile id (from `compare-profiles list`).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option(\n '--examples <n>',\n 'Max example FQNs to show per bucket in human output. Default 5.',\n (v) => parseInt(v, 10),\n 5,\n )\n .option('--json', 'Emit the full PreviewSummary as JSON.')\n .action(async (id, opts) => {\n const store = new compareProfiles.CompareProfilesStore({ root: String(opts.root) });\n const profile = await store.get(String(id));\n if (!profile) {\n console.error(\n `No profile with id \"${id}\". Run \\`ddt compare-profiles list\\` to enumerate.`,\n );\n process.exitCode = 1;\n return;\n }\n\n const root = String(opts.root);\n const source = await resolveEndpointFqns(profile.source, root);\n const target = await resolveEndpointFqns(profile.target, root);\n\n const summary = compareProfiles.previewMatch({\n source: source.fqns,\n target: target.fqns,\n mappings: profile.mappings,\n ...(profile.caseSensitive ? { caseSensitive: true } : {}),\n });\n\n if (opts.json) {\n console.log(\n JSON.stringify(\n {\n profile: { id: profile.id, name: profile.name },\n source: {\n kind: profile.source.kind,\n reference: profile.source.reference,\n count: source.fqns.length,\n },\n target: {\n kind: profile.target.kind,\n reference: profile.target.reference,\n count: target.fqns.length,\n },\n summary,\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n console.log(`Preview: ${profile.name} (${profile.id})`);\n console.log(\n ` source (${profile.source.kind}=${profile.source.reference}): ${source.fqns.length} object(s)${source.note ? ` — ${source.note}` : ''}`,\n );\n console.log(\n ` target (${profile.target.kind}=${profile.target.reference}): ${target.fqns.length} object(s)${target.note ? ` — ${target.note}` : ''}`,\n );\n console.log('');\n console.log(` matched: ${summary.matchedCount}`);\n console.log(` source-only: ${summary.sourceOnlyCount}`);\n console.log(` target-only: ${summary.targetOnlyCount}`);\n\n const exN = Math.max(0, Number(opts.examples));\n printBucket('matched', summary.matched, exN);\n printBucket('source-only', summary.sourceOnly, exN);\n printBucket('target-only', summary.targetOnly, exN);\n\n if (\n summary.matchedCount === 0 &&\n (summary.sourceOnlyCount > 0 || summary.targetOnlyCount > 0)\n ) {\n console.warn(\"No FQNs matched — check the profile's scope and mapping rules.\");\n }\n });\n\n return cmd;\n}\n\ninterface EndpointResolution {\n fqns: FullyQualifiedName[];\n note?: string;\n}\n\nasync function resolveEndpointFqns(\n endpoint: compareProfiles.CompareProfile['source'],\n root: string,\n): Promise<EndpointResolution> {\n if (endpoint.kind === 'connection') {\n const cache = new catalog.CatalogCache({ root, connection: endpoint.reference });\n const snapshot = await cache.get();\n if (snapshot.catalogs.length === 0) {\n return {\n fqns: [],\n note: `empty catalog cache at ${cache.path} — run \\`ddt catalog refresh --connection ${endpoint.reference}\\` first`,\n };\n }\n return { fqns: fqnsFromSnapshot(snapshot, endpoint.catalog, endpoint.schema) };\n }\n if (endpoint.kind === 'pac') {\n const contents = await pac.readPac(endpoint.reference);\n return { fqns: fqnsFromObjects(contents.model, endpoint.catalog, endpoint.schema) };\n }\n // kind === 'project'\n const loaded = await loadProject(endpoint.reference);\n const model = await parseProjectModel(loaded);\n return { fqns: fqnsFromObjects(model, endpoint.catalog, endpoint.schema) };\n}\n\nfunction fqnsFromSnapshot(\n snapshot: catalog.CatalogSnapshot,\n catalogScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const cat of snapshot.catalogs) {\n if (catalogScope && !sameId(cat.catalog, catalogScope)) continue;\n for (const sc of cat.schemas) {\n if (schemaScope && !sameId(sc.schema, schemaScope)) continue;\n for (const obj of sc.objects) {\n // FQN uses `database` for UC's catalog — paired-file convention.\n out.push({ database: obj.catalog, schema: obj.schema, name: obj.name });\n }\n }\n }\n return out;\n}\n\nfunction fqnsFromObjects(\n model: readonly DatabricksObject[],\n catalogScope: string | undefined,\n schemaScope: string | undefined,\n): FullyQualifiedName[] {\n const sameId = (a: string | undefined, b: string | undefined): boolean =>\n !!a && !!b && a.toUpperCase() === b.toUpperCase();\n const out: FullyQualifiedName[] = [];\n for (const obj of model) {\n // FQN uses `database` for UC's catalog — paired-file convention.\n if (catalogScope && !sameId(obj.fqn.database, catalogScope)) continue;\n if (schemaScope && !sameId(obj.fqn.schema, schemaScope)) continue;\n out.push(obj.fqn);\n }\n return out;\n}\n\nfunction printBucket(label: string, items: readonly string[], exampleN: number): void {\n if (items.length === 0) return;\n console.log('');\n console.log(\n ` ${label} examples (showing ${Math.min(exampleN, items.length)} of ${items.length}):`,\n );\n for (const fqn of items.slice(0, exampleN)) console.log(` ${fqn}`);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : (chunk as Buffer));\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n","/**\n * `ddt explorer` — ASCII tree dump of the live catalog/schema/object\n * hierarchy for a connected target, read from the EE1 catalog cache.\n *\n * The eventual VS Code TreeDataProvider walks the same `treeForSnapshot`\n * shape; this CLI gives non-VS-Code users the same browsable view of the\n * cached catalog. No live queries are issued — the cache is read-only.\n * Run `ddt catalog refresh --connection <name>` first to populate it.\n *\n * Inputs:\n * --connection <name> Required. Connection profile name to load the cache for.\n * --root <path> Project root (where .ddt/cache/ lives). Default cwd.\n * --filter <query> Typeahead filter; case-insensitive substring match.\n * Keeps every ancestor of a leaf match.\n * --json Emit the tree as JSON instead of an ASCII tree.\n */\nimport { Command } from 'commander';\nimport { catalog, objectExplorer } from '@ddt-tools/core';\n\nexport function explorerCommand(): Command {\n const cmd = new Command('explorer');\n cmd\n .description(\n 'ASCII tree dump of the cached catalog for a connection. Run `ddt catalog refresh` first to populate.',\n )\n .requiredOption('--connection <name>', 'Connection profile name (the cache subfolder).')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--filter <query>', 'Typeahead substring filter (case-insensitive).')\n .option(\n '--depth <n>',\n 'Truncate tree at depth N (0 = root only, 1 = +catalogs, 2 = +schemas, 3 = +object-groups, 4 = +objects). Default unlimited.',\n (v) => parseInt(v, 10),\n )\n .option('--json', 'Emit tree as JSON instead of ASCII.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n let tree = objectExplorer.treeForSnapshot(snapshot);\n if (opts.filter) tree = objectExplorer.filterTree(tree, String(opts.filter));\n if (typeof opts.depth === 'number') tree = objectExplorer.truncateTree(tree, opts.depth);\n\n if (snapshot.catalogs.length === 0) {\n console.warn(`Catalog cache is empty for connection \"${opts.connection}\".`);\n console.warn(` Cache file: ${cache.path}`);\n console.warn(` Run \\`ddt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n\n if (opts.json) {\n console.log(JSON.stringify(tree, null, 2));\n return;\n }\n\n renderAsciiTree(tree);\n });\n return cmd;\n}\n\n/**\n * Render the explorer tree as an ASCII tree (├──, │, └──). Mirrors the\n * GNU `tree`(1) glyph set for familiarity. Root prints without a\n * connector; descendants get the standard branch glyphs.\n */\nfunction renderAsciiTree(root: objectExplorer.ExplorerNode): void {\n const desc = root.description ? ` (${root.description})` : '';\n console.log(`${root.label}${desc}`);\n const children = root.children ?? [];\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, '', i === children.length - 1);\n }\n}\n\nfunction renderChild(node: objectExplorer.ExplorerNode, prefix: string, isLast: boolean): void {\n const connector = isLast ? '└── ' : '├── ';\n const desc = node.description ? ` (${node.description})` : '';\n console.log(`${prefix}${connector}${node.label}${desc}`);\n const children = node.children ?? [];\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n for (let i = 0; i < children.length; i++) {\n renderChild(children[i]!, childPrefix, i === children.length - 1);\n }\n}\n","/**\n * `ddt catalog` — manage the per-connection catalog cache (EE1 substrate).\n *\n * ddt catalog refresh --connection <name> [--catalogs <csv>] [--concurrency <n>]\n * ddt catalog show --connection <name> [--json]\n * ddt catalog clear --connection <name>\n *\n * `refresh` opens a live Databricks SQL warehouse connection, discovers\n * catalogs via `SHOW CATALOGS`, runs the bulk-scan SQL per catalog via\n * the bounded promise pool, and writes the assembled snapshot to\n * `<root>/.ddt/cache/<conn>/catalog.msgpack` (RES.1 — was `catalog.json`\n * before 2026-05-16; the cache reader still accepts the legacy form for\n * one major version). Schema fingerprints (`MAX(LAST_ALTERED)`) are\n * checked first; catalogs that haven't changed since the last refresh\n * are skipped.\n *\n * `show` reads the cache file and pretty-prints (or emits JSON).\n * `clear` deletes the cache file (and its parent dir if empty).\n *\n * Object Explorer (`ddt explorer`) and the eventual EE2 intellisense\n * provider both consume this cache.\n */\nimport { Command } from 'commander';\nimport { catalog, createConnection, getProfile, type DatabricksConnection } from '@ddt-tools/core';\n\n/**\n * Built-in catalogs that almost no one wants in their cache. Pass\n * `--include-builtins` to keep them. `system` is intentionally excluded\n * because the bulk-scan SQL filters out `information_schema` already.\n */\nconst BUILTIN_CATALOGS = new Set(['system', 'samples', '__databricks_internal']);\n\ninterface ShowCatalogsRow {\n catalog?: string;\n catalog_name?: string;\n CATALOG?: string;\n CATALOG_NAME?: string;\n}\n\nexport function catalogCommand(): Command {\n const cmd = new Command('catalog');\n cmd.description(\n 'Manage the per-connection catalog cache used by the Object Explorer + EE2 intellisense.',\n );\n\n cmd\n .command('refresh')\n .description('Open the connection, scan every (non-builtin) catalog, write the catalog cache.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--catalogs <csv>', 'Comma-separated list. Default: every non-builtin catalog.')\n .option('--include-builtins', 'Include system / samples / __databricks_internal.', false)\n .option(\n '--concurrency <n>',\n 'Bounded-concurrency cap for the bulk-scan pool. Default 10.',\n '10',\n )\n .option('--no-fingerprint-skip', 'Force a full scan even when fingerprints are unchanged.')\n .action(async (opts) => {\n const profile = await getProfile(String(opts.connection));\n const conn = createConnection(profile);\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: profile.name,\n });\n\n console.log(`Connecting to ${profile.auth.host}…`);\n await conn.connect();\n try {\n const cats = await resolveCatalogs(conn, opts);\n if (cats.length === 0) {\n console.warn('No catalogs to scan. Pass --catalogs or --include-builtins.');\n return;\n }\n console.log(\n `Scanning ${cats.length} catalog(s) with concurrency ${Number(opts.concurrency)}.`,\n );\n\n const cached = await cache.get();\n const cachedByCat = new Map(cached.catalogs.map((c) => [c.catalog, c] as const));\n\n const concurrency = Math.max(1, Number(opts.concurrency) || 10);\n const fingerprintSkip = opts.fingerprintSkip !== false;\n\n const { results, errors } = await catalog.mapPool(\n cats,\n async (cat) => {\n let freshFingerprint: number | null = null;\n try {\n const fpRes = await conn.query<{ MAX_LAST_ALTERED: unknown }>(\n catalog.fingerprintSqlForCatalog(cat),\n );\n freshFingerprint = catalog.parseFingerprintRow(fpRes.rows);\n } catch (err) {\n console.warn(\n `fingerprint(${cat}) failed; falling through to full scan: ${(err as Error).message}`,\n );\n }\n\n const cachedCat = cachedByCat.get(cat);\n if (\n fingerprintSkip &&\n cachedCat &&\n cachedCat.fingerprint != null &&\n freshFingerprint != null &&\n catalog.isFresh(cachedCat.fingerprint, freshFingerprint)\n ) {\n console.log(` ${cat}: fresh; reusing cache`);\n return {\n catalog: cat,\n fingerprint: cachedCat.fingerprint,\n schemas: cachedCat.schemas,\n };\n }\n\n const scanRes = await conn.query(catalog.bulkScanSqlForCatalog(cat));\n const schemas = catalog.parseBulkScanRows(cat, scanRes.rows);\n const fingerprint = freshFingerprint ?? null;\n console.log(\n ` ${cat}: ${schemas.length} schemas / ${schemas.reduce((sum, s) => sum + s.objects.length, 0)} objects`,\n );\n return { catalog: cat, fingerprint, schemas };\n },\n { concurrency },\n );\n\n for (const e of errors) {\n console.warn(`scan failed for \"${cats[e.index]}\": ${(e.error as Error).message}`);\n }\n\n const snapshot = catalog.refreshFingerprints({\n version: catalog.CATALOG_SNAPSHOT_VERSION,\n connection: profile.name,\n snapshotAt: new Date().toISOString(),\n fingerprint: null,\n catalogs: results.filter((r): r is NonNullable<typeof r> => !!r),\n });\n await cache.set(snapshot);\n\n console.log(`Wrote ${snapshot.catalogs.length} catalogs to ${cache.path}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n cmd\n .command('show')\n .description('Pretty-print or JSON-dump the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .option('--json', 'Emit JSON instead of summary.')\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n const snapshot = await cache.get();\n if (opts.json) {\n console.log(JSON.stringify(snapshot, null, 2));\n return;\n }\n if (snapshot.catalogs.length === 0) {\n console.warn(`Catalog cache is empty for \"${opts.connection}\".`);\n console.warn(` Cache file: ${cache.path}`);\n console.warn(` Run \\`ddt catalog refresh --connection ${opts.connection}\\` to populate.`);\n return;\n }\n console.log(`Snapshot for \"${snapshot.connection}\" — ${snapshot.snapshotAt}`);\n console.log(\n ` Top-level fingerprint: ${snapshot.fingerprint != null ? new Date(snapshot.fingerprint).toISOString() : '(none)'}`,\n );\n for (const cat of snapshot.catalogs) {\n const objCount = cat.schemas.reduce((sum, s) => sum + s.objects.length, 0);\n console.log(\n ` ${cat.catalog.padEnd(32)} ${cat.schemas.length} schemas / ${objCount} objects`,\n );\n }\n });\n\n cmd\n .command('clear')\n .description('Delete the cached snapshot for a connection.')\n .requiredOption('-c, --connection <name>', 'Connection profile name.')\n .option('--root <path>', 'Project root. Default cwd.', process.cwd())\n .action(async (opts) => {\n const cache = new catalog.CatalogCache({\n root: String(opts.root),\n connection: String(opts.connection),\n });\n await cache.clear();\n console.log(`Cleared cache for \"${opts.connection}\".`);\n console.log(` was: ${cache.path}`);\n });\n\n return cmd;\n}\n\nasync function resolveCatalogs(\n conn: DatabricksConnection,\n opts: { catalogs?: unknown; includeBuiltins?: unknown },\n): Promise<string[]> {\n if (opts.catalogs) {\n return String(opts.catalogs)\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n const res = await conn.query<ShowCatalogsRow>('SHOW CATALOGS');\n const names = res.rows\n .map((r) => String(r.catalog ?? r.catalog_name ?? r.CATALOG ?? r.CATALOG_NAME ?? ''))\n .filter(Boolean);\n if (opts.includeBuiltins) return names;\n return names.filter((n) => !BUILTIN_CATALOGS.has(n.toLowerCase()));\n}\n","/**\n * `ddt exec <file.sql> --profiles <list>` — AUTH.3.\n *\n * Runs a SQL / DeltaSQL script on one or more connection profiles in\n * parallel and prints a merged report. Guarded against any profile\n * whose name matches \"prod\" or \"production\" (case-insensitive) unless\n * `--yes` is passed.\n *\n * Mirrors `Snowflake/packages/cli/src/commands/exec.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport { getProfile, createConnection } from '@ddt-tools/core/connection';\nimport { queryExecution } from '@ddt-tools/core';\n\nexport interface ExecResult {\n profile: string;\n status: 'success' | 'error';\n rowsAffected?: number;\n durationMs: number;\n error?: string;\n}\n\nexport type ExecFn = (\n profile: string,\n sql: string,\n timeoutMs: number,\n) => Promise<Omit<ExecResult, 'profile' | 'durationMs'>>;\n\nconst PROD_PATTERN = /\\bprod(uction)?\\b/i;\n\nfunction isProductionProfile(name: string): boolean {\n return PROD_PATTERN.test(name);\n}\n\nasync function runOnProfile(\n execFn: ExecFn,\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<ExecResult> {\n const start = Date.now();\n try {\n const res = await execFn(profile, sql, timeoutMs);\n return { ...res, profile, durationMs: Date.now() - start };\n } catch (err) {\n return {\n profile,\n status: 'error',\n durationMs: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction renderText(results: ExecResult[]): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.status === 'success') {\n const rows = r.rowsAffected !== undefined ? ` (${r.rowsAffected} rows)` : '';\n lines.push(` ${r.profile}: ✓${rows} — ${(r.durationMs / 1000).toFixed(1)}s`);\n } else {\n lines.push(` ${r.profile}: ✗ ${r.error ?? 'unknown error'}`);\n }\n }\n const total = results.length;\n const succeeded = results.filter((r) => r.status === 'success').length;\n lines.push(`\\n${succeeded}/${total} profiles succeeded.`);\n return lines.join('\\n');\n}\n\n/**\n * Wire to the real Databricks connection layer:\n * 1. Resolve the named profile (`~/.ddt/profiles.json`).\n * 2. Open a connection (PAT bearer or OAuth, per profile.auth).\n * 3. Split the SQL via the shared `queryExecution.splitStatements`\n * (Databricks dialect: backtick identifiers, no dollar-quotes)\n * and run each statement sequentially through\n * `DatabricksConnection.query`. We do NOT `failFast` so a script\n * with N statements surfaces every error.\n * 4. Aggregate: success iff every statement succeeded; the first\n * error's message becomes the profile-level error. Total\n * `rowsAffected` is the sum of rowCount across statements.\n *\n * Injectable for tests via the `execFn` parameter on `execCommand`.\n */\nasync function defaultExecFn(\n profile: string,\n sql: string,\n timeoutMs: number,\n): Promise<Omit<ExecResult, 'profile' | 'durationMs'>> {\n const profileObj = await getProfile(profile);\n const conn = createConnection(profileObj);\n await conn.connect();\n try {\n const timeoutSeconds = Math.max(1, Math.ceil(timeoutMs / 1000));\n const runner: queryExecution.QueryRunner = {\n executeStatement: async (statement: string) => {\n const result = await conn.query(statement, { timeoutSeconds });\n return {\n rows: result.rows as Record<string, unknown>[],\n durationMs: result.durationMs,\n };\n },\n };\n const result = await queryExecution.executeStatements(sql, runner, {\n failFast: false,\n splitOptions: { dialect: 'databricks' },\n toolName: 'ddt',\n });\n const firstError = result.statements.find((s) => s.error);\n if (firstError && firstError.error) {\n throw new Error(firstError.error.message);\n }\n const rowsAffected = result.statements.reduce((acc, s) => acc + (s.rowCount ?? 0), 0);\n return { status: 'success', rowsAffected };\n } finally {\n await conn.disconnect().catch(() => {\n /* best-effort cleanup */\n });\n }\n}\n\nexport function execCommand(execFn: ExecFn = defaultExecFn): Command {\n const cmd = new Command('exec');\n cmd\n .description('Run a SQL script on one or more connection profiles in parallel.')\n .argument('<file>', 'Path to the .sql file to execute.')\n .requiredOption('--profiles <list>', 'Comma-separated connection profile names.')\n .option('--yes', 'Confirm execution against production profiles without prompting.')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--timeout <ms>', 'Per-profile timeout in milliseconds.', '30000')\n .action(async (file: string, opts) => {\n const profiles = (opts.profiles as string)\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n if (profiles.length === 0) throw new Error('--profiles must list at least one profile.');\n\n const prodProfiles = profiles.filter(isProductionProfile);\n if (prodProfiles.length > 0 && !opts.yes) {\n throw new Error(\n `Profile(s) look like production: ${prodProfiles.join(', ')}. ` +\n `Pass --yes to confirm.`,\n );\n }\n\n let sql: string;\n try {\n sql = await fs.readFile(file, 'utf8');\n } catch {\n throw new Error(`Cannot read file: ${file}`);\n }\n if (!sql.trim()) throw new Error(`File is empty: ${file}`);\n\n const timeoutMs = parseInt(String(opts.timeout ?? '30000'), 10);\n const results = await Promise.all(\n profiles.map((p) => runOnProfile(execFn, p, sql, timeoutMs)),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n const failed = results.filter((r) => r.status === 'error').length;\n process.stdout.write(\n JSON.stringify(\n {\n results,\n summary: {\n total: results.length,\n succeeded: results.length - failed,\n failed,\n },\n },\n null,\n 2,\n ) + '\\n',\n );\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n process.stdout.write(renderText(results) + '\\n');\n });\n return cmd;\n}\n","/**\n * `ddt search <pattern> --profiles <list|all>` — AUTH.4.\n *\n * Finds objects whose name matches a pattern across one or more connection\n * profiles. Surfaces presence/absence drift: if an object exists in some\n * profiles but not others, those profiles are flagged.\n *\n * The search is case-insensitive substring match by default; --exact\n * switches to exact name match; --type filters by objectType.\n *\n * Mirrors `Snowflake/packages/cli/src/commands/search.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { catalog } from '@ddt-tools/core';\n\nexport interface SearchMatch {\n profile: string;\n fqn: string;\n objectType: string;\n}\n\nexport interface SearchResult {\n profile: string;\n matches: SearchMatch[];\n error?: string;\n}\n\nexport interface SearchFnOptions {\n exact: boolean;\n objectType?: string;\n /** Project / cache root. Defaults to `process.cwd()`. */\n root?: string;\n}\n\nexport type SearchFn = (\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n) => Promise<SearchMatch[]>;\n\nfunction buildDriftReport(results: SearchResult[]): string {\n const allFqns = new Set<string>();\n const byFqn = new Map<string, Set<string>>();\n for (const r of results) {\n if (r.error) continue;\n for (const m of r.matches) {\n allFqns.add(m.fqn);\n if (!byFqn.has(m.fqn)) byFqn.set(m.fqn, new Set());\n byFqn.get(m.fqn)!.add(r.profile);\n }\n }\n const successProfiles = results.filter((r) => !r.error).map((r) => r.profile);\n const driftLines: string[] = [];\n for (const fqn of allFqns) {\n const present = byFqn.get(fqn)!;\n if (present.size < successProfiles.length) {\n const absent = successProfiles.filter((p) => !present.has(p));\n driftLines.push(\n ` DRIFT ${fqn} [present: ${[...present].join(', ')} absent: ${absent.join(', ')}]`,\n );\n }\n }\n return driftLines.join('\\n');\n}\n\nfunction renderText(results: SearchResult[], showDrift: boolean): string {\n const lines: string[] = [];\n for (const r of results) {\n if (r.error) {\n lines.push(`[${r.profile}] ERROR: ${r.error}`);\n continue;\n }\n if (r.matches.length === 0) {\n lines.push(`[${r.profile}] no matches`);\n } else {\n for (const m of r.matches) {\n lines.push(`[${r.profile}] ${m.fqn} (${m.objectType})`);\n }\n }\n }\n if (showDrift) {\n const drift = buildDriftReport(results);\n if (drift) {\n lines.push('');\n lines.push('--- Drift detected ---');\n lines.push(drift);\n }\n }\n return lines.join('\\n');\n}\n\nasync function loadProfileNames(profilesOpt: string, profilesDir: string): Promise<string[]> {\n if (profilesOpt.toLowerCase() !== 'all') {\n return profilesOpt\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n }\n try {\n const entries = await fs.readdir(profilesDir);\n return entries\n .filter((e) => e.endsWith('.json') || e.endsWith('.toml'))\n .map((e) => path.basename(e, path.extname(e)));\n } catch {\n return [];\n }\n}\n\n/**\n * Wire to the on-disk catalog cache (`<root>/.ddt/cache/<profile>/catalog.msgpack`\n * written by `ddt catalog refresh` / `ddt extract --write-catalog-cache`).\n *\n * 1. Open `catalog.CatalogCache({root, connection: profile})`.\n * 2. Read the snapshot — `get()` returns an empty snapshot when the\n * file is absent / corrupt / version-mismatched.\n * 3. If the snapshot is empty, surface an actionable error naming\n * the expected file path and the two commands that populate it.\n * 4. Walk every (catalog, schema, object), filter by `--type`, then\n * match the name (case-insensitive substring by default, exact\n * when `--exact` is set), and return `SearchMatch[]` with the\n * fully-qualified `catalog.schema.name`.\n *\n * Injectable for tests via the `searchFn` parameter on `searchCommand`.\n */\nasync function defaultSearchFn(\n profile: string,\n pattern: string,\n opts: SearchFnOptions,\n): Promise<SearchMatch[]> {\n const root = opts.root ?? process.cwd();\n const cache = new catalog.CatalogCache({ root, connection: profile });\n const snapshot = await cache.get();\n if (snapshot.catalogs.length === 0) {\n throw new Error(\n `No catalog cache for profile \"${profile}\" at ${cache.path}. ` +\n `Run \\`ddt catalog refresh --connection ${profile} --root ${root}\\` ` +\n `or \\`ddt extract --connection ${profile} --output ${root} --write-catalog-cache\\` first.`,\n );\n }\n const needle = pattern.toLowerCase();\n const typeFilter = opts.objectType ? opts.objectType.toUpperCase() : undefined;\n const matches: SearchMatch[] = [];\n for (const cat of snapshot.catalogs) {\n for (const schema of cat.schemas) {\n for (const obj of schema.objects) {\n if (typeFilter && obj.objectType !== typeFilter) continue;\n const name = obj.name.toLowerCase();\n const hit = opts.exact ? name === needle : name.includes(needle);\n if (hit) {\n matches.push({\n profile,\n fqn: `${obj.catalog}.${obj.schema}.${obj.name}`,\n objectType: obj.objectType,\n });\n }\n }\n }\n }\n return matches;\n}\n\nexport function searchCommand(searchFn: SearchFn = defaultSearchFn): Command {\n const cmd = new Command('search');\n cmd\n .description('Find objects matching a name pattern across one or more connection profiles.')\n .argument('<pattern>', 'Name pattern to search for (case-insensitive substring).')\n .requiredOption(\n '--profiles <list|all>',\n 'Comma-separated profile names, or \"all\" to scan every configured profile.',\n )\n .option('--exact', 'Exact name match instead of substring.', false)\n .option('--type <objectType>', 'Filter results to a specific object type (e.g. TABLE, VIEW).')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option(\n '--profiles-dir <dir>',\n 'Directory to scan when --profiles all is used.',\n path.join(os.homedir(), '.ddt', 'connections'),\n )\n .option(\n '--root <dir>',\n 'Project / cache root containing the .ddt/cache directory. Default: cwd.',\n process.cwd(),\n )\n .option('--no-drift', 'Suppress the drift section in text output.')\n .action(async (pattern: string, opts) => {\n const profiles = await loadProfileNames(opts.profiles as string, opts.profilesDir as string);\n if (profiles.length === 0) {\n throw new Error(\n opts.profiles.toLowerCase() === 'all'\n ? `No profiles found in ${opts.profilesDir}. Run \\`ddt connection add\\` first.`\n : '--profiles must list at least one profile.',\n );\n }\n\n const results: SearchResult[] = await Promise.all(\n profiles.map(async (p) => {\n try {\n const matches = await searchFn(p, pattern, {\n exact: opts.exact as boolean,\n objectType: opts.type as string | undefined,\n root: opts.root as string,\n });\n return { profile: p, matches };\n } catch (err) {\n return {\n profile: p,\n matches: [],\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }),\n );\n\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(results, null, 2) + '\\n');\n return;\n }\n if (fmt !== 'text') throw new Error(`Unknown --format: ${opts.format}. Use text | json.`);\n const text = renderText(results, opts.drift !== false);\n process.stdout.write(text ? text + '\\n' : 'No results.\\n');\n });\n return cmd;\n}\n","/**\n * `ddt query-log` — AUTH.5 local query log CLI.\n *\n * Subcommands:\n * ddt query-log list [--profile <p>] [--limit N] [--format text|json]\n * ddt query-log show <id> [--format text|json|sql]\n * ddt query-log add <sql> --profile <p> [--status success|error] [--store <path>]\n * ddt query-log clear [--profile <p>] [--yes]\n *\n * The log is stored at `~/.ddt/query-log.json` (override with --store).\n * EE3 will call `appendEntry()` on the substrate directly when a query\n * is executed. This CLI surfaces it for ad-hoc review + rerun.\n *\n * Mirrors `Snowflake/packages/cli/src/commands/query-log.ts`.\n */\nimport { Command } from 'commander';\nimport { promises as fs } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { queryLog } from '@ddt-tools/core';\n\nconst DEFAULT_STORE = path.join(os.homedir(), '.ddt', 'query-log.json');\n\nasync function loadStore(storePath: string): Promise<queryLog.QueryLogStore> {\n try {\n const raw = await fs.readFile(storePath, 'utf8');\n return queryLog.QueryLogStore.deserialize(JSON.parse(raw));\n } catch {\n return new queryLog.QueryLogStore();\n }\n}\n\nasync function saveStore(storePath: string, store: queryLog.QueryLogStore): Promise<void> {\n await fs.mkdir(path.dirname(storePath), { recursive: true });\n await fs.writeFile(storePath, JSON.stringify(store.serialize(), null, 2), 'utf8');\n}\n\nexport function queryLogCommand(): Command {\n const cmd = new Command('query-log');\n cmd.description('Browse and manage the local query log from the EE3 query window (AUTH.5).');\n\n cmd\n .command('list')\n .description('List recent query log entries (newest first).')\n .option('--profile <p>', 'Filter to a specific connection profile.')\n .option('--limit <n>', 'Maximum entries to show (default 100).', '100')\n .option('--format <fmt>', 'text | json (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n const store = await loadStore(opts.store as string);\n const entries = store.listEntries({\n profile: opts.profile as string | undefined,\n limit: parseInt(String(opts.limit ?? '100'), 10),\n });\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entries, null, 2) + '\\n');\n return;\n }\n if (entries.length === 0) {\n process.stdout.write('No query log entries.\\n');\n return;\n }\n for (const e of entries) {\n const when = e.executedAt.slice(0, 19).replace('T', ' ');\n const dur = e.durationMs !== undefined ? ` ${e.durationMs}ms` : '';\n const rows = e.rowCount !== undefined ? ` ${e.rowCount} rows` : '';\n const status = e.status === 'error' ? ' ✗' : ' ✓';\n const sql = e.sql.replace(/\\s+/g, ' ').slice(0, 80);\n process.stdout.write(`[${e.id}] ${when} [${e.profile}]${status}${dur}${rows} ${sql}\\n`);\n }\n });\n\n cmd\n .command('show <id>')\n .description('Show a single query log entry by id.')\n .option('--format <fmt>', 'text | json | sql (default text).', 'text')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (id: string, opts) => {\n const store = await loadStore(opts.store as string);\n const entry = store.getEntry(id);\n if (!entry) throw new Error(`No entry with id '${id}'.`);\n const fmt = String(opts.format ?? 'text').toLowerCase();\n if (fmt === 'sql') {\n process.stdout.write(entry.sql + '\\n');\n return;\n }\n if (fmt === 'json') {\n process.stdout.write(JSON.stringify(entry, null, 2) + '\\n');\n return;\n }\n process.stdout.write(`id: ${entry.id}\\n`);\n process.stdout.write(`profile: ${entry.profile}\\n`);\n process.stdout.write(`executed: ${entry.executedAt}\\n`);\n process.stdout.write(`status: ${entry.status}\\n`);\n if (entry.durationMs !== undefined) process.stdout.write(`duration: ${entry.durationMs}ms\\n`);\n if (entry.rowCount !== undefined) process.stdout.write(`rows: ${entry.rowCount}\\n`);\n if (entry.error) process.stdout.write(`error: ${entry.error}\\n`);\n process.stdout.write(`\\n${entry.sql}\\n`);\n });\n\n cmd\n .command('add <sql>')\n .description('Manually append a query to the log (used by EE3 and for testing).')\n .requiredOption('--profile <p>', 'Connection profile the query was run against.')\n .option('--status <s>', 'success | error (default success).', 'success')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (sql: string, opts) => {\n if (opts.status !== 'success' && opts.status !== 'error') {\n throw new Error(`--status must be success or error, got: ${opts.status}`);\n }\n const store = await loadStore(opts.store as string);\n const entry = store.appendEntry({\n profile: opts.profile as string,\n sql,\n executedAt: new Date().toISOString(),\n status: opts.status as 'success' | 'error',\n });\n await saveStore(opts.store as string, store);\n process.stdout.write(`Added entry ${entry.id}.\\n`);\n });\n\n cmd\n .command('clear')\n .description('Remove query log entries.')\n .option('--profile <p>', 'Remove only entries for this profile (omit for all).')\n .option('--yes', 'Skip confirmation prompt.')\n .option('--store <path>', 'Path to the query log JSON file.', DEFAULT_STORE)\n .action(async (opts) => {\n if (!opts.yes) {\n const target = opts.profile ? `profile '${opts.profile as string}'` : 'all profiles';\n throw new Error(`Pass --yes to confirm clearing the query log for ${target}.`);\n }\n const store = await loadStore(opts.store as string);\n const removed = store.clearEntries(opts.profile as string | undefined);\n await saveStore(opts.store as string, store);\n process.stdout.write(`Cleared ${removed} entries.\\n`);\n });\n\n return cmd;\n}\n"],"mappings":"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","names":["import_commander","import_commander","import_core","safetyApi","import_commander","import_core","fs","import_node_fs","import_commander","import_core","fs","import_node_fs","import_commander","import_core","readStdin","fs","import_commander","import_core","import_commander","import_core","import_commander","import_node_fs","import_core","result","fs","import_commander","import_node_fs","import_core","renderText","fs","path","os","import_commander","import_node_fs","import_node_os","import_node_path","import_core","path","os","fs"]}
package/dist/index.js CHANGED
@@ -10,13 +10,19 @@ import {
10
10
  } from "@ddt-tools/core";
11
11
  function connectionCommand() {
12
12
  const cmd = new Command("connection").description("Manage Databricks connection profiles.");
13
- cmd.command("add <name>").description("Store a new connection profile.").option("--host <host>", "Workspace host, e.g. dbc-12345-abcd.cloud.databricks.com").option("--auth <method>", "One of: pat | oauth-m2m | oauth-u2m | azure-ad | google-idc", "pat").option(
13
+ cmd.command("add [name]").description("Store a new connection profile.").option("--name <name>", "Profile name (flag form of the positional name arg)").option("--host <host>", "Workspace host, e.g. dbc-12345-abcd.cloud.databricks.com").option("--auth <method>", "One of: pat | oauth-m2m | oauth-u2m | azure-ad | google-idc", "pat").option(
14
14
  "--token <token>",
15
15
  "PAT token \u2014 use env:DATABRICKS_TOKEN to reference an env var, never inline a secret"
16
16
  ).option("--client-id <id>", "OAuth M2M / Azure AD client ID").option("--client-secret <secret>", "OAuth M2M / Azure AD client secret").option("--tenant-id <id>", "Azure AD tenant ID").option(
17
17
  "--service-account-key-path <path>",
18
18
  "Path to a GCP service-account key JSON file (for google-idc auth)"
19
- ).requiredOption("--warehouse-id <id>", "SQL warehouse ID for DDL operations").option("--catalog <catalog>", "Default Unity Catalog catalog").option("--schema <schema>", "Default schema").action(async (name, opts) => {
19
+ ).requiredOption("--warehouse-id <id>", "SQL warehouse ID for DDL operations").option("--catalog <catalog>", "Default Unity Catalog catalog").option("--schema <schema>", "Default schema").action(async (nameArg, opts) => {
20
+ const name = opts.name ? String(opts.name) : nameArg ?? "";
21
+ if (!name) {
22
+ throw new Error(
23
+ "connection add needs a profile name \u2014 pass it positionally (`ddt connection add <name>`) or via `--name`."
24
+ );
25
+ }
20
26
  if (!opts.host) throw new Error("--host is required");
21
27
  const auth = buildAuth(opts);
22
28
  const profile = {