@ddt-tools/cli 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cli.js +49 -11
- package/dist/cli.js.map +1 -1
- package/dist/{compare-P7JOV76O.js → compare-IOEATL6G.js} +69 -13
- package/dist/compare-IOEATL6G.js.map +1 -0
- package/dist/{errorReporting-3LPE2IJY.js → errorReporting-LX6WT4JH.js} +2 -2
- package/dist/{errorReporting-3LPE2IJY.js.map → errorReporting-LX6WT4JH.js.map} +1 -1
- package/dist/import-EGOVKTLX.js +29 -0
- package/dist/import-EGOVKTLX.js.map +1 -0
- package/dist/{import-2RNYDL4E.js → import-script-R5RXPDH6.js} +5 -5
- package/dist/import-script-R5RXPDH6.js.map +1 -0
- package/dist/{mcp-F7FND5X7.js → mcp-6ZXOAF7S.js} +2 -2
- package/dist/{mcp-F7FND5X7.js.map → mcp-6ZXOAF7S.js.map} +1 -1
- package/dist/{publish-AYCRMCE2.js → publish-HLP3XHM5.js} +35 -8
- package/dist/publish-HLP3XHM5.js.map +1 -0
- package/package.json +13 -13
- package/dist/compare-P7JOV76O.js.map +0 -1
- package/dist/import-2RNYDL4E.js.map +0 -1
- package/dist/publish-AYCRMCE2.js.map +0 -1
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ npm i -g @ddt-tools/cli
|
|
|
13
13
|
ddt --help
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
📺 **See it in action (60s each):** [Schema Compare](https://youtu.be/_p5Z45T2kVM) · [Safe deploy](https://youtu.be/L7wbQI3OzEQ) · [Extract workspace](https://youtu.be/lVclo6wnWfw) · [all demos on YouTube](https://www.youtube.com/channel/UCc3L8L8BBOO9lVLI1V2FFNQ)
|
|
17
|
+
|
|
16
18
|
## What it does
|
|
17
19
|
|
|
18
20
|
You describe the _desired state_ of your Unity Catalog schema as SQL files (`CREATE OR REPLACE`, the Databricks idiom); `ddt` computes the deltas against the live workspace, classifies each change (`SAFE` / `DESTRUCTIVE` / `EXPENSIVE` / `UNRECOVERABLE`), emits a reviewable migration script, and captures a manifest for one-command rollback. DDT understands UC-specific failure modes — streaming-table checkpoint loss, managed-table file deletion — that generic SQL tools miss.
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
logger
|
|
4
|
+
} from "./chunk-VM2H4LAO.js";
|
|
2
5
|
import "./chunk-DGUM43GV.js";
|
|
3
6
|
|
|
4
7
|
// src/cli.ts
|
|
@@ -17,12 +20,12 @@ var COMMAND_MANIFEST = {
|
|
|
17
20
|
},
|
|
18
21
|
compare: {
|
|
19
22
|
term: "compare [options]",
|
|
20
|
-
description: "Compare two
|
|
23
|
+
description: "Compare two schemas (the desired state vs the current state). Each side may be a .ddtproj, a .ddtpac, or databricks://<profile>[/catalog[/schema]]."
|
|
21
24
|
},
|
|
22
25
|
build: { term: "build [options]", description: "Build a .ddtpac from a .ddtproj project." },
|
|
23
26
|
publish: {
|
|
24
27
|
term: "publish [options]",
|
|
25
|
-
description: "Generate (and optionally apply) a migration script from source \u2192 target."
|
|
28
|
+
description: "Generate (and optionally apply) a migration script from source \u2192 target. Shared form with `sdt publish`: `--source <desired> --connection <live-target>` compares the desired state against the live workspace. Or pass `--target <offline>` to diff against a `.ddtproj` / `.ddtpac` instead."
|
|
26
29
|
},
|
|
27
30
|
script: {
|
|
28
31
|
term: "script [options]",
|
|
@@ -30,6 +33,10 @@ var COMMAND_MANIFEST = {
|
|
|
30
33
|
},
|
|
31
34
|
import: {
|
|
32
35
|
term: "import [options]",
|
|
36
|
+
description: "Convert artifacts from other tools into a DDT project."
|
|
37
|
+
},
|
|
38
|
+
"import-script": {
|
|
39
|
+
term: "import-script [options]",
|
|
33
40
|
description: "Parse a SQL script and write each DDL statement into the .ddtproj tree under its canonical folder."
|
|
34
41
|
},
|
|
35
42
|
extract: {
|
|
@@ -368,17 +375,18 @@ function defaultOutputStyle() {
|
|
|
368
375
|
if (env && VALID_OUTPUT_STYLES.has(env)) return env;
|
|
369
376
|
return "standard";
|
|
370
377
|
}
|
|
371
|
-
var CLI_VERSION = "0.2.
|
|
378
|
+
var CLI_VERSION = "0.2.5";
|
|
372
379
|
globalThis.__DDT_START_NS__ ??= process.hrtime.bigint() - BigInt(Math.round(performance.now() * 1e6));
|
|
373
380
|
var COMMAND_LOADERS = {
|
|
374
381
|
connection: async () => (await import("./connection-CDGVEFUC.js")).connectionCommand(),
|
|
375
382
|
init: async () => (await import("./init-EAOGNGXI.js")).initCommand(),
|
|
376
383
|
validate: async () => (await import("./validate-LFDEZFFH.js")).validateCommand(),
|
|
377
|
-
compare: async () => (await import("./compare-
|
|
384
|
+
compare: async () => (await import("./compare-IOEATL6G.js")).compareCommand(),
|
|
378
385
|
build: async () => (await import("./build-MP3JQEFO.js")).buildCommand(),
|
|
379
|
-
publish: async () => (await import("./publish-
|
|
386
|
+
publish: async () => (await import("./publish-HLP3XHM5.js")).publishCommand(),
|
|
380
387
|
script: async () => (await import("./script-BMYVBHFR.js")).scriptCommand(),
|
|
381
|
-
import: async () => (await import("./import-
|
|
388
|
+
import: async () => (await import("./import-EGOVKTLX.js")).importCommand(),
|
|
389
|
+
"import-script": async () => (await import("./import-script-R5RXPDH6.js")).importScriptCommand(),
|
|
382
390
|
extract: async () => (await import("./extract-4LWEZG4O.js")).extractCommand(),
|
|
383
391
|
completion: async () => (await import("./completion-ZSNCQKJ2.js")).completionCommand(),
|
|
384
392
|
drift: async () => (await import("./drift-FDRNPWQA.js")).driftCommand(),
|
|
@@ -410,7 +418,7 @@ var COMMAND_LOADERS = {
|
|
|
410
418
|
suite: async () => (await import("./suite-YTQ3CNX5.js")).suiteCommand(),
|
|
411
419
|
refactor: async () => (await import("./refactor-TC7S43F2.js")).refactorCommand(),
|
|
412
420
|
license: async () => (await import("./license-Z5YSC7XQ.js")).licenseCommand(),
|
|
413
|
-
mcp: async () => (await import("./mcp-
|
|
421
|
+
mcp: async () => (await import("./mcp-6ZXOAF7S.js")).mcpCommand(),
|
|
414
422
|
ai: async () => (await import("./ai-NTNPYEKZ.js")).aiCommand(),
|
|
415
423
|
explain: async () => (await import("./explain-NS26WE2Y.js")).explainCommand(),
|
|
416
424
|
feedback: async () => (await import("./feedback-CBLGXUEG.js")).feedbackCommand(),
|
|
@@ -463,6 +471,26 @@ var COMMAND_LOADERS = {
|
|
|
463
471
|
trial: async () => (await import("./trial-GFTGYCR3.js")).trialCommand(),
|
|
464
472
|
pilot: async () => (await import("./pilot-BR6GVK32.js")).pilotCommand()
|
|
465
473
|
};
|
|
474
|
+
async function tierGateHook(actionCommand) {
|
|
475
|
+
const path = [];
|
|
476
|
+
for (let c = actionCommand; c && c.parent; c = c.parent) {
|
|
477
|
+
path.unshift(c.name());
|
|
478
|
+
}
|
|
479
|
+
const licenseNs = await import("@ddt-tools/core/license");
|
|
480
|
+
const gate = licenseNs.findCommandGate(path);
|
|
481
|
+
if (!gate) return;
|
|
482
|
+
const requiredTier = licenseNs.resolveRequiredTier(gate.requiredTier, actionCommand.opts());
|
|
483
|
+
const access = await licenseNs.resolveAccessForCommand(requiredTier, gate.label);
|
|
484
|
+
if (!access.allowed) {
|
|
485
|
+
logger.error(access.blockedReason ?? `"${gate.label}" requires a ${requiredTier} license.`);
|
|
486
|
+
process.exitCode = 1;
|
|
487
|
+
process.exit(1);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
if (access.trialNotice) {
|
|
491
|
+
console.log(chalk.dim(access.trialNotice));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
466
494
|
async function main() {
|
|
467
495
|
const firstArg = process.argv[2];
|
|
468
496
|
if (firstArg === "--version" || firstArg === "-v") {
|
|
@@ -509,19 +537,28 @@ async function main() {
|
|
|
509
537
|
"",
|
|
510
538
|
"Personalized suggestions:",
|
|
511
539
|
" ddt discover # feature tips based on your usage history",
|
|
540
|
+
"",
|
|
541
|
+
"Watch the 60-second demos:",
|
|
542
|
+
" Schema Compare https://youtu.be/_p5Z45T2kVM",
|
|
543
|
+
" Safe deploy https://youtu.be/L7wbQI3OzEQ",
|
|
544
|
+
" Extract workspace https://youtu.be/lVclo6wnWfw",
|
|
545
|
+
" All demos https://www.youtube.com/channel/UCc3L8L8BBOO9lVLI1V2FFNQ",
|
|
512
546
|
""
|
|
513
547
|
].join("\n")
|
|
514
548
|
);
|
|
515
549
|
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
516
550
|
if (actionCommand.parent !== program) return;
|
|
517
|
-
const reporting = await import("./errorReporting-
|
|
551
|
+
const reporting = await import("./errorReporting-LX6WT4JH.js");
|
|
518
552
|
await reporting.setupErrorReporting(actionCommand.name());
|
|
519
553
|
});
|
|
520
554
|
program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
521
555
|
if (actionCommand.parent !== program) return;
|
|
522
|
-
const reporting = await import("./errorReporting-
|
|
556
|
+
const reporting = await import("./errorReporting-LX6WT4JH.js");
|
|
523
557
|
await reporting.finishErrorReporting(CLI_VERSION);
|
|
524
558
|
});
|
|
559
|
+
program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
560
|
+
await tierGateHook(actionCommand);
|
|
561
|
+
});
|
|
525
562
|
program.hook("postAction", async (_thisCommand, actionCommand) => {
|
|
526
563
|
if (actionCommand.parent !== program) return;
|
|
527
564
|
const { FeatureAdvisor, DDT_HINT_RULES } = await import("@ddt-tools/core/discovery");
|
|
@@ -552,13 +589,14 @@ if (process.env["DDT_CLI_NO_MAIN"] !== "1") {
|
|
|
552
589
|
console.error(err instanceof Error ? err.message : String(err));
|
|
553
590
|
process.exitCode = 1;
|
|
554
591
|
try {
|
|
555
|
-
const reporting = await import("./errorReporting-
|
|
592
|
+
const reporting = await import("./errorReporting-LX6WT4JH.js");
|
|
556
593
|
await reporting.reportCliFailure(err, CLI_VERSION);
|
|
557
594
|
} catch {
|
|
558
595
|
}
|
|
559
596
|
});
|
|
560
597
|
}
|
|
561
598
|
export {
|
|
562
|
-
COMMAND_LOADERS
|
|
599
|
+
COMMAND_LOADERS,
|
|
600
|
+
tierGateHook
|
|
563
601
|
};
|
|
564
602
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commandManifest.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `ddt` — Databricks Data Tools command-line interface.\n *\n * Mirrors the SDT CLI surface: every command name and flag matches so muscle\n * memory carries between Snowflake and Databricks engagements.\n *\n * Subcommand modules are loaded LAZILY: only the requested subcommand's\n * module (and its `@ddt-tools/core` dependency chain) is imported on the common\n * path. `--help` / `--version` / no-arg / unknown-command paths fall back\n * to loading every command so Commander can render the full subcommand\n * list.\n *\n * Cold-start win: `ddt <known-cmd> ...` skips ~80 command-module loads\n * and their per-module `@ddt-tools/core/...` imports. Mirrors the SDT-side\n * pattern; see Snowflake/packages/cli/src/cli.ts.\n */\nimport { Command, Help } from 'commander';\n// RH4.2 — core modules are imported LAZILY (dynamic `import()` at the use\n// site), NOT eagerly at module top. The eager subpath imports of\n// `@ddt-tools/core/{discovery,features,outputStyle}` each statically pulled\n// their whole barrel subtree into the startup chunk, which Node parsed +\n// evaluated on every invocation — including the `--version` / `--help`\n// fast paths that never touch them. Deferring them lets tsup code-split\n// those subtrees out of the eager chunk so cold start pays only Node\n// bootstrap + commander + the requested command. `import type` is free\n// (erased at compile), so types stay top-level. The barrel (`@ddt-tools/core`)\n// is still never imported — subpath / dynamic only (RH3.3 pin).\nimport type { OutputStyle } from '@ddt-tools/core/outputStyle';\nimport { COMMAND_MANIFEST } from './commandManifest.js';\nimport chalk from 'chalk';\n\nconst VALID_OUTPUT_STYLES = new Set<OutputStyle>(['standard', 'audit', 'ci', 'review', 'terse']);\n\n/**\n * Resolve the default `--style` value without eagerly loading the\n * `@ddt-tools/core/outputStyle` module on the cold-start path. Mirrors\n * `resolveOutputStyle()` exactly (env var → default 'standard'); the flag\n * value is not yet known here (commander resolves it after parse), so this\n * only folds in `DDT_OUTPUT_STYLE`. Kept in lockstep with\n * core/outputStyle/style.ts `resolveOutputStyle`.\n */\nfunction defaultOutputStyle(): OutputStyle {\n const env = process.env['DDT_OUTPUT_STYLE'];\n if (env && VALID_OUTPUT_STYLES.has(env as OutputStyle)) return env as OutputStyle;\n return 'standard';\n}\n\nconst CLI_VERSION = '0.2.4';\n\n// Cold-start timestamp for `ddt perf cold-start`. ESM hoists imports above\n// this line, so a plain `process.hrtime.bigint()` here would EXCLUDE the\n// import cost from the measurement. Back-date the stamp to true process\n// start (`performance.now()` counts from process timeOrigin) so the\n// reported number covers Node bootstrap + ESM imports + command dispatch.\n// `??=` preserves a value pre-set by any earlier bootstrap wrapper.\n(globalThis as { __DDT_START_NS__?: bigint }).__DDT_START_NS__ ??=\n process.hrtime.bigint() - BigInt(Math.round(performance.now() * 1e6));\n\n// Mapping of CLI subcommand-name → lazy loader. Each loader resolves to\n// the Commander `Command` instance for that subcommand. When you add a\n// new top-level `ddt <name>` command, add its entry here. Aliases (`erd`)\n// can re-use the same module export with a different factory name.\nexport const COMMAND_LOADERS: Record<string, () => Promise<Command>> = {\n connection: async () => (await import('./commands/connection.js')).connectionCommand(),\n init: async () => (await import('./commands/init.js')).initCommand(),\n validate: async () => (await import('./commands/validate.js')).validateCommand(),\n compare: async () => (await import('./commands/compare.js')).compareCommand(),\n build: async () => (await import('./commands/build.js')).buildCommand(),\n publish: async () => (await import('./commands/publish.js')).publishCommand(),\n script: async () => (await import('./commands/script.js')).scriptCommand(),\n import: async () => (await import('./commands/import.js')).importCommand(),\n extract: async () => (await import('./commands/extract.js')).extractCommand(),\n completion: async () => (await import('./commands/completion.js')).completionCommand(),\n drift: async () => (await import('./commands/drift.js')).driftCommand(),\n format: async () => (await import('./commands/format.js')).formatCommand(),\n lint: async () => (await import('./commands/lint.js')).lintCommand(),\n docs: async () => (await import('./commands/docs.js')).docsCommand(),\n erd: async () => (await import('./commands/docs.js')).erdCommand(),\n verify: async () => (await import('./commands/verify.js')).verifyCommand(),\n revert: async () => (await import('./commands/revert.js')).revertCommand(),\n snapshot: async () => (await import('./commands/snapshot.js')).snapshotCommand(),\n graph: async () => (await import('./commands/graph.js')).graphCommand(),\n lineage: async () => (await import('./commands/lineage.js')).lineageCommand(),\n diagnose: async () => (await import('./commands/diagnose.js')).diagnoseCommand(),\n review: async () => (await import('./commands/review.js')).reviewCommand(),\n impact: async () => (await import('./commands/impact.js')).impactCommand(),\n 'cost-estimate': async () => (await import('./commands/cost-estimate.js')).costEstimateCommand(),\n 'pr-comment': async () => (await import('./commands/pr-comment.js')).prCommentCommand(),\n template: async () => (await import('./commands/template.js')).templateCommand(),\n anonymize: async () => (await import('./commands/anonymize.js')).anonymizeCommand(),\n test: async () => (await import('./commands/test.js')).testCommand(),\n branch: async () => (await import('./commands/branch.js')).branchCommand(),\n schema: async () => (await import('./commands/schema.js')).schemaCommand(),\n suggest: async () => (await import('./commands/suggest.js')).suggestCommand(),\n history: async () => (await import('./commands/history.js')).historyCommand(),\n 'audit-log': async () => (await import('./commands/audit-log.js')).auditLogCommand(),\n 'install-hooks': async () => (await import('./commands/install-hooks.js')).installHooksCommand(),\n telemetry: async () => (await import('./commands/telemetry.js')).telemetryCommand(),\n seed: async () => (await import('./commands/seed.js')).seedCommand(),\n suite: async () => (await import('./commands/suite.js')).suiteCommand(),\n refactor: async () => (await import('./commands/refactor.js')).refactorCommand(),\n license: async () => (await import('./commands/license.js')).licenseCommand(),\n mcp: async () => (await import('./commands/mcp.js')).mcpCommand(),\n ai: async () => (await import('./commands/ai.js')).aiCommand(),\n explain: async () => (await import('./commands/explain.js')).explainCommand(),\n feedback: async () => (await import('./commands/feedback.js')).feedbackCommand(),\n features: async () => (await import('./commands/features.js')).featuresCommand(),\n hosts: async () => (await import('./commands/hosts.js')).hostsCommand(),\n safety: async () => (await import('./commands/safety.js')).safetyCommand(),\n pii: async () => (await import('./commands/pii.js')).piiCommand(),\n bisect: async () => (await import('./commands/bisect.js')).bisectCommand(),\n changelog: async () => (await import('./commands/changelog.js')).changelogCommand(),\n replay: async () => (await import('./commands/replay.js')).replayCommand(),\n 'drift-gate': async () => (await import('./commands/drift-gate.js')).driftGateCommand(),\n promote: async () => (await import('./commands/promote.js')).promoteCommand(),\n 'data-fit': async () => (await import('./commands/data-fit.js')).dataFitCommand(),\n 'data-compare': async () => (await import('./commands/data-compare.js')).dataCompareCommand(),\n approval: async () => (await import('./commands/approval.js')).approvalCommand(),\n 'advise-tests': async () => (await import('./commands/advise-tests.js')).adviseTestsCommand(),\n 'safer-alternative': async () =>\n (await import('./commands/safer-alternative.js')).saferAlternativeCommand(),\n sketch: async () => (await import('./commands/sketch.js')).sketchCommand(),\n design: async () => (await import('./commands/design.js')).designCommand(),\n optimize: async () => (await import('./commands/optimize.js')).optimizeCommand(),\n 'rollback-suggest': async () =>\n (await import('./commands/rollback-suggest.js')).rollbackSuggestCommand(),\n 'compare-profiles': async () =>\n (await import('./commands/compare-profiles.js')).compareProfilesCommand(),\n explorer: async () => (await import('./commands/explorer.js')).explorerCommand(),\n catalog: async () => (await import('./commands/catalog.js')).catalogCommand(),\n 'xcompare-ir': async () => (await import('./commands/xcompare.js')).xcompareCommand(),\n profile: async () => (await import('./commands/profile.js')).profileCommand(),\n 'suggest-constraints': async () =>\n (await import('./commands/suggest-constraints.js')).suggestConstraintsCommand(),\n purge: async () => (await import('./commands/purge.js')).purgeCommand(),\n preview: async () => (await import('./commands/preview.js')).previewCommand(),\n refresh: async () => (await import('./commands/refresh.js')).refreshCommand(),\n discover: async () => (await import('./commands/discover.js')).discoverCommand(),\n find: async () => (await import('./commands/find.js')).findCommand(),\n 'scan-secrets': async () => (await import('./commands/scan-secrets.js')).scanSecretsCommand(),\n 'error-lookup': async () => (await import('./commands/error-lookup.js')).errorLookupCommand(),\n 'deploy-status': async () => (await import('./commands/deploy-status.js')).deployStatusCommand(),\n 'approval-chain': async () =>\n (await import('./commands/approval-chain.js')).approvalChainCommand(),\n standards: async () => (await import('./commands/standards.js')).standardsCommand(),\n perf: async () => (await import('./commands/perf.js')).perfCommand(),\n 'migrate-platform': async () =>\n (await import('./commands/migrate-platform.js')).migratePlatformCommand(),\n migrate: async () => (await import('./commands/migrate-from-dbt.js')).migrateFromDbtCommand(),\n backlog: async () => (await import('./commands/backlog.js')).backlogCommand(),\n watch: async () => (await import('./commands/watch.js')).watchCommand(),\n bookmarks: async () => (await import('./commands/bookmarks.js')).bookmarksCommand(),\n snippets: async () => (await import('./commands/snippets.js')).snippetsCommand(),\n generate: async () => (await import('./commands/generate.js')).generateCommand(),\n exec: async () => (await import('./commands/exec.js')).execCommand(),\n search: async () => (await import('./commands/search.js')).searchCommand(),\n 'query-log': async () => (await import('./commands/query-log.js')).queryLogCommand(),\n savings: async () => (await import('./commands/savings.js')).savingsCommand(),\n trial: async () => (await import('./commands/trial.js')).trialCommand(),\n pilot: async () => (await import('./commands/pilot.js')).pilotCommand(),\n};\n\nasync function main(): Promise<void> {\n // RH4.2 cold-start fast path: `ddt -v` / `ddt --version` is the canonical\n // cold-start benchmark and must not load any command chunk. With code\n // splitting (tsup `splitting: true`) the no-arg / `--help` / `--version`\n // path otherwise loads ALL ~85 command chunks (separate files) so\n // commander can render the full subcommand list — dozens of disk reads\n // that dominate wall-clock on Windows. `--version` only needs the\n // version string, so short-circuit before building the program. Mirrors\n // commander's own `--version` output (bare version line) exactly.\n const firstArg = process.argv[2];\n if (firstArg === '--version' || firstArg === '-v') {\n process.stdout.write(CLI_VERSION + '\\n');\n return;\n }\n\n const program = new Command();\n program\n .name('ddt')\n .description(\n 'Databricks Data Tools — declarative schema management for Databricks Unity Catalog.',\n )\n .version(CLI_VERSION, '-v, --version')\n .option(\n '--style <mode>',\n 'Output style: standard | audit | ci | review | terse. Also reads DDT_OUTPUT_STYLE env var.',\n defaultOutputStyle(),\n )\n .option('--explain-features', 'After each command, show related features from the catalog.');\n\n const arg2 = process.argv[2];\n const explicitLoader = arg2 && !arg2.startsWith('-') ? COMMAND_LOADERS[arg2] : undefined;\n\n if (explicitLoader) {\n program.addCommand(await explicitLoader());\n } else {\n // RH4.7 — help / no-arg / unknown-command path. Register STUB\n // subcommands (name + description) from the static manifest instead of\n // loading all ~85 command modules. Commander renders the subcommand\n // list + the standard \"unknown command\" error from these stubs with\n // zero command-module imports. The stub carries no options/arguments,\n // so its rendered term would be just the bare name; override\n // `subcommandTerm` to emit the manifest's exact term (e.g.\n // `template [options] <kind> <name>`) so the --help columns are\n // byte-identical to the load-everything path. Per-command help\n // (`ddt <cmd> --help`) still loads the real module via the\n // explicit-loader path above, so argument/option detail is unaffected.\n for (const [name, entry] of Object.entries(COMMAND_MANIFEST)) {\n program.command(name).description(entry.description);\n }\n const defaultHelp = new Help();\n program.configureHelp({\n // Manifest commands render their exact term; the implicit `help`\n // subcommand (and anything else not in the manifest) falls back to\n // commander's own term so `help [command]` stays intact.\n subcommandTerm: (cmd) =>\n COMMAND_MANIFEST[cmd.name()]?.term ?? defaultHelp.subcommandTerm(cmd),\n });\n }\n\n // Global help footer — surfaces the searchable options catalog\n // (`ddt explain <query>`) on every command's --help screen. Free-tier\n // discoverability hook: users land in --help, see the hint, learn\n // they can ask `ddt explain allowDropTable` for safety + path detail\n // without leaving the terminal. Mirrors the SDT-side footer.\n program.addHelpText('afterAll', () =>\n [\n '',\n 'Options catalog:',\n ' Every CLI flag and `.ddtproj` option has a searchable entry with safety',\n ' tier, default, related options, and an example. Look one up with:',\n ' ddt explain <name> # e.g. ddt explain allowDropTable',\n ' ddt explain <topic> # fuzzy: \"drop\", \"safety\", \"compare\"',\n '',\n 'Features catalog (locked + unlocked):',\n ' ddt features list # what ships in each tier',\n ' ddt features show <id>',\n '',\n 'Personalized suggestions:',\n ' ddt discover # feature tips based on your usage history',\n '',\n ].join('\\n'),\n );\n\n // ERR.2 — error-reporting lifecycle. Lazily imported so the cold-start\n // path pays nothing; the preAction hook handles first-run consent +\n // crash-hook install, the postAction hook drains the spool when consent\n // is on. Both no-op fast for exempt commands (telemetry, feedback, help).\n program.hook('preAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.parent !== program) return;\n const reporting = await import('./util/errorReporting.js');\n await reporting.setupErrorReporting(actionCommand.name());\n });\n program.hook('postAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.parent !== program) return;\n const reporting = await import('./util/errorReporting.js');\n await reporting.finishErrorReporting(CLI_VERSION);\n });\n\n // Feature Discovery: fire a single contextual hint after each top-level\n // command succeeds. One line, dim, easy to ignore. Disabled with DDT_NO_HINTS=1.\n // RH4.2 — the FeatureAdvisor + hint rules and the features catalog are\n // imported LAZILY inside the hook so the cold-start path (which never\n // runs an action hook for `--version` / `--help`) pays nothing for them.\n program.hook('postAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.parent !== program) return;\n const { FeatureAdvisor, DDT_HINT_RULES } = await import('@ddt-tools/core/discovery');\n const ddtAdvisor = new FeatureAdvisor('ddt', DDT_HINT_RULES);\n const tip = ddtAdvisor.advise(actionCommand.name());\n if (tip) {\n console.log(chalk.dim(`\\n ✦ ${tip}`));\n console.log(chalk.dim(' ddt discover · ddt features list'));\n }\n // DSC.6 — explain-features: when the global flag is set, show related\n // features from the catalog for the command that just ran.\n if ((program.opts() as { explainFeatures?: boolean }).explainFeatures) {\n const cmdName = actionCommand.name();\n const featuresNs = await import('@ddt-tools/core/features');\n const related = featuresNs.pickRelatedFeatures(\n featuresNs.DDT_FEATURE_CATALOG,\n cmdName,\n 3,\n 'ddt',\n );\n const hint = featuresNs.renderRelatedFeaturesHint(related, cmdName, 'ddt');\n if (hint) console.log(chalk.dim('\\n' + hint));\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\n// Only auto-run when invoked as the CLI entry point, not when imported by\n// a test harness (the COMMAND_LOADERS / COMMAND_MANIFEST anti-drift test\n// imports this module to introspect the registry without dispatching).\nif (process.env['DDT_CLI_NO_MAIN'] !== '1') {\n main().catch(async (err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n // ERR.2 — capture the failure and (with consent) report it; without\n // consent, offer a one-keystroke manual report. Never throws.\n try {\n const reporting = await import('./util/errorReporting.js');\n await reporting.reportCliFailure(err, CLI_VERSION);\n } catch {\n // Error reporting must never mask the original failure.\n }\n });\n}\n","/**\n * Static command manifest — subcommand name → { term, description }.\n *\n * RH4.7: the `--help` / no-arg / unknown-command paths render the full\n * subcommand list. Building that list by loading every entry in\n * `COMMAND_LOADERS` forces ~85 lazy command chunks (and their\n * `@ddt-tools/core/...` dependency chains) off disk on a path that never\n * executes a command — the dominant cost of `ddt --help` cold start.\n *\n * Instead, the help/error paths register STUB subcommands from this\n * manifest and render the subcommand list from it, so Commander produces a\n * byte-identical subcommand list + usage error without importing a single\n * command module. The real module is loaded only when a known command is\n * actually dispatched (see `cli.ts`).\n *\n * - `term` — the exact left-column term Commander renders for the\n * command in the parent --help list (name + ` [options]`\n * when the command registers any option + the\n * human-readable positional-argument signature). Used to\n * override `subcommandTerm` so the help columns line up\n * identically to the load-everything path.\n * - `description` — the one-line string the command module passes to\n * commander's `.description(...)`.\n *\n * `commandManifest.test.ts` dynamically loads every `COMMAND_LOADERS` entry\n * and asserts both `term` and `description` match what the real module\n * registers, plus that the key set + order are identical — so any drift (a\n * changed description, a new/removed option or argument, a new command\n * without a manifest row, a stale row) fails the test rather than silently\n * rotting the help text.\n *\n * Key order is kept aligned with `COMMAND_LOADERS` in `cli.ts` so the\n * rendered `--help` subcommand ordering is unchanged. Mirrors the\n * Snowflake-side manifest.\n */\nexport interface CommandManifestEntry {\n /** Exact Commander subcommand term for the parent --help list. */\n readonly term: string;\n /** One-line description (must equal the module's `.description(...)`). */\n readonly description: string;\n}\n\nexport const COMMAND_MANIFEST: Record<string, CommandManifestEntry> = {\n connection: { term: 'connection', description: 'Manage Databricks connection profiles.' },\n init: {\n term: 'init [options]',\n description: 'Initialize a new DDT project in the current directory.',\n },\n validate: {\n term: 'validate [options]',\n description:\n 'Validate a .ddtproj — schema check; optionally resolve every object reference (--references).',\n },\n compare: {\n term: 'compare [options]',\n description: 'Compare two .ddtpac files (pac↔pac); project / live compare pending v0.3 polish.',\n },\n build: { term: 'build [options]', description: 'Build a .ddtpac from a .ddtproj project.' },\n publish: {\n term: 'publish [options]',\n description: 'Generate (and optionally apply) a migration script from source → target.',\n },\n script: {\n term: 'script [options]',\n description:\n 'Generate a deploy SQL script for source → target. Always offline — does not touch the workspace.',\n },\n import: {\n term: 'import [options]',\n description:\n 'Parse a SQL script and write each DDL statement into the .ddtproj tree under its canonical folder.',\n },\n extract: {\n term: 'extract [options]',\n description:\n 'Extract live UC objects from a workspace into a project tree (--output) or a .ddtpac (--out-pac).',\n },\n completion: {\n term: 'completion <shell>',\n description: 'Emit a shell completion script (bash | zsh | fish | powershell).',\n },\n drift: {\n term: 'drift [options]',\n description:\n 'Refuse with non-zero exit when the live target has drifted from --source or a dbt manifest.',\n },\n format: {\n term: 'format [options]',\n description:\n 'Format every .sql under a .ddtproj — uppercase reserved keywords + tidy whitespace.',\n },\n lint: {\n term: 'lint [options]',\n description:\n 'Lint a SQL script for risky deploy patterns. Exits non-zero on any ERROR-severity finding.',\n },\n docs: {\n term: 'docs [options]',\n description: 'Generate HTML schema docs from a .ddtproj or .ddtpac.',\n },\n erd: {\n term: 'erd [options]',\n description:\n 'Generate an ER diagram (Mermaid Markdown or interactive 3D HTML) from a .ddtproj or .ddtpac.',\n },\n verify: {\n term: 'verify [options]',\n description: 'Recompute checksums on a .ddtpac and confirm every object matches the manifest.',\n },\n revert: {\n term: 'revert [options]',\n description:\n 'Replay a previous deploy manifest in reverse, executing reverseSql for each successful step.',\n },\n snapshot: {\n term: 'snapshot',\n description:\n 'Inspect / prune the pre-deploy snapshot registry written by `ddt publish --apply`.',\n },\n graph: {\n term: 'graph [options]',\n description: 'Build an object-dependency DAG and emit it as Mermaid or DOT.',\n },\n lineage: {\n term: 'lineage [options]',\n description: 'Extract data-flow lineage from a .ddtproj, .ddtpac, or dbt manifest.json.',\n },\n diagnose: {\n term: 'diagnose [options]',\n description:\n 'Project-level health report: lint + lineage smells + object smells + cost smells, with reasoning.',\n },\n review: {\n term: 'review [options]',\n description:\n 'Senior-DBA-style health report (lint + lineage + smell + cost + safety, with reasoning).',\n },\n impact: {\n term: 'impact [options] <fqn>',\n description:\n 'Single-FQN blast-radius: who feeds it, who reads from it, what findings apply to it.',\n },\n 'cost-estimate': {\n term: 'cost-estimate [options]',\n description: 'Heuristic Databricks-DBU estimate for a generated migration script.',\n },\n 'pr-comment': {\n term: 'pr-comment [options]',\n description:\n 'Generate a Markdown PR comment from a source↔target compare (diff + safety + health).',\n },\n template: {\n term: 'template [options] <kind> <name>',\n description:\n 'Scaffold a common schema pattern (scd1|scd2|scd3|scd4|scd6|star|fact|scd2-merge|current-view|time-series|audit). Writes .sql files into <out>/.',\n },\n anonymize: {\n term: 'anonymize [options]',\n description: 'Generate column-mask DDL for PII columns detected in the project model.',\n },\n test: {\n term: 'test',\n description:\n 'Declarative tests (unique / not_null / accepted_values / relationships / expression) compiled from YAML to SQL.',\n },\n branch: {\n term: 'branch',\n description: 'PlanetScale-style branching for Databricks via UC SHALLOW CLONE. create / drop.',\n },\n schema: {\n term: 'schema',\n description:\n 'Interop with third-party schema formats (DBML import/export; draw.io export). NOT a separate data modeler — DDT remains the canonical model.',\n },\n suggest: {\n term: 'suggest [options]',\n description:\n 'Suggest FK / PK / UK / composite-PK candidates with reasoning. Output is Markdown by default.',\n },\n history: {\n term: 'history [options]',\n description:\n 'List deploy manifests (default) or query live system.query.* via --last/--query/--verify.',\n },\n 'audit-log': {\n term: 'audit-log',\n description:\n 'Export deploy history to enterprise audit sinks (file / syslog / Splunk HEC / Datadog Logs).',\n },\n 'install-hooks': {\n term: 'install-hooks [options]',\n description:\n 'Install a git pre-commit hook that runs `ddt validate` + `ddt format --check` before each commit.',\n },\n telemetry: {\n term: 'telemetry',\n description: 'Manage opt-in telemetry. Off by default; local-only by default.',\n },\n seed: {\n term: 'seed',\n description:\n 'Reference / dimension data seeds. Declare static rows next to DDL; engine generates MERGEs.',\n },\n suite: {\n term: 'suite',\n description: 'Manage a .ddtsuite — a collection of .ddtproj projects deploying together.',\n },\n refactor: {\n term: 'refactor',\n description: 'Record refactor operations (renames, moves) so compare emits ALTER … RENAME.',\n },\n license: {\n term: 'license',\n description: 'Manage the DDT license key (open-core, offline, warn-mode in v0.3).',\n },\n mcp: {\n term: 'mcp',\n description:\n 'Start the DDT Model Context Protocol server on stdio (for Claude / Cursor / agents).',\n },\n ai: { term: 'ai', description: 'Configure and test the AI provider adapter (BYO key).' },\n explain: {\n term: 'explain [options] [query...]',\n description:\n 'Search the options catalog. Explains what an option does, when to use it, and what it pairs with.',\n },\n feedback: {\n term: 'feedback [options] <message...>',\n description: 'Send a feedback / bug / feature-request ticket to the DDT team.',\n },\n features: {\n term: 'features',\n description:\n 'Browse DDT features. Free users see paid features too — with copy explaining what each one does and how to unlock it.',\n },\n hosts: {\n term: 'hosts',\n description:\n 'Browse every host DDT plugs into — CLI, VS Code, MCP agents, Databricks Workflows, dbt, Airflow, etc. Shows supported versions and the host-specific tailoring notes.',\n },\n safety: {\n term: 'safety',\n description:\n 'Inspect the safety-finding catalog. See `ddt safety list` and `ddt safety explain <code>`.',\n },\n pii: {\n term: 'pii',\n description:\n 'Detect PII columns + render Unity-Catalog column-mask DDL. See `ddt pii scan` and `ddt pii mask`.',\n },\n bisect: {\n term: 'bisect [options] <fqn>',\n description: 'Find the commit where a specific FQN first changed in the project tree.',\n },\n changelog: {\n term: 'changelog [options]',\n description:\n 'Generate a Markdown CHANGELOG section from git commits between two refs (Conventional Commits parser).',\n },\n replay: {\n term: 'replay [options]',\n description:\n 'Re-execute forwardSql from one or more deploy manifests against a target workspace.',\n },\n 'drift-gate': {\n term: 'drift-gate [options]',\n description:\n 'Refuse-on-drift CI gate across multiple replica workspaces. Compares replicas against a primary.',\n },\n promote: {\n term: 'promote [options]',\n description:\n 'Branch-per-env deploy: compare live source→target, optionally open a PR with the deploy bundle.',\n },\n 'data-fit': {\n term: 'data-fit [options]',\n description:\n 'Emit pre-flight SELECT count_if() probes for every narrowing type change in a pac↔pac compare. Run them against the live target before --apply.',\n },\n 'data-compare': {\n term: 'data-compare [options]',\n description:\n 'Row-level data compare: diff two tables by primary key and emit an INSERT/UPDATE/DELETE script that converts target into source. Source/target rows read from JSON files in v1.',\n },\n approval: {\n term: 'approval',\n description: 'Record / list / verify multi-approver gate tokens for prod deploys.',\n },\n 'advise-tests': {\n term: 'advise-tests [options]',\n description:\n 'PR-time AI regression-test advisor. Walks the DDT feature catalog, flags features whose surfaces match the changed files, and recommends 1–8 tests to add alongside the diff.',\n },\n 'safer-alternative': {\n term: 'safer-alternative [options]',\n description:\n 'AI-assist: propose a safer DDL alternative for a safety finding. Requires a configured AI provider (ddt ai status).',\n },\n sketch: {\n term: 'sketch [options] <kind>',\n description:\n 'AI-assist: scaffold idiomatic Databricks UC DDL from a prose description. Output always carries a REVIEW BEFORE DEPLOY header.',\n },\n design: {\n term: 'design',\n description:\n 'AI-assist: generative schema-design scaffolds. Output always carries a REVIEW BEFORE RUNNING header.',\n },\n optimize: {\n term: 'optimize [options]',\n description:\n 'Surface ranked optimization recommendations (Z-ORDER, ENUM-shaped strings, missing PKs, streaming-table schedule).',\n },\n 'rollback-suggest': {\n term: 'rollback-suggest [options]',\n description:\n 'AI-assist: propose a reverse SQL for a forward DDL when the deterministic plan-to-steps bridge could not invert it. Output always carries a REVIEW BEFORE APPLY header. Standalone — not auto-wired into `revert`.',\n },\n 'compare-profiles': {\n term: 'compare-profiles',\n description: 'Manage saved compare profiles (.ddt/compare-profiles.json).',\n },\n explorer: {\n term: 'explorer [options]',\n description:\n 'ASCII tree dump of the cached catalog for a connection. Run `ddt catalog refresh` first to populate.',\n },\n catalog: {\n term: 'catalog',\n description:\n 'Manage the per-connection catalog cache used by the Object Explorer + EE2 intellisense.',\n },\n 'xcompare-ir': {\n term: 'xcompare-ir [options]',\n description:\n 'Cross-platform IR compare (Databricks ↔ Snowflake). Maps source IRs through XPM-Deep substrate; emits tier-gated safety assessment. IR-level only (live-warehouse compare is a follow-up).',\n },\n profile: {\n term: 'profile [options] <fqn>',\n description:\n 'Compute per-column profile statistics (nulls, distinct, min/max, top values) for a table. Rows are read from a JSON file in v1 (live-warehouse executeRows wiring is a documented follow-up).',\n },\n 'suggest-constraints': {\n term: 'suggest-constraints [options] <fqn>',\n description:\n 'Suggest PK/UK/FK/CHECK candidates for a profiled table. Reads a TableProfile JSON (from `ddt profile`) and emits suggestions with confidence tiers + rationale.',\n },\n purge: {\n term: 'purge [options]',\n description:\n 'Generate a DROP script for every object in the project (bulk teardown). Requires --confirm-production. Honours all per-type drop gates.',\n },\n preview: {\n term: 'preview [options] <fqn>',\n description:\n 'Preview rows from a table (SELECT * FROM <fqn> LIMIT <n>). Read-only — requires a connection profile.',\n },\n refresh: {\n term: 'refresh [options]',\n description:\n 'Generate a REFRESH script for streaming tables + materialized views + pipeline API calls. Operator runs the output script + makes the pipeline API calls explicitly.',\n },\n discover: {\n term: 'discover [options]',\n description: 'Show personalized feature suggestions based on your usage history.',\n },\n find: {\n term: 'find [options] <query...>',\n description: 'Search DDT features by keyword — find what you want to do.',\n },\n 'scan-secrets': {\n term: 'scan-secrets [options]',\n description: 'Scan a project or pac for hardcoded credentials in DDL bodies.',\n },\n 'error-lookup': {\n term: 'error-lookup [options]',\n description: 'Look up a failure in the known-error catalog by code, fingerprint, or message.',\n },\n 'deploy-status': {\n term: 'deploy-status [options] [deployId]',\n description: 'Show or list resumable deploy checkpoints written by `ddt publish`.',\n },\n 'approval-chain': {\n term: 'approval-chain',\n description: 'Signed M-of-N approval workflow (DSR.8).',\n },\n standards: {\n term: 'standards',\n description: 'Team SQL standards — init, check, fix, and explain.',\n },\n perf: {\n term: 'perf',\n description: 'CLI performance diagnostics (cold-start audit, hot-path profiling).',\n },\n 'migrate-platform': {\n term: 'migrate-platform [options] <path>',\n description:\n 'Translate Databricks SQL files to another platform dialect. v1: --to snowflake. Reads .sql files from <path> (file or directory).',\n },\n migrate: {\n term: 'migrate',\n description: 'Migrate from another tool to SDT (`from-dbt` subcommand only in v1).',\n },\n backlog: {\n term: 'backlog',\n description: 'Local-compute backlog tooling. Pure parse + score; no warehouse contact.',\n },\n watch: {\n term: 'watch',\n description:\n 'Platform-feature drift detector. Diffs release-notes markdown against a cached snapshot.',\n },\n bookmarks: {\n term: 'bookmarks [options]',\n description: 'Save fast-access pointers to queries, files, or named sections.',\n },\n snippets: {\n term: 'snippets',\n description: 'Browse the built-in SQL snippet catalog (SCD, star schema, data quality).',\n },\n generate: {\n term: 'generate',\n description: 'Code generation: ingest notebooks, SCD merge scripts, star-schema pipelines.',\n },\n exec: {\n term: 'exec [options] <file>',\n description: 'Run a SQL script on one or more connection profiles in parallel.',\n },\n search: {\n term: 'search [options] <pattern>',\n description: 'Find objects matching a name pattern across one or more connection profiles.',\n },\n 'query-log': {\n term: 'query-log',\n description: 'Browse and manage the local query log from the EE3 query window (AUTH.5).',\n },\n savings: {\n term: 'savings [options]',\n description: 'Show estimated AI token savings from using deterministic DDT surfaces.',\n },\n trial: { term: 'trial', description: 'Manage the DDT 30-day Pro trial (no account required).' },\n pilot: {\n term: 'pilot',\n description: 'Join or check the DDT pilot program (90-day Pro access for early adopters).',\n },\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commandManifest.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `ddt` — Databricks Data Tools command-line interface.\n *\n * Mirrors the SDT CLI surface: every command name and flag matches so muscle\n * memory carries between Snowflake and Databricks engagements.\n *\n * Subcommand modules are loaded LAZILY: only the requested subcommand's\n * module (and its `@ddt-tools/core` dependency chain) is imported on the common\n * path. `--help` / `--version` / no-arg / unknown-command paths fall back\n * to loading every command so Commander can render the full subcommand\n * list.\n *\n * Cold-start win: `ddt <known-cmd> ...` skips ~80 command-module loads\n * and their per-module `@ddt-tools/core/...` imports. Mirrors the SDT-side\n * pattern; see Snowflake/packages/cli/src/cli.ts.\n */\nimport { Command, Help } from 'commander';\n// RH4.2 — core modules are imported LAZILY (dynamic `import()` at the use\n// site), NOT eagerly at module top. The eager subpath imports of\n// `@ddt-tools/core/{discovery,features,outputStyle}` each statically pulled\n// their whole barrel subtree into the startup chunk, which Node parsed +\n// evaluated on every invocation — including the `--version` / `--help`\n// fast paths that never touch them. Deferring them lets tsup code-split\n// those subtrees out of the eager chunk so cold start pays only Node\n// bootstrap + commander + the requested command. `import type` is free\n// (erased at compile), so types stay top-level. The barrel (`@ddt-tools/core`)\n// is still never imported — subpath / dynamic only (RH3.3 pin).\nimport type { OutputStyle } from '@ddt-tools/core/outputStyle';\nimport { COMMAND_MANIFEST } from './commandManifest.js';\nimport chalk from 'chalk';\nimport { logger } from './util/logger.js';\n\nconst VALID_OUTPUT_STYLES = new Set<OutputStyle>(['standard', 'audit', 'ci', 'review', 'terse']);\n\n/**\n * Resolve the default `--style` value without eagerly loading the\n * `@ddt-tools/core/outputStyle` module on the cold-start path. Mirrors\n * `resolveOutputStyle()` exactly (env var → default 'standard'); the flag\n * value is not yet known here (commander resolves it after parse), so this\n * only folds in `DDT_OUTPUT_STYLE`. Kept in lockstep with\n * core/outputStyle/style.ts `resolveOutputStyle`.\n */\nfunction defaultOutputStyle(): OutputStyle {\n const env = process.env['DDT_OUTPUT_STYLE'];\n if (env && VALID_OUTPUT_STYLES.has(env as OutputStyle)) return env as OutputStyle;\n return 'standard';\n}\n\nconst CLI_VERSION = '0.2.5';\n\n// Cold-start timestamp for `ddt perf cold-start`. ESM hoists imports above\n// this line, so a plain `process.hrtime.bigint()` here would EXCLUDE the\n// import cost from the measurement. Back-date the stamp to true process\n// start (`performance.now()` counts from process timeOrigin) so the\n// reported number covers Node bootstrap + ESM imports + command dispatch.\n// `??=` preserves a value pre-set by any earlier bootstrap wrapper.\n(globalThis as { __DDT_START_NS__?: bigint }).__DDT_START_NS__ ??=\n process.hrtime.bigint() - BigInt(Math.round(performance.now() * 1e6));\n\n// Mapping of CLI subcommand-name → lazy loader. Each loader resolves to\n// the Commander `Command` instance for that subcommand. When you add a\n// new top-level `ddt <name>` command, add its entry here. Aliases (`erd`)\n// can re-use the same module export with a different factory name.\nexport const COMMAND_LOADERS: Record<string, () => Promise<Command>> = {\n connection: async () => (await import('./commands/connection.js')).connectionCommand(),\n init: async () => (await import('./commands/init.js')).initCommand(),\n validate: async () => (await import('./commands/validate.js')).validateCommand(),\n compare: async () => (await import('./commands/compare.js')).compareCommand(),\n build: async () => (await import('./commands/build.js')).buildCommand(),\n publish: async () => (await import('./commands/publish.js')).publishCommand(),\n script: async () => (await import('./commands/script.js')).scriptCommand(),\n import: async () => (await import('./commands/import.js')).importCommand(),\n 'import-script': async () => (await import('./commands/import-script.js')).importScriptCommand(),\n extract: async () => (await import('./commands/extract.js')).extractCommand(),\n completion: async () => (await import('./commands/completion.js')).completionCommand(),\n drift: async () => (await import('./commands/drift.js')).driftCommand(),\n format: async () => (await import('./commands/format.js')).formatCommand(),\n lint: async () => (await import('./commands/lint.js')).lintCommand(),\n docs: async () => (await import('./commands/docs.js')).docsCommand(),\n erd: async () => (await import('./commands/docs.js')).erdCommand(),\n verify: async () => (await import('./commands/verify.js')).verifyCommand(),\n revert: async () => (await import('./commands/revert.js')).revertCommand(),\n snapshot: async () => (await import('./commands/snapshot.js')).snapshotCommand(),\n graph: async () => (await import('./commands/graph.js')).graphCommand(),\n lineage: async () => (await import('./commands/lineage.js')).lineageCommand(),\n diagnose: async () => (await import('./commands/diagnose.js')).diagnoseCommand(),\n review: async () => (await import('./commands/review.js')).reviewCommand(),\n impact: async () => (await import('./commands/impact.js')).impactCommand(),\n 'cost-estimate': async () => (await import('./commands/cost-estimate.js')).costEstimateCommand(),\n 'pr-comment': async () => (await import('./commands/pr-comment.js')).prCommentCommand(),\n template: async () => (await import('./commands/template.js')).templateCommand(),\n anonymize: async () => (await import('./commands/anonymize.js')).anonymizeCommand(),\n test: async () => (await import('./commands/test.js')).testCommand(),\n branch: async () => (await import('./commands/branch.js')).branchCommand(),\n schema: async () => (await import('./commands/schema.js')).schemaCommand(),\n suggest: async () => (await import('./commands/suggest.js')).suggestCommand(),\n history: async () => (await import('./commands/history.js')).historyCommand(),\n 'audit-log': async () => (await import('./commands/audit-log.js')).auditLogCommand(),\n 'install-hooks': async () => (await import('./commands/install-hooks.js')).installHooksCommand(),\n telemetry: async () => (await import('./commands/telemetry.js')).telemetryCommand(),\n seed: async () => (await import('./commands/seed.js')).seedCommand(),\n suite: async () => (await import('./commands/suite.js')).suiteCommand(),\n refactor: async () => (await import('./commands/refactor.js')).refactorCommand(),\n license: async () => (await import('./commands/license.js')).licenseCommand(),\n mcp: async () => (await import('./commands/mcp.js')).mcpCommand(),\n ai: async () => (await import('./commands/ai.js')).aiCommand(),\n explain: async () => (await import('./commands/explain.js')).explainCommand(),\n feedback: async () => (await import('./commands/feedback.js')).feedbackCommand(),\n features: async () => (await import('./commands/features.js')).featuresCommand(),\n hosts: async () => (await import('./commands/hosts.js')).hostsCommand(),\n safety: async () => (await import('./commands/safety.js')).safetyCommand(),\n pii: async () => (await import('./commands/pii.js')).piiCommand(),\n bisect: async () => (await import('./commands/bisect.js')).bisectCommand(),\n changelog: async () => (await import('./commands/changelog.js')).changelogCommand(),\n replay: async () => (await import('./commands/replay.js')).replayCommand(),\n 'drift-gate': async () => (await import('./commands/drift-gate.js')).driftGateCommand(),\n promote: async () => (await import('./commands/promote.js')).promoteCommand(),\n 'data-fit': async () => (await import('./commands/data-fit.js')).dataFitCommand(),\n 'data-compare': async () => (await import('./commands/data-compare.js')).dataCompareCommand(),\n approval: async () => (await import('./commands/approval.js')).approvalCommand(),\n 'advise-tests': async () => (await import('./commands/advise-tests.js')).adviseTestsCommand(),\n 'safer-alternative': async () =>\n (await import('./commands/safer-alternative.js')).saferAlternativeCommand(),\n sketch: async () => (await import('./commands/sketch.js')).sketchCommand(),\n design: async () => (await import('./commands/design.js')).designCommand(),\n optimize: async () => (await import('./commands/optimize.js')).optimizeCommand(),\n 'rollback-suggest': async () =>\n (await import('./commands/rollback-suggest.js')).rollbackSuggestCommand(),\n 'compare-profiles': async () =>\n (await import('./commands/compare-profiles.js')).compareProfilesCommand(),\n explorer: async () => (await import('./commands/explorer.js')).explorerCommand(),\n catalog: async () => (await import('./commands/catalog.js')).catalogCommand(),\n 'xcompare-ir': async () => (await import('./commands/xcompare.js')).xcompareCommand(),\n profile: async () => (await import('./commands/profile.js')).profileCommand(),\n 'suggest-constraints': async () =>\n (await import('./commands/suggest-constraints.js')).suggestConstraintsCommand(),\n purge: async () => (await import('./commands/purge.js')).purgeCommand(),\n preview: async () => (await import('./commands/preview.js')).previewCommand(),\n refresh: async () => (await import('./commands/refresh.js')).refreshCommand(),\n discover: async () => (await import('./commands/discover.js')).discoverCommand(),\n find: async () => (await import('./commands/find.js')).findCommand(),\n 'scan-secrets': async () => (await import('./commands/scan-secrets.js')).scanSecretsCommand(),\n 'error-lookup': async () => (await import('./commands/error-lookup.js')).errorLookupCommand(),\n 'deploy-status': async () => (await import('./commands/deploy-status.js')).deployStatusCommand(),\n 'approval-chain': async () =>\n (await import('./commands/approval-chain.js')).approvalChainCommand(),\n standards: async () => (await import('./commands/standards.js')).standardsCommand(),\n perf: async () => (await import('./commands/perf.js')).perfCommand(),\n 'migrate-platform': async () =>\n (await import('./commands/migrate-platform.js')).migratePlatformCommand(),\n migrate: async () => (await import('./commands/migrate-from-dbt.js')).migrateFromDbtCommand(),\n backlog: async () => (await import('./commands/backlog.js')).backlogCommand(),\n watch: async () => (await import('./commands/watch.js')).watchCommand(),\n bookmarks: async () => (await import('./commands/bookmarks.js')).bookmarksCommand(),\n snippets: async () => (await import('./commands/snippets.js')).snippetsCommand(),\n generate: async () => (await import('./commands/generate.js')).generateCommand(),\n exec: async () => (await import('./commands/exec.js')).execCommand(),\n search: async () => (await import('./commands/search.js')).searchCommand(),\n 'query-log': async () => (await import('./commands/query-log.js')).queryLogCommand(),\n savings: async () => (await import('./commands/savings.js')).savingsCommand(),\n trial: async () => (await import('./commands/trial.js')).trialCommand(),\n pilot: async () => (await import('./commands/pilot.js')).pilotCommand(),\n};\n\n/**\n * PIL.5 tier-gating enforcement — the body of the `preAction` hook `main()`\n * registers on `program`, extracted so it's independently testable (the\n * `preAction` callback itself calls `process.exit(1)` directly, which can't\n * be exercised safely except by mocking `process.exit` around a call to\n * this function — see `tests/tier-gate-hook.test.ts`). Walks `actionCommand`\n * up to its root to build the full subcommand path (so `ddt drift watch`\n * resolves to `['drift', 'watch']`, not just `['watch']`), looks it up in\n * `commandTiers.ts`'s `COMMAND_TIER_GATES`, and blocks (exit 1) or notes a\n * trial countdown exactly as `resolveAccessForCommand` decides.\n */\nexport async function tierGateHook(actionCommand: Command): Promise<void> {\n const path: string[] = [];\n for (let c: Command | null = actionCommand; c && c.parent; c = c.parent) {\n path.unshift(c.name());\n }\n const licenseNs = await import('@ddt-tools/core/license');\n const gate = licenseNs.findCommandGate(path);\n if (!gate) return;\n\n const requiredTier = licenseNs.resolveRequiredTier(gate.requiredTier, actionCommand.opts());\n const access = await licenseNs.resolveAccessForCommand(requiredTier, gate.label);\n if (!access.allowed) {\n logger.error(access.blockedReason ?? `\"${gate.label}\" requires a ${requiredTier} license.`);\n process.exitCode = 1;\n process.exit(1);\n // Unreachable in production (process.exit terminates); the explicit\n // return keeps control flow self-evidently safe under a test double\n // that mocks process.exit as a no-op instead of actually exiting.\n return;\n }\n if (access.trialNotice) {\n console.log(chalk.dim(access.trialNotice));\n }\n}\n\nasync function main(): Promise<void> {\n // RH4.2 cold-start fast path: `ddt -v` / `ddt --version` is the canonical\n // cold-start benchmark and must not load any command chunk. With code\n // splitting (tsup `splitting: true`) the no-arg / `--help` / `--version`\n // path otherwise loads ALL ~85 command chunks (separate files) so\n // commander can render the full subcommand list — dozens of disk reads\n // that dominate wall-clock on Windows. `--version` only needs the\n // version string, so short-circuit before building the program. Mirrors\n // commander's own `--version` output (bare version line) exactly.\n const firstArg = process.argv[2];\n if (firstArg === '--version' || firstArg === '-v') {\n process.stdout.write(CLI_VERSION + '\\n');\n return;\n }\n\n const program = new Command();\n program\n .name('ddt')\n .description(\n 'Databricks Data Tools — declarative schema management for Databricks Unity Catalog.',\n )\n .version(CLI_VERSION, '-v, --version')\n .option(\n '--style <mode>',\n 'Output style: standard | audit | ci | review | terse. Also reads DDT_OUTPUT_STYLE env var.',\n defaultOutputStyle(),\n )\n .option('--explain-features', 'After each command, show related features from the catalog.');\n\n const arg2 = process.argv[2];\n const explicitLoader = arg2 && !arg2.startsWith('-') ? COMMAND_LOADERS[arg2] : undefined;\n\n if (explicitLoader) {\n program.addCommand(await explicitLoader());\n } else {\n // RH4.7 — help / no-arg / unknown-command path. Register STUB\n // subcommands (name + description) from the static manifest instead of\n // loading all ~85 command modules. Commander renders the subcommand\n // list + the standard \"unknown command\" error from these stubs with\n // zero command-module imports. The stub carries no options/arguments,\n // so its rendered term would be just the bare name; override\n // `subcommandTerm` to emit the manifest's exact term (e.g.\n // `template [options] <kind> <name>`) so the --help columns are\n // byte-identical to the load-everything path. Per-command help\n // (`ddt <cmd> --help`) still loads the real module via the\n // explicit-loader path above, so argument/option detail is unaffected.\n for (const [name, entry] of Object.entries(COMMAND_MANIFEST)) {\n program.command(name).description(entry.description);\n }\n const defaultHelp = new Help();\n program.configureHelp({\n // Manifest commands render their exact term; the implicit `help`\n // subcommand (and anything else not in the manifest) falls back to\n // commander's own term so `help [command]` stays intact.\n subcommandTerm: (cmd) =>\n COMMAND_MANIFEST[cmd.name()]?.term ?? defaultHelp.subcommandTerm(cmd),\n });\n }\n\n // Global help footer — surfaces the searchable options catalog\n // (`ddt explain <query>`) on every command's --help screen. Free-tier\n // discoverability hook: users land in --help, see the hint, learn\n // they can ask `ddt explain allowDropTable` for safety + path detail\n // without leaving the terminal. Mirrors the SDT-side footer.\n program.addHelpText('afterAll', () =>\n [\n '',\n 'Options catalog:',\n ' Every CLI flag and `.ddtproj` option has a searchable entry with safety',\n ' tier, default, related options, and an example. Look one up with:',\n ' ddt explain <name> # e.g. ddt explain allowDropTable',\n ' ddt explain <topic> # fuzzy: \"drop\", \"safety\", \"compare\"',\n '',\n 'Features catalog (locked + unlocked):',\n ' ddt features list # what ships in each tier',\n ' ddt features show <id>',\n '',\n 'Personalized suggestions:',\n ' ddt discover # feature tips based on your usage history',\n '',\n 'Watch the 60-second demos:',\n ' Schema Compare https://youtu.be/_p5Z45T2kVM',\n ' Safe deploy https://youtu.be/L7wbQI3OzEQ',\n ' Extract workspace https://youtu.be/lVclo6wnWfw',\n ' All demos https://www.youtube.com/channel/UCc3L8L8BBOO9lVLI1V2FFNQ',\n '',\n ].join('\\n'),\n );\n\n // ERR.2 — error-reporting lifecycle. Lazily imported so the cold-start\n // path pays nothing; the preAction hook handles first-run consent +\n // crash-hook install, the postAction hook drains the spool when consent\n // is on. Both no-op fast for exempt commands (telemetry, feedback, help).\n program.hook('preAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.parent !== program) return;\n const reporting = await import('./util/errorReporting.js');\n await reporting.setupErrorReporting(actionCommand.name());\n });\n program.hook('postAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.parent !== program) return;\n const reporting = await import('./util/errorReporting.js');\n await reporting.finishErrorReporting(CLI_VERSION);\n });\n\n // PIL.5 — tier-gating enforcement. Runs for every command INCLUDING\n // nested subcommands (unlike the two hooks above, which only fire for\n // direct `ddt <cmd>` invocations) so `ddt drift watch`, `ddt approval\n // add`, etc. are covered by their own gate entries. Commands with no\n // entry in the table (Free tier, or a deliberately-deferred mixed-tier\n // command — see commandTiers.ts) pass through untouched.\n program.hook('preAction', async (_thisCommand, actionCommand) => {\n await tierGateHook(actionCommand);\n });\n\n // Feature Discovery: fire a single contextual hint after each top-level\n // command succeeds. One line, dim, easy to ignore. Disabled with DDT_NO_HINTS=1.\n // RH4.2 — the FeatureAdvisor + hint rules and the features catalog are\n // imported LAZILY inside the hook so the cold-start path (which never\n // runs an action hook for `--version` / `--help`) pays nothing for them.\n program.hook('postAction', async (_thisCommand, actionCommand) => {\n if (actionCommand.parent !== program) return;\n const { FeatureAdvisor, DDT_HINT_RULES } = await import('@ddt-tools/core/discovery');\n const ddtAdvisor = new FeatureAdvisor('ddt', DDT_HINT_RULES);\n const tip = ddtAdvisor.advise(actionCommand.name());\n if (tip) {\n console.log(chalk.dim(`\\n ✦ ${tip}`));\n console.log(chalk.dim(' ddt discover · ddt features list'));\n }\n // DSC.6 — explain-features: when the global flag is set, show related\n // features from the catalog for the command that just ran.\n if ((program.opts() as { explainFeatures?: boolean }).explainFeatures) {\n const cmdName = actionCommand.name();\n const featuresNs = await import('@ddt-tools/core/features');\n const related = featuresNs.pickRelatedFeatures(\n featuresNs.DDT_FEATURE_CATALOG,\n cmdName,\n 3,\n 'ddt',\n );\n const hint = featuresNs.renderRelatedFeaturesHint(related, cmdName, 'ddt');\n if (hint) console.log(chalk.dim('\\n' + hint));\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\n// Only auto-run when invoked as the CLI entry point, not when imported by\n// a test harness (the COMMAND_LOADERS / COMMAND_MANIFEST anti-drift test\n// imports this module to introspect the registry without dispatching).\nif (process.env['DDT_CLI_NO_MAIN'] !== '1') {\n main().catch(async (err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n // ERR.2 — capture the failure and (with consent) report it; without\n // consent, offer a one-keystroke manual report. Never throws.\n try {\n const reporting = await import('./util/errorReporting.js');\n await reporting.reportCliFailure(err, CLI_VERSION);\n } catch {\n // Error reporting must never mask the original failure.\n }\n });\n}\n","/**\n * Static command manifest — subcommand name → { term, description }.\n *\n * RH4.7: the `--help` / no-arg / unknown-command paths render the full\n * subcommand list. Building that list by loading every entry in\n * `COMMAND_LOADERS` forces ~85 lazy command chunks (and their\n * `@ddt-tools/core/...` dependency chains) off disk on a path that never\n * executes a command — the dominant cost of `ddt --help` cold start.\n *\n * Instead, the help/error paths register STUB subcommands from this\n * manifest and render the subcommand list from it, so Commander produces a\n * byte-identical subcommand list + usage error without importing a single\n * command module. The real module is loaded only when a known command is\n * actually dispatched (see `cli.ts`).\n *\n * - `term` — the exact left-column term Commander renders for the\n * command in the parent --help list (name + ` [options]`\n * when the command registers any option + the\n * human-readable positional-argument signature). Used to\n * override `subcommandTerm` so the help columns line up\n * identically to the load-everything path.\n * - `description` — the one-line string the command module passes to\n * commander's `.description(...)`.\n *\n * `commandManifest.test.ts` dynamically loads every `COMMAND_LOADERS` entry\n * and asserts both `term` and `description` match what the real module\n * registers, plus that the key set + order are identical — so any drift (a\n * changed description, a new/removed option or argument, a new command\n * without a manifest row, a stale row) fails the test rather than silently\n * rotting the help text.\n *\n * Key order is kept aligned with `COMMAND_LOADERS` in `cli.ts` so the\n * rendered `--help` subcommand ordering is unchanged. Mirrors the\n * Snowflake-side manifest.\n */\nexport interface CommandManifestEntry {\n /** Exact Commander subcommand term for the parent --help list. */\n readonly term: string;\n /** One-line description (must equal the module's `.description(...)`). */\n readonly description: string;\n}\n\nexport const COMMAND_MANIFEST: Record<string, CommandManifestEntry> = {\n connection: { term: 'connection', description: 'Manage Databricks connection profiles.' },\n init: {\n term: 'init [options]',\n description: 'Initialize a new DDT project in the current directory.',\n },\n validate: {\n term: 'validate [options]',\n description:\n 'Validate a .ddtproj — schema check; optionally resolve every object reference (--references).',\n },\n compare: {\n term: 'compare [options]',\n description:\n 'Compare two schemas (the desired state vs the current state). Each side may be a .ddtproj, a .ddtpac, or databricks://<profile>[/catalog[/schema]].',\n },\n build: { term: 'build [options]', description: 'Build a .ddtpac from a .ddtproj project.' },\n publish: {\n term: 'publish [options]',\n description:\n 'Generate (and optionally apply) a migration script from source → target. Shared form with `sdt publish`: `--source <desired> --connection <live-target>` compares the desired state against the live workspace. Or pass `--target <offline>` to diff against a `.ddtproj` / `.ddtpac` instead.',\n },\n script: {\n term: 'script [options]',\n description:\n 'Generate a deploy SQL script for source → target. Always offline — does not touch the workspace.',\n },\n import: {\n term: 'import [options]',\n description: 'Convert artifacts from other tools into a DDT project.',\n },\n 'import-script': {\n term: 'import-script [options]',\n description:\n 'Parse a SQL script and write each DDL statement into the .ddtproj tree under its canonical folder.',\n },\n extract: {\n term: 'extract [options]',\n description:\n 'Extract live UC objects from a workspace into a project tree (--output) or a .ddtpac (--out-pac).',\n },\n completion: {\n term: 'completion <shell>',\n description: 'Emit a shell completion script (bash | zsh | fish | powershell).',\n },\n drift: {\n term: 'drift [options]',\n description:\n 'Refuse with non-zero exit when the live target has drifted from --source or a dbt manifest.',\n },\n format: {\n term: 'format [options]',\n description:\n 'Format every .sql under a .ddtproj — uppercase reserved keywords + tidy whitespace.',\n },\n lint: {\n term: 'lint [options]',\n description:\n 'Lint a SQL script for risky deploy patterns. Exits non-zero on any ERROR-severity finding.',\n },\n docs: {\n term: 'docs [options]',\n description: 'Generate HTML schema docs from a .ddtproj or .ddtpac.',\n },\n erd: {\n term: 'erd [options]',\n description:\n 'Generate an ER diagram (Mermaid Markdown or interactive 3D HTML) from a .ddtproj or .ddtpac.',\n },\n verify: {\n term: 'verify [options]',\n description: 'Recompute checksums on a .ddtpac and confirm every object matches the manifest.',\n },\n revert: {\n term: 'revert [options]',\n description:\n 'Replay a previous deploy manifest in reverse, executing reverseSql for each successful step.',\n },\n snapshot: {\n term: 'snapshot',\n description:\n 'Inspect / prune the pre-deploy snapshot registry written by `ddt publish --apply`.',\n },\n graph: {\n term: 'graph [options]',\n description: 'Build an object-dependency DAG and emit it as Mermaid or DOT.',\n },\n lineage: {\n term: 'lineage [options]',\n description: 'Extract data-flow lineage from a .ddtproj, .ddtpac, or dbt manifest.json.',\n },\n diagnose: {\n term: 'diagnose [options]',\n description:\n 'Project-level health report: lint + lineage smells + object smells + cost smells, with reasoning.',\n },\n review: {\n term: 'review [options]',\n description:\n 'Senior-DBA-style health report (lint + lineage + smell + cost + safety, with reasoning).',\n },\n impact: {\n term: 'impact [options] <fqn>',\n description:\n 'Single-FQN blast-radius: who feeds it, who reads from it, what findings apply to it.',\n },\n 'cost-estimate': {\n term: 'cost-estimate [options]',\n description: 'Heuristic Databricks-DBU estimate for a generated migration script.',\n },\n 'pr-comment': {\n term: 'pr-comment [options]',\n description:\n 'Generate a Markdown PR comment from a source↔target compare (diff + safety + health).',\n },\n template: {\n term: 'template [options] <kind> <name>',\n description:\n 'Scaffold a common schema pattern (scd1|scd2|scd3|scd4|scd6|star|fact|scd2-merge|current-view|time-series|audit). Writes .sql files into <out>/.',\n },\n anonymize: {\n term: 'anonymize [options]',\n description: 'Generate column-mask DDL for PII columns detected in the project model.',\n },\n test: {\n term: 'test',\n description:\n 'Declarative tests (unique / not_null / accepted_values / relationships / expression) compiled from YAML to SQL.',\n },\n branch: {\n term: 'branch',\n description: 'PlanetScale-style branching for Databricks via UC SHALLOW CLONE. create / drop.',\n },\n schema: {\n term: 'schema',\n description:\n 'Interop with third-party schema formats (DBML import/export; draw.io export). NOT a separate data modeler — DDT remains the canonical model.',\n },\n suggest: {\n term: 'suggest [options]',\n description:\n 'Suggest FK / PK / UK / composite-PK candidates with reasoning. Output is Markdown by default.',\n },\n history: {\n term: 'history [options]',\n description:\n 'List deploy manifests (default) or query live system.query.* via --last/--query/--verify.',\n },\n 'audit-log': {\n term: 'audit-log',\n description:\n 'Export deploy history to enterprise audit sinks (file / syslog / Splunk HEC / Datadog Logs).',\n },\n 'install-hooks': {\n term: 'install-hooks [options]',\n description:\n 'Install a git pre-commit hook that runs `ddt validate` + `ddt format --check` before each commit.',\n },\n telemetry: {\n term: 'telemetry',\n description: 'Manage opt-in telemetry. Off by default; local-only by default.',\n },\n seed: {\n term: 'seed',\n description:\n 'Reference / dimension data seeds. Declare static rows next to DDL; engine generates MERGEs.',\n },\n suite: {\n term: 'suite',\n description: 'Manage a .ddtsuite — a collection of .ddtproj projects deploying together.',\n },\n refactor: {\n term: 'refactor',\n description: 'Record refactor operations (renames, moves) so compare emits ALTER … RENAME.',\n },\n license: {\n term: 'license',\n description: 'Manage the DDT license key (open-core, offline, warn-mode in v0.3).',\n },\n mcp: {\n term: 'mcp',\n description:\n 'Start the DDT Model Context Protocol server on stdio (for Claude / Cursor / agents).',\n },\n ai: { term: 'ai', description: 'Configure and test the AI provider adapter (BYO key).' },\n explain: {\n term: 'explain [options] [query...]',\n description:\n 'Search the options catalog. Explains what an option does, when to use it, and what it pairs with.',\n },\n feedback: {\n term: 'feedback [options] <message...>',\n description: 'Send a feedback / bug / feature-request ticket to the DDT team.',\n },\n features: {\n term: 'features',\n description:\n 'Browse DDT features. Free users see paid features too — with copy explaining what each one does and how to unlock it.',\n },\n hosts: {\n term: 'hosts',\n description:\n 'Browse every host DDT plugs into — CLI, VS Code, MCP agents, Databricks Workflows, dbt, Airflow, etc. Shows supported versions and the host-specific tailoring notes.',\n },\n safety: {\n term: 'safety',\n description:\n 'Inspect the safety-finding catalog. See `ddt safety list` and `ddt safety explain <code>`.',\n },\n pii: {\n term: 'pii',\n description:\n 'Detect PII columns + render Unity-Catalog column-mask DDL. See `ddt pii scan` and `ddt pii mask`.',\n },\n bisect: {\n term: 'bisect [options] <fqn>',\n description: 'Find the commit where a specific FQN first changed in the project tree.',\n },\n changelog: {\n term: 'changelog [options]',\n description:\n 'Generate a Markdown CHANGELOG section from git commits between two refs (Conventional Commits parser).',\n },\n replay: {\n term: 'replay [options]',\n description:\n 'Re-execute forwardSql from one or more deploy manifests against a target workspace.',\n },\n 'drift-gate': {\n term: 'drift-gate [options]',\n description:\n 'Refuse-on-drift CI gate across multiple replica workspaces. Compares replicas against a primary.',\n },\n promote: {\n term: 'promote [options]',\n description:\n 'Branch-per-env deploy: compare live source→target, optionally open a PR with the deploy bundle.',\n },\n 'data-fit': {\n term: 'data-fit [options]',\n description:\n 'Emit pre-flight SELECT count_if() probes for every narrowing type change in a pac↔pac compare. Run them against the live target before --apply.',\n },\n 'data-compare': {\n term: 'data-compare [options]',\n description:\n 'Row-level data compare: diff two tables by primary key and emit an INSERT/UPDATE/DELETE script that converts target into source. Source/target rows read from JSON files in v1.',\n },\n approval: {\n term: 'approval',\n description: 'Record / list / verify multi-approver gate tokens for prod deploys.',\n },\n 'advise-tests': {\n term: 'advise-tests [options]',\n description:\n 'PR-time AI regression-test advisor. Walks the DDT feature catalog, flags features whose surfaces match the changed files, and recommends 1–8 tests to add alongside the diff.',\n },\n 'safer-alternative': {\n term: 'safer-alternative [options]',\n description:\n 'AI-assist: propose a safer DDL alternative for a safety finding. Requires a configured AI provider (ddt ai status).',\n },\n sketch: {\n term: 'sketch [options] <kind>',\n description:\n 'AI-assist: scaffold idiomatic Databricks UC DDL from a prose description. Output always carries a REVIEW BEFORE DEPLOY header.',\n },\n design: {\n term: 'design',\n description:\n 'AI-assist: generative schema-design scaffolds. Output always carries a REVIEW BEFORE RUNNING header.',\n },\n optimize: {\n term: 'optimize [options]',\n description:\n 'Surface ranked optimization recommendations (Z-ORDER, ENUM-shaped strings, missing PKs, streaming-table schedule).',\n },\n 'rollback-suggest': {\n term: 'rollback-suggest [options]',\n description:\n 'AI-assist: propose a reverse SQL for a forward DDL when the deterministic plan-to-steps bridge could not invert it. Output always carries a REVIEW BEFORE APPLY header. Standalone — not auto-wired into `revert`.',\n },\n 'compare-profiles': {\n term: 'compare-profiles',\n description: 'Manage saved compare profiles (.ddt/compare-profiles.json).',\n },\n explorer: {\n term: 'explorer [options]',\n description:\n 'ASCII tree dump of the cached catalog for a connection. Run `ddt catalog refresh` first to populate.',\n },\n catalog: {\n term: 'catalog',\n description:\n 'Manage the per-connection catalog cache used by the Object Explorer + EE2 intellisense.',\n },\n 'xcompare-ir': {\n term: 'xcompare-ir [options]',\n description:\n 'Cross-platform IR compare (Databricks ↔ Snowflake). Maps source IRs through XPM-Deep substrate; emits tier-gated safety assessment. IR-level only (live-warehouse compare is a follow-up).',\n },\n profile: {\n term: 'profile [options] <fqn>',\n description:\n 'Compute per-column profile statistics (nulls, distinct, min/max, top values) for a table. Rows are read from a JSON file in v1 (live-warehouse executeRows wiring is a documented follow-up).',\n },\n 'suggest-constraints': {\n term: 'suggest-constraints [options] <fqn>',\n description:\n 'Suggest PK/UK/FK/CHECK candidates for a profiled table. Reads a TableProfile JSON (from `ddt profile`) and emits suggestions with confidence tiers + rationale.',\n },\n purge: {\n term: 'purge [options]',\n description:\n 'Generate a DROP script for every object in the project (bulk teardown). Requires --confirm-production. Honours all per-type drop gates.',\n },\n preview: {\n term: 'preview [options] <fqn>',\n description:\n 'Preview rows from a table (SELECT * FROM <fqn> LIMIT <n>). Read-only — requires a connection profile.',\n },\n refresh: {\n term: 'refresh [options]',\n description:\n 'Generate a REFRESH script for streaming tables + materialized views + pipeline API calls. Operator runs the output script + makes the pipeline API calls explicitly.',\n },\n discover: {\n term: 'discover [options]',\n description: 'Show personalized feature suggestions based on your usage history.',\n },\n find: {\n term: 'find [options] <query...>',\n description: 'Search DDT features by keyword — find what you want to do.',\n },\n 'scan-secrets': {\n term: 'scan-secrets [options]',\n description: 'Scan a project or pac for hardcoded credentials in DDL bodies.',\n },\n 'error-lookup': {\n term: 'error-lookup [options]',\n description: 'Look up a failure in the known-error catalog by code, fingerprint, or message.',\n },\n 'deploy-status': {\n term: 'deploy-status [options] [deployId]',\n description: 'Show or list resumable deploy checkpoints written by `ddt publish`.',\n },\n 'approval-chain': {\n term: 'approval-chain',\n description: 'Signed M-of-N approval workflow (DSR.8).',\n },\n standards: {\n term: 'standards',\n description: 'Team SQL standards — init, check, fix, and explain.',\n },\n perf: {\n term: 'perf',\n description: 'CLI performance diagnostics (cold-start audit, hot-path profiling).',\n },\n 'migrate-platform': {\n term: 'migrate-platform [options] <path>',\n description:\n 'Translate Databricks SQL files to another platform dialect. v1: --to snowflake. Reads .sql files from <path> (file or directory).',\n },\n migrate: {\n term: 'migrate',\n description: 'Migrate from another tool to SDT (`from-dbt` subcommand only in v1).',\n },\n backlog: {\n term: 'backlog',\n description: 'Local-compute backlog tooling. Pure parse + score; no warehouse contact.',\n },\n watch: {\n term: 'watch',\n description:\n 'Platform-feature drift detector. Diffs release-notes markdown against a cached snapshot.',\n },\n bookmarks: {\n term: 'bookmarks [options]',\n description: 'Save fast-access pointers to queries, files, or named sections.',\n },\n snippets: {\n term: 'snippets',\n description: 'Browse the built-in SQL snippet catalog (SCD, star schema, data quality).',\n },\n generate: {\n term: 'generate',\n description: 'Code generation: ingest notebooks, SCD merge scripts, star-schema pipelines.',\n },\n exec: {\n term: 'exec [options] <file>',\n description: 'Run a SQL script on one or more connection profiles in parallel.',\n },\n search: {\n term: 'search [options] <pattern>',\n description: 'Find objects matching a name pattern across one or more connection profiles.',\n },\n 'query-log': {\n term: 'query-log',\n description: 'Browse and manage the local query log from the EE3 query window (AUTH.5).',\n },\n savings: {\n term: 'savings [options]',\n description: 'Show estimated AI token savings from using deterministic DDT surfaces.',\n },\n trial: { term: 'trial', description: 'Manage the DDT 30-day Pro trial (no account required).' },\n pilot: {\n term: 'pilot',\n description: 'Join or check the DDT pilot program (90-day Pro access for early adopters).',\n },\n};\n"],"mappings":"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","names":[]}
|
|
@@ -14,9 +14,14 @@ import path from "path";
|
|
|
14
14
|
import { Command } from "commander";
|
|
15
15
|
import {
|
|
16
16
|
CompareEngine,
|
|
17
|
+
LiveSource,
|
|
17
18
|
PacSource,
|
|
19
|
+
ProjectSource,
|
|
18
20
|
ai,
|
|
19
21
|
compileSlice,
|
|
22
|
+
createConnection,
|
|
23
|
+
getProfile,
|
|
24
|
+
loadProject,
|
|
20
25
|
pac as pacNs,
|
|
21
26
|
renderHtmlReport,
|
|
22
27
|
safety,
|
|
@@ -78,9 +83,56 @@ function makeColorizer(enabled) {
|
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
// src/commands/compare.ts
|
|
86
|
+
async function resolveSource(arg) {
|
|
87
|
+
if (arg.startsWith("databricks://")) {
|
|
88
|
+
const rest = arg.slice("databricks://".length);
|
|
89
|
+
const [profileName, catalog, schema] = rest.split("/");
|
|
90
|
+
if (!profileName) throw new Error(`Invalid databricks URI: ${arg}`);
|
|
91
|
+
const profile = await getProfile(profileName);
|
|
92
|
+
const conn = createConnection(profile);
|
|
93
|
+
return new LiveSource(conn, {
|
|
94
|
+
...catalog ? { catalog } : {},
|
|
95
|
+
...schema ? { schema } : {}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const lower = arg.toLowerCase();
|
|
99
|
+
if (lower.endsWith(".ddtproj")) return new ProjectSource(arg);
|
|
100
|
+
if (lower.endsWith(".ddtpac")) return new PacSource(arg);
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Unrecognized source: ${arg}. Use *.ddtproj, *.ddtpac, or databricks://<profile>[/catalog[/schema]].`
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
async function maybeLoadSliceFromSource(arg) {
|
|
106
|
+
const lower = arg.toLowerCase();
|
|
107
|
+
if (lower.endsWith(".ddtproj")) {
|
|
108
|
+
const loaded = await loadProject(arg);
|
|
109
|
+
if (!loaded.project.slice) return void 0;
|
|
110
|
+
return compileSlice(loaded.project.slice);
|
|
111
|
+
}
|
|
112
|
+
if (lower.endsWith(".ddtpac")) {
|
|
113
|
+
const srcPac = await pacNs.readPac(arg);
|
|
114
|
+
if (srcPac.manifest.slice) return compileSlice(srcPac.manifest.slice);
|
|
115
|
+
}
|
|
116
|
+
return void 0;
|
|
117
|
+
}
|
|
118
|
+
function compareHistoryRoot(sourceArg) {
|
|
119
|
+
const lower = sourceArg.toLowerCase();
|
|
120
|
+
if (lower.endsWith(".ddtproj") || lower.endsWith(".ddtpac")) {
|
|
121
|
+
return path.dirname(path.resolve(sourceArg));
|
|
122
|
+
}
|
|
123
|
+
return process.cwd();
|
|
124
|
+
}
|
|
81
125
|
function compareCommand() {
|
|
82
126
|
const cmd = new Command("compare");
|
|
83
|
-
cmd.description(
|
|
127
|
+
cmd.description(
|
|
128
|
+
"Compare two schemas (the desired state vs the current state). Each side may be a .ddtproj, a .ddtpac, or databricks://<profile>[/catalog[/schema]]."
|
|
129
|
+
).requiredOption(
|
|
130
|
+
"--source <ref>",
|
|
131
|
+
"Source / desired state: .ddtproj, .ddtpac, or databricks://<profile>[/catalog[/schema]]."
|
|
132
|
+
).requiredOption(
|
|
133
|
+
"--target <ref>",
|
|
134
|
+
"Target / current state: .ddtproj, .ddtpac, or databricks://<profile>[/catalog[/schema]]."
|
|
135
|
+
).option("--ignore-case", "Compare object FQNs case-insensitively.", false).option(
|
|
84
136
|
"--json",
|
|
85
137
|
"Emit a JSON CompareResult instead of human-readable output. (Alias for --format json.)",
|
|
86
138
|
false
|
|
@@ -118,13 +170,9 @@ function compareCommand() {
|
|
|
118
170
|
cmd.action(async (opts) => {
|
|
119
171
|
const nameMapping = await buildMappingFromOptions(opts);
|
|
120
172
|
const engine = new CompareEngine();
|
|
121
|
-
const source =
|
|
122
|
-
const target =
|
|
123
|
-
|
|
124
|
-
if (opts.slice !== false) {
|
|
125
|
-
const srcPac = await pacNs.readPac(String(opts.source));
|
|
126
|
-
if (srcPac.manifest.slice) slice = compileSlice(srcPac.manifest.slice);
|
|
127
|
-
}
|
|
173
|
+
const source = await resolveSource(String(opts.source));
|
|
174
|
+
const target = await resolveSource(String(opts.target));
|
|
175
|
+
const slice = opts.slice === false ? void 0 : await maybeLoadSliceFromSource(String(opts.source));
|
|
128
176
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
129
177
|
const result = await engine.compare(source, target, {
|
|
130
178
|
ignoreCase: !!opts.ignoreCase,
|
|
@@ -136,7 +184,7 @@ function compareCommand() {
|
|
|
136
184
|
try {
|
|
137
185
|
const histAssessment = safety.assess(result);
|
|
138
186
|
const changed = result.summary.added + result.summary.removed + result.summary.modified;
|
|
139
|
-
await writeCompareHistory(
|
|
187
|
+
await writeCompareHistory(compareHistoryRoot(String(opts.source)), {
|
|
140
188
|
startedAt,
|
|
141
189
|
finishedAt,
|
|
142
190
|
durationMs: Date.parse(finishedAt) - Date.parse(startedAt),
|
|
@@ -232,7 +280,8 @@ function compareCommand() {
|
|
|
232
280
|
if (opts.writeImpact !== void 0) {
|
|
233
281
|
await writeImpactJson(
|
|
234
282
|
result,
|
|
235
|
-
opts.writeImpact === true ? void 0 : String(opts.writeImpact)
|
|
283
|
+
opts.writeImpact === true ? void 0 : String(opts.writeImpact),
|
|
284
|
+
String(opts.source)
|
|
236
285
|
);
|
|
237
286
|
}
|
|
238
287
|
if (opts.typeSafe) {
|
|
@@ -286,7 +335,7 @@ function compareCommand() {
|
|
|
286
335
|
]);
|
|
287
336
|
return cmd;
|
|
288
337
|
}
|
|
289
|
-
async function writeImpactJson(result, explicitPath) {
|
|
338
|
+
async function writeImpactJson(result, explicitPath, sourceArg) {
|
|
290
339
|
const findings = typecheck.analyzeImpact(result);
|
|
291
340
|
const summary = typecheck.summarizeImpact(findings);
|
|
292
341
|
const file = {
|
|
@@ -297,13 +346,20 @@ async function writeImpactJson(result, explicitPath) {
|
|
|
297
346
|
findings,
|
|
298
347
|
summary
|
|
299
348
|
};
|
|
300
|
-
const outPath = explicitPath ? path.resolve(explicitPath) :
|
|
349
|
+
const outPath = explicitPath ? path.resolve(explicitPath) : defaultImpactPath(sourceArg);
|
|
301
350
|
await fs.mkdir(path.dirname(outPath), { recursive: true });
|
|
302
351
|
await fs.writeFile(outPath, typecheck.serializeImpactFile(file));
|
|
303
352
|
console.log(
|
|
304
353
|
`Wrote ${outPath} \u2014 ${summary.findingsCount} finding(s), ${summary.errors} error / ${summary.warnings} warning ripple(s).`
|
|
305
354
|
);
|
|
306
355
|
}
|
|
356
|
+
function defaultImpactPath(sourceArg) {
|
|
357
|
+
const lower = sourceArg.toLowerCase();
|
|
358
|
+
if (lower.endsWith(".ddtproj") || lower.endsWith(".ddtpac")) {
|
|
359
|
+
return path.resolve(path.dirname(sourceArg), ".ddt", "impact.json");
|
|
360
|
+
}
|
|
361
|
+
return path.resolve(".ddt", "impact.json");
|
|
362
|
+
}
|
|
307
363
|
var SYSTEM_PROMPT = `You are a senior Databricks Unity Catalog DBA reviewing a schema diff. Your job is to narrate the changes in plain English to a teammate who hasn't seen the underlying SQL. For each change, briefly say:
|
|
308
364
|
- what it is (e.g. "a new fact table is added")
|
|
309
365
|
- why a reasonable engineer might do this (the intent)
|
|
@@ -376,4 +432,4 @@ export {
|
|
|
376
432
|
buildExplainPrompt,
|
|
377
433
|
compareCommand
|
|
378
434
|
};
|
|
379
|
-
//# sourceMappingURL=compare-
|
|
435
|
+
//# sourceMappingURL=compare-IOEATL6G.js.map
|