@sdt-tools/cli 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ var COMMAND_MANIFEST = {
20
20
  build: { term: "build [options]", description: "Build a .sdtpac from a .sdtproj project." },
21
21
  publish: {
22
22
  term: "publish [options]",
23
- description: "Compare a .sdtpac to a live Snowflake target and apply (or dry-run) the migration."
23
+ description: "Compare a .sdtpac (the desired state) to a live Snowflake target and apply (or dry-run) the migration. Shared form with `ddt publish`: `--source <desired> --connection <live-target>`."
24
24
  },
25
25
  compare: {
26
26
  term: "compare [options] [source] [target]",
@@ -43,6 +43,10 @@ var COMMAND_MANIFEST = {
43
43
  term: "import [options]",
44
44
  description: "Convert artifacts from other tools into an SDT project."
45
45
  },
46
+ "import-script": {
47
+ term: "import-script [options]",
48
+ description: "Parse a SQL script and write each DDL statement into the .sdtproj tree under its canonical folder."
49
+ },
46
50
  format: {
47
51
  term: "format [options] [files...]",
48
52
  description: "Format SQL files using the tokenizer-based v2 engine (refuse-on-invalid, idempotent, token-faithful)."
@@ -375,19 +379,20 @@ function defaultOutputStyle() {
375
379
  if (env && VALID_OUTPUT_STYLES.has(env)) return env;
376
380
  return "standard";
377
381
  }
378
- var CLI_VERSION = "0.2.5";
382
+ var CLI_VERSION = "0.2.6";
379
383
  globalThis.__SDT_START_NS__ ??= process.hrtime.bigint() - BigInt(Math.round(performance.now() * 1e6));
380
384
  var COMMAND_LOADERS = {
381
385
  init: async () => (await import("./init-SWRRJMGI.js")).initCommand(),
382
386
  extract: async () => (await import("./extract-VMMVRQVT.js")).extractCommand(),
383
387
  build: async () => (await import("./build-VNIQFKSP.js")).buildCommand(),
384
- publish: async () => (await import("./publish-Y2J56K4Y.js")).publishCommand(),
388
+ publish: async () => (await import("./publish-UMVIWH6H.js")).publishCommand(),
385
389
  compare: async () => (await import("./compare-5O6UTWPJ.js")).compareCommand(),
386
390
  drift: async () => (await import("./drift-XDA3BDYN.js")).driftCommand(),
387
391
  validate: async () => (await import("./validate-T6D2WCOK.js")).validateCommand(),
388
- connection: async () => (await import("./connection-SYTH4V53.js")).connectionCommand(),
392
+ connection: async () => (await import("./connection-GNTZDHXF.js")).connectionCommand(),
389
393
  refactor: async () => (await import("./refactor-LTZQLJ35.js")).refactorCommand(),
390
394
  import: async () => (await import("./import-AELYLY6A.js")).importCommand(),
395
+ "import-script": async () => (await import("./import-script-2OF5BI6A.js")).importScriptCommand(),
391
396
  format: async () => (await import("./format-TRLWLMGS.js")).formatCommand(),
392
397
  completion: async () => (await import("./completion-I5U5VVAX.js")).completionCommand(),
393
398
  telemetry: async () => (await import("./telemetry-3U2QLA2S.js")).telemetryCommand(),
@@ -397,7 +402,7 @@ var COMMAND_LOADERS = {
397
402
  suite: async () => (await import("./suite-TRNGZWQM.js")).suiteCommand(),
398
403
  docs: async () => (await import("./docs-CVRKGUSW.js")).docsCommand(),
399
404
  erd: async () => (await import("./docs-CVRKGUSW.js")).erdCommand(),
400
- mcp: async () => (await import("./mcp-3QI4TH4N.js")).mcpCommand(),
405
+ mcp: async () => (await import("./mcp-SARDMCDV.js")).mcpCommand(),
401
406
  ai: async () => (await import("./ai-G4MJWHTM.js")).aiCommand(),
402
407
  explain: async () => (await import("./explain-LWKJOTL7.js")).explainCommand(),
403
408
  feedback: async () => (await import("./feedback-M7DM2EQC.js")).feedbackCommand(),
@@ -520,12 +525,12 @@ async function main() {
520
525
  );
521
526
  program.hook("preAction", async (_thisCommand, actionCommand) => {
522
527
  if (actionCommand.parent !== program) return;
523
- const reporting = await import("./errorReporting-ZRNJ3VW7.js");
528
+ const reporting = await import("./errorReporting-AQXKKGZH.js");
524
529
  await reporting.setupErrorReporting(actionCommand.name());
525
530
  });
526
531
  program.hook("postAction", async (_thisCommand, actionCommand) => {
527
532
  if (actionCommand.parent !== program) return;
528
- const reporting = await import("./errorReporting-ZRNJ3VW7.js");
533
+ const reporting = await import("./errorReporting-AQXKKGZH.js");
529
534
  await reporting.finishErrorReporting(CLI_VERSION);
530
535
  });
531
536
  program.hook("postAction", async (_thisCommand, actionCommand) => {
@@ -558,7 +563,7 @@ if (process.env["SDT_CLI_NO_MAIN"] !== "1") {
558
563
  logger.error(err instanceof Error ? err.message : String(err));
559
564
  process.exitCode = 1;
560
565
  try {
561
- const reporting = await import("./errorReporting-ZRNJ3VW7.js");
566
+ const reporting = await import("./errorReporting-AQXKKGZH.js");
562
567
  await reporting.reportCliFailure(err, CLI_VERSION);
563
568
  } catch {
564
569
  }
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 * `sdt` command entry point.\n *\n * Subcommand modules are loaded LAZILY: only the requested subcommand's\n * module (and its `@sdt-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: `sdt <known-cmd> ...` skips ~80 command-module loads\n * and their per-module `@sdt-tools/core/...` imports. Reasoning in\n * docs/BACKLOG.md COLD cluster + the 200 ms cold-start standing bar.\n */\nimport { Command, Help } from 'commander';\nimport { logger } from './util/logger.js';\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// `@sdt-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 (`@sdt-tools/core`)\n// is still never imported — subpath / dynamic only (RH3.3 pin).\nimport type { OutputStyle } from '@sdt-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 * `@sdt-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 `SDT_OUTPUT_STYLE`. Kept in lockstep with\n * core/outputStyle/style.ts `resolveOutputStyle`.\n */\nfunction defaultOutputStyle(): OutputStyle {\n const env = process.env['SDT_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 `sdt 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 { __SDT_START_NS__?: bigint }).__SDT_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 `sdt <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 init: async () => (await import('./commands/init.js')).initCommand(),\n extract: async () => (await import('./commands/extract.js')).extractCommand(),\n build: async () => (await import('./commands/build.js')).buildCommand(),\n publish: async () => (await import('./commands/publish.js')).publishCommand(),\n compare: async () => (await import('./commands/compare.js')).compareCommand(),\n drift: async () => (await import('./commands/drift.js')).driftCommand(),\n validate: async () => (await import('./commands/validate.js')).validateCommand(),\n connection: async () => (await import('./commands/connection.js')).connectionCommand(),\n refactor: async () => (await import('./commands/refactor.js')).refactorCommand(),\n import: async () => (await import('./commands/import.js')).importCommand(),\n format: async () => (await import('./commands/format.js')).formatCommand(),\n completion: async () => (await import('./commands/completion.js')).completionCommand(),\n telemetry: async () => (await import('./commands/telemetry.js')).telemetryCommand(),\n license: async () => (await import('./commands/license.js')).licenseCommand(),\n trial: async () => (await import('./commands/trial.js')).trialCommand(),\n pilot: async () => (await import('./commands/pilot.js')).pilotCommand(),\n suite: async () => (await import('./commands/suite.js')).suiteCommand(),\n docs: async () => (await import('./commands/docs.js')).docsCommand(),\n erd: async () => (await import('./commands/docs.js')).erdCommand(),\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 lint: async () => (await import('./commands/lint.js')).lintCommand(),\n features: async () => (await import('./commands/features.js')).featuresCommand(),\n hosts: async () => (await import('./commands/hosts.js')).hostsCommand(),\n 'install-hooks': async () => (await import('./commands/install-hooks.js')).installHooksCommand(),\n history: async () => (await import('./commands/history.js')).historyCommand(),\n 'audit-log': async () => (await import('./commands/audit-log.js')).auditLogCommand(),\n verify: async () => (await import('./commands/verify.js')).verifyCommand(),\n graph: async () => (await import('./commands/graph.js')).graphCommand(),\n script: async () => (await import('./commands/script.js')).scriptCommand(),\n revert: async () => (await import('./commands/revert.js')).revertCommand(),\n snapshot: async () => (await import('./commands/snapshot.js')).snapshotCommand(),\n seed: async () => (await import('./commands/seed.js')).seedCommand(),\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 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 export: async () => (await import('./commands/export.js')).exportCommand(),\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};\n\nasync function main(): Promise<void> {\n // RH4.2 cold-start fast path: `sdt -v` / `sdt --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('sdt')\n .description('Snowflake Data Tools — declarative schema management for Snowflake.')\n .version(CLI_VERSION, '-v, --version')\n .option(\n '--style <mode>',\n 'Output style: standard | audit | ci | review | terse. Also reads SDT_OUTPUT_STYLE env var.',\n defaultOutputStyle(),\n )\n .option('--explain-features', 'After each command, show related features from the catalog.');\n\n // Decide whether to load all commands or just the requested one. The\n // \"explicit known command\" path is the cold-start win — every other\n // path needs the full subcommand list registered so Commander can\n // render --help or emit the standard \"unknown command\" error.\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 // `compare [options] <source> <target>`) so the --help columns are\n // byte-identical to the load-everything path. Per-command help\n // (`sdt <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 (`sdt\n // 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 `sdt explain allowDropTable` for safety + path detail\n // without leaving the terminal. Mirrors the DDT-side footer.\n program.addHelpText('afterAll', () =>\n [\n '',\n 'Options catalog:',\n ' Every CLI flag and `.sdtproj` option has a searchable entry with safety',\n ' tier, default, related options, and an example. Look one up with:',\n ' sdt explain <name> # e.g. sdt explain allowDropTable',\n ' sdt explain <topic> # fuzzy: \"drop\", \"safety\", \"compare\"',\n '',\n 'Features catalog (locked + unlocked):',\n ' sdt features list # what ships in each tier',\n ' sdt features show <id>',\n '',\n 'Personalized suggestions:',\n ' sdt 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 SDT_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 // Only hint for direct sdt subcommands, not nested subcommands.\n if (actionCommand.parent !== program) return;\n const { FeatureAdvisor, SDT_HINT_RULES } = await import('@sdt-tools/core/discovery');\n const sdtAdvisor = new FeatureAdvisor('sdt', SDT_HINT_RULES);\n const tip = sdtAdvisor.advise(actionCommand.name());\n if (tip) {\n console.log(chalk.dim(`\\n ✦ ${tip}`));\n console.log(chalk.dim(' sdt discover · sdt 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('@sdt-tools/core/features');\n const related = featuresNs.pickRelatedFeatures(\n featuresNs.SDT_FEATURE_CATALOG,\n cmdName,\n 3,\n 'sdt',\n );\n const hint = featuresNs.renderRelatedFeaturesHint(related, cmdName, 'sdt');\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['SDT_CLI_NO_MAIN'] !== '1') {\n main().catch(async (err: unknown) => {\n logger.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 * `@sdt-tools/core/...` dependency chains) off disk on a path that never\n * executes a command — the dominant cost of `sdt --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.\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 init: {\n term: 'init [options]',\n description: 'Initialize a new SDT project in the current directory.',\n },\n extract: {\n term: 'extract [options]',\n description: 'Extract a Snowflake account/database/schema into a project layout.',\n },\n build: { term: 'build [options]', description: 'Build a .sdtpac from a .sdtproj project.' },\n publish: {\n term: 'publish [options]',\n description:\n 'Compare a .sdtpac to a live Snowflake target and apply (or dry-run) the migration.',\n },\n compare: {\n term: 'compare [options] [source] [target]',\n description:\n 'Compare two schemas. Sources may be .sdtproj, .sdtpac, or snowflake://<profile>[/db[/schema]].',\n },\n drift: {\n term: 'drift [options]',\n description:\n 'Check whether a live Snowflake target has drifted from the project pac or a dbt manifest.',\n },\n validate: {\n term: 'validate [options]',\n description:\n 'Validate a .sdtproj — schema check; optionally resolve every object reference (--references).',\n },\n connection: { term: 'connection', description: 'Manage Snowflake connection profiles.' },\n refactor: {\n term: 'refactor',\n description: 'Record refactor operations (renames, moves) so compare emits ALTER … RENAME.',\n },\n import: {\n term: 'import [options]',\n description: 'Convert artifacts from other tools into an SDT project.',\n },\n format: {\n term: 'format [options] [files...]',\n description:\n 'Format SQL files using the tokenizer-based v2 engine (refuse-on-invalid, idempotent, token-faithful).',\n },\n completion: {\n term: 'completion <shell>',\n description: 'Print shell completion script (bash, zsh, fish, powershell).',\n },\n telemetry: {\n term: 'telemetry',\n description: 'Control opt-in usage telemetry and automatic error reporting.',\n },\n license: {\n term: 'license',\n description: 'Manage the SDT license key (open-core, offline, warn-mode in v0.1).',\n },\n trial: { term: 'trial', description: 'Manage the SDT 30-day Pro trial (no account required).' },\n pilot: {\n term: 'pilot',\n description: 'Join or check the SDT pilot program (90-day Pro access for early adopters).',\n },\n suite: {\n term: 'suite',\n description: 'Manage a .sdtsuite — a collection of .sdtproj projects deploying together.',\n },\n docs: {\n term: 'docs [options]',\n description: 'Generate HTML schema docs from a .sdtproj or .sdtpac.',\n },\n erd: {\n term: 'erd [options]',\n description:\n 'Generate an ER diagram (Mermaid Markdown or interactive 3D HTML) from a .sdtproj or .sdtpac.',\n },\n mcp: {\n term: 'mcp',\n description:\n 'Start the SDT 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 SDT team.',\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 features: {\n term: 'features',\n description:\n 'Browse SDT 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 SDT plugs into — CLI, VS Code, MCP agents, GitHub Actions, dbt, Airflow, etc. Shows supported versions and the host-specific tailoring notes.',\n },\n 'install-hooks': {\n term: 'install-hooks [options]',\n description:\n 'Install a git pre-commit hook that runs `sdt validate` + `sdt format --check` before each commit.',\n },\n history: {\n term: 'history [options]',\n description:\n 'List deploy manifests (default) or query the live Snowflake QUERY_HISTORY views 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 verify: {\n term: 'verify [options]',\n description: 'Recompute checksums on a .sdtpac and confirm every object matches the manifest.',\n },\n graph: {\n term: 'graph [options]',\n description: 'Build an object-dependency DAG and emit it as Mermaid or DOT.',\n },\n script: {\n term: 'script [options]',\n description:\n 'Generate a deploy SQL script for source → target. Always offline — does not touch the account.',\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 `sdt publish --apply`.',\n },\n seed: {\n term: 'seed',\n description:\n 'Reference / dimension data seeds. Declare static rows next to DDL; engine generates MERGEs.',\n },\n lineage: {\n term: 'lineage [options]',\n description: 'Extract data-flow lineage from a .sdtproj, .sdtpac, 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 Snowflake-credit 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 MASKING POLICY 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 via Snowflake zero-copy clone. create / drop / list.',\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 — SDT 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 safety: {\n term: 'safety',\n description:\n 'Inspect the safety-finding catalog. See `sdt safety list` and `sdt safety explain <code>`.',\n },\n pii: {\n term: 'pii',\n description:\n 'Detect PII columns + render Snowflake MASKING POLICY DDL. See `sdt pii scan` and `sdt 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 Snowflake account.',\n },\n 'drift-gate': {\n term: 'drift-gate [options]',\n description:\n 'Refuse-on-drift CI gate across multiple replica Snowflake accounts. 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 SDT 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 (sdt ai status).',\n },\n sketch: {\n term: 'sketch [options] <kind>',\n description:\n 'AI-assist: scaffold idiomatic Snowflake 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 (clustering, narrowing, missing PKs, dynamic-table lag).',\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 (.sdt/compare-profiles.json).',\n },\n explorer: {\n term: 'explorer [options]',\n description:\n 'ASCII tree dump of the cached catalog for a connection. Run `sdt 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 (Snowflake ↔ Databricks). 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 `sdt profile`) and emits suggestions with confidence tiers + rationale.',\n },\n export: {\n term: 'export',\n description: 'Export an SDT project to another format (DCM, etc.). v1 supports `dcm` only.',\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 — relax with --allow-* flags.',\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 the dynamic tables + tasks in the project. Operator runs the output script 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 SDT 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 `sdt 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 Snowflake SQL files to another platform dialect. v1: --to databricks. 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 SDT surfaces.',\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 * `sdt` command entry point.\n *\n * Subcommand modules are loaded LAZILY: only the requested subcommand's\n * module (and its `@sdt-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: `sdt <known-cmd> ...` skips ~80 command-module loads\n * and their per-module `@sdt-tools/core/...` imports. Reasoning in\n * docs/BACKLOG.md COLD cluster + the 200 ms cold-start standing bar.\n */\nimport { Command, Help } from 'commander';\nimport { logger } from './util/logger.js';\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// `@sdt-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 (`@sdt-tools/core`)\n// is still never imported — subpath / dynamic only (RH3.3 pin).\nimport type { OutputStyle } from '@sdt-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 * `@sdt-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 `SDT_OUTPUT_STYLE`. Kept in lockstep with\n * core/outputStyle/style.ts `resolveOutputStyle`.\n */\nfunction defaultOutputStyle(): OutputStyle {\n const env = process.env['SDT_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.6';\n\n// Cold-start timestamp for `sdt 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 { __SDT_START_NS__?: bigint }).__SDT_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 `sdt <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 init: async () => (await import('./commands/init.js')).initCommand(),\n extract: async () => (await import('./commands/extract.js')).extractCommand(),\n build: async () => (await import('./commands/build.js')).buildCommand(),\n publish: async () => (await import('./commands/publish.js')).publishCommand(),\n compare: async () => (await import('./commands/compare.js')).compareCommand(),\n drift: async () => (await import('./commands/drift.js')).driftCommand(),\n validate: async () => (await import('./commands/validate.js')).validateCommand(),\n connection: async () => (await import('./commands/connection.js')).connectionCommand(),\n refactor: async () => (await import('./commands/refactor.js')).refactorCommand(),\n import: async () => (await import('./commands/import.js')).importCommand(),\n 'import-script': async () => (await import('./commands/import-script.js')).importScriptCommand(),\n format: async () => (await import('./commands/format.js')).formatCommand(),\n completion: async () => (await import('./commands/completion.js')).completionCommand(),\n telemetry: async () => (await import('./commands/telemetry.js')).telemetryCommand(),\n license: async () => (await import('./commands/license.js')).licenseCommand(),\n trial: async () => (await import('./commands/trial.js')).trialCommand(),\n pilot: async () => (await import('./commands/pilot.js')).pilotCommand(),\n suite: async () => (await import('./commands/suite.js')).suiteCommand(),\n docs: async () => (await import('./commands/docs.js')).docsCommand(),\n erd: async () => (await import('./commands/docs.js')).erdCommand(),\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 lint: async () => (await import('./commands/lint.js')).lintCommand(),\n features: async () => (await import('./commands/features.js')).featuresCommand(),\n hosts: async () => (await import('./commands/hosts.js')).hostsCommand(),\n 'install-hooks': async () => (await import('./commands/install-hooks.js')).installHooksCommand(),\n history: async () => (await import('./commands/history.js')).historyCommand(),\n 'audit-log': async () => (await import('./commands/audit-log.js')).auditLogCommand(),\n verify: async () => (await import('./commands/verify.js')).verifyCommand(),\n graph: async () => (await import('./commands/graph.js')).graphCommand(),\n script: async () => (await import('./commands/script.js')).scriptCommand(),\n revert: async () => (await import('./commands/revert.js')).revertCommand(),\n snapshot: async () => (await import('./commands/snapshot.js')).snapshotCommand(),\n seed: async () => (await import('./commands/seed.js')).seedCommand(),\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 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 export: async () => (await import('./commands/export.js')).exportCommand(),\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};\n\nasync function main(): Promise<void> {\n // RH4.2 cold-start fast path: `sdt -v` / `sdt --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('sdt')\n .description('Snowflake Data Tools — declarative schema management for Snowflake.')\n .version(CLI_VERSION, '-v, --version')\n .option(\n '--style <mode>',\n 'Output style: standard | audit | ci | review | terse. Also reads SDT_OUTPUT_STYLE env var.',\n defaultOutputStyle(),\n )\n .option('--explain-features', 'After each command, show related features from the catalog.');\n\n // Decide whether to load all commands or just the requested one. The\n // \"explicit known command\" path is the cold-start win — every other\n // path needs the full subcommand list registered so Commander can\n // render --help or emit the standard \"unknown command\" error.\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 // `compare [options] <source> <target>`) so the --help columns are\n // byte-identical to the load-everything path. Per-command help\n // (`sdt <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 (`sdt\n // 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 `sdt explain allowDropTable` for safety + path detail\n // without leaving the terminal. Mirrors the DDT-side footer.\n program.addHelpText('afterAll', () =>\n [\n '',\n 'Options catalog:',\n ' Every CLI flag and `.sdtproj` option has a searchable entry with safety',\n ' tier, default, related options, and an example. Look one up with:',\n ' sdt explain <name> # e.g. sdt explain allowDropTable',\n ' sdt explain <topic> # fuzzy: \"drop\", \"safety\", \"compare\"',\n '',\n 'Features catalog (locked + unlocked):',\n ' sdt features list # what ships in each tier',\n ' sdt features show <id>',\n '',\n 'Personalized suggestions:',\n ' sdt 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 SDT_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 // Only hint for direct sdt subcommands, not nested subcommands.\n if (actionCommand.parent !== program) return;\n const { FeatureAdvisor, SDT_HINT_RULES } = await import('@sdt-tools/core/discovery');\n const sdtAdvisor = new FeatureAdvisor('sdt', SDT_HINT_RULES);\n const tip = sdtAdvisor.advise(actionCommand.name());\n if (tip) {\n console.log(chalk.dim(`\\n ✦ ${tip}`));\n console.log(chalk.dim(' sdt discover · sdt 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('@sdt-tools/core/features');\n const related = featuresNs.pickRelatedFeatures(\n featuresNs.SDT_FEATURE_CATALOG,\n cmdName,\n 3,\n 'sdt',\n );\n const hint = featuresNs.renderRelatedFeaturesHint(related, cmdName, 'sdt');\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['SDT_CLI_NO_MAIN'] !== '1') {\n main().catch(async (err: unknown) => {\n logger.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 * `@sdt-tools/core/...` dependency chains) off disk on a path that never\n * executes a command — the dominant cost of `sdt --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.\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 init: {\n term: 'init [options]',\n description: 'Initialize a new SDT project in the current directory.',\n },\n extract: {\n term: 'extract [options]',\n description: 'Extract a Snowflake account/database/schema into a project layout.',\n },\n build: { term: 'build [options]', description: 'Build a .sdtpac from a .sdtproj project.' },\n publish: {\n term: 'publish [options]',\n description:\n 'Compare a .sdtpac (the desired state) to a live Snowflake target and apply (or dry-run) the migration. Shared form with `ddt publish`: `--source <desired> --connection <live-target>`.',\n },\n compare: {\n term: 'compare [options] [source] [target]',\n description:\n 'Compare two schemas. Sources may be .sdtproj, .sdtpac, or snowflake://<profile>[/db[/schema]].',\n },\n drift: {\n term: 'drift [options]',\n description:\n 'Check whether a live Snowflake target has drifted from the project pac or a dbt manifest.',\n },\n validate: {\n term: 'validate [options]',\n description:\n 'Validate a .sdtproj — schema check; optionally resolve every object reference (--references).',\n },\n connection: { term: 'connection', description: 'Manage Snowflake connection profiles.' },\n refactor: {\n term: 'refactor',\n description: 'Record refactor operations (renames, moves) so compare emits ALTER … RENAME.',\n },\n import: {\n term: 'import [options]',\n description: 'Convert artifacts from other tools into an SDT project.',\n },\n 'import-script': {\n term: 'import-script [options]',\n description:\n 'Parse a SQL script and write each DDL statement into the .sdtproj tree under its canonical folder.',\n },\n format: {\n term: 'format [options] [files...]',\n description:\n 'Format SQL files using the tokenizer-based v2 engine (refuse-on-invalid, idempotent, token-faithful).',\n },\n completion: {\n term: 'completion <shell>',\n description: 'Print shell completion script (bash, zsh, fish, powershell).',\n },\n telemetry: {\n term: 'telemetry',\n description: 'Control opt-in usage telemetry and automatic error reporting.',\n },\n license: {\n term: 'license',\n description: 'Manage the SDT license key (open-core, offline, warn-mode in v0.1).',\n },\n trial: { term: 'trial', description: 'Manage the SDT 30-day Pro trial (no account required).' },\n pilot: {\n term: 'pilot',\n description: 'Join or check the SDT pilot program (90-day Pro access for early adopters).',\n },\n suite: {\n term: 'suite',\n description: 'Manage a .sdtsuite — a collection of .sdtproj projects deploying together.',\n },\n docs: {\n term: 'docs [options]',\n description: 'Generate HTML schema docs from a .sdtproj or .sdtpac.',\n },\n erd: {\n term: 'erd [options]',\n description:\n 'Generate an ER diagram (Mermaid Markdown or interactive 3D HTML) from a .sdtproj or .sdtpac.',\n },\n mcp: {\n term: 'mcp',\n description:\n 'Start the SDT 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 SDT team.',\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 features: {\n term: 'features',\n description:\n 'Browse SDT 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 SDT plugs into — CLI, VS Code, MCP agents, GitHub Actions, dbt, Airflow, etc. Shows supported versions and the host-specific tailoring notes.',\n },\n 'install-hooks': {\n term: 'install-hooks [options]',\n description:\n 'Install a git pre-commit hook that runs `sdt validate` + `sdt format --check` before each commit.',\n },\n history: {\n term: 'history [options]',\n description:\n 'List deploy manifests (default) or query the live Snowflake QUERY_HISTORY views 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 verify: {\n term: 'verify [options]',\n description: 'Recompute checksums on a .sdtpac and confirm every object matches the manifest.',\n },\n graph: {\n term: 'graph [options]',\n description: 'Build an object-dependency DAG and emit it as Mermaid or DOT.',\n },\n script: {\n term: 'script [options]',\n description:\n 'Generate a deploy SQL script for source → target. Always offline — does not touch the account.',\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 `sdt publish --apply`.',\n },\n seed: {\n term: 'seed',\n description:\n 'Reference / dimension data seeds. Declare static rows next to DDL; engine generates MERGEs.',\n },\n lineage: {\n term: 'lineage [options]',\n description: 'Extract data-flow lineage from a .sdtproj, .sdtpac, 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 Snowflake-credit 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 MASKING POLICY 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 via Snowflake zero-copy clone. create / drop / list.',\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 — SDT 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 safety: {\n term: 'safety',\n description:\n 'Inspect the safety-finding catalog. See `sdt safety list` and `sdt safety explain <code>`.',\n },\n pii: {\n term: 'pii',\n description:\n 'Detect PII columns + render Snowflake MASKING POLICY DDL. See `sdt pii scan` and `sdt 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 Snowflake account.',\n },\n 'drift-gate': {\n term: 'drift-gate [options]',\n description:\n 'Refuse-on-drift CI gate across multiple replica Snowflake accounts. 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 SDT 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 (sdt ai status).',\n },\n sketch: {\n term: 'sketch [options] <kind>',\n description:\n 'AI-assist: scaffold idiomatic Snowflake 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 (clustering, narrowing, missing PKs, dynamic-table lag).',\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 (.sdt/compare-profiles.json).',\n },\n explorer: {\n term: 'explorer [options]',\n description:\n 'ASCII tree dump of the cached catalog for a connection. Run `sdt 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 (Snowflake ↔ Databricks). 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 `sdt profile`) and emits suggestions with confidence tiers + rationale.',\n },\n export: {\n term: 'export',\n description: 'Export an SDT project to another format (DCM, etc.). v1 supports `dcm` only.',\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 — relax with --allow-* flags.',\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 the dynamic tables + tasks in the project. Operator runs the output script 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 SDT 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 `sdt 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 Snowflake SQL files to another platform dialect. v1: --to databricks. 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 SDT surfaces.',\n },\n};\n"],"mappings":"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","names":[]}
@@ -87,6 +87,11 @@ function connectionCommand() {
87
87
  await upsertProfile(profile);
88
88
  logger.success(`Saved profile "${profile.name}".`);
89
89
  });
90
+ cmd.command("get <name>").description("Print a profile (secrets are redacted).").action(async (name) => {
91
+ const profile = await getProfile(String(name));
92
+ const redacted = { ...profile, auth: redactAuth(profile.auth) };
93
+ logger.info(JSON.stringify(redacted, null, 2));
94
+ });
90
95
  cmd.command("remove").description("Remove a connection profile.").argument("<name>").action(async (name) => {
91
96
  const ok = await removeProfile(String(name));
92
97
  if (ok) logger.success(`Removed profile "${name}".`);
@@ -104,7 +109,25 @@ function connectionCommand() {
104
109
  });
105
110
  return cmd;
106
111
  }
112
+ function redactAuth(auth) {
113
+ const isPlaceholder = (v) => v.startsWith("env:") || v.startsWith("keyring:");
114
+ switch (auth.method) {
115
+ case "PASSWORD":
116
+ case "MFA":
117
+ return auth.password && !isPlaceholder(auth.password) ? { ...auth, password: "<redacted>" } : auth;
118
+ case "OAUTH":
119
+ return auth.token && !isPlaceholder(auth.token) ? { ...auth, token: "<redacted>" } : auth;
120
+ case "KEY_PAIR":
121
+ return auth.privateKeyPassphrase && !isPlaceholder(auth.privateKeyPassphrase) ? { ...auth, privateKeyPassphrase: "<redacted>" } : auth;
122
+ case "EXTERNAL_BROWSER":
123
+ return auth;
124
+ default: {
125
+ const _exhaustive = auth;
126
+ return _exhaustive;
127
+ }
128
+ }
129
+ }
107
130
  export {
108
131
  connectionCommand
109
132
  };
110
- //# sourceMappingURL=connection-SYTH4V53.js.map
133
+ //# sourceMappingURL=connection-GNTZDHXF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/connection.ts"],"sourcesContent":["import { Command } from 'commander';\nimport {\n getProfile,\n loadProfiles,\n removeProfile,\n SnowflakeConnection,\n upsertProfile,\n type ConnectionProfile,\n type SnowflakeAuth,\n} from '@sdt-tools/core/connection';\nimport { logger } from '../util/logger.js';\n\nexport function connectionCommand(): Command {\n const cmd = new Command('connection');\n cmd.description('Manage Snowflake connection profiles.');\n\n cmd\n .command('list')\n .description('List configured connection profiles.')\n .action(async () => {\n const profiles = await loadProfiles();\n if (!profiles.length) {\n logger.dim('(no profiles configured — run `sdt connection add` to add one)');\n return;\n }\n for (const p of profiles) {\n logger.info(\n ` ${p.name.padEnd(20)} ${p.account.padEnd(28)} ${p.auth.method} as ${p.auth.username}`,\n );\n }\n });\n\n cmd\n .command('add')\n .description('Add or replace a connection profile.')\n .requiredOption('--name <name>', 'Profile name')\n .requiredOption('--account <account>', 'Snowflake account locator (e.g. xy12345.us-east-1)')\n .requiredOption('--user <user>', 'Snowflake username')\n .option(\n '--auth <method>',\n 'Auth method: PASSWORD | KEY_PAIR | OAUTH | EXTERNAL_BROWSER | MFA',\n 'PASSWORD',\n )\n .option('--password <value>', 'Password or env:VAR_NAME placeholder')\n .option('--key <path>', 'Path to RSA private key (for KEY_PAIR auth)')\n .option('--key-passphrase <value>', 'Passphrase or env:VAR_NAME placeholder')\n .option('--role <role>', 'Default role')\n .option('--warehouse <wh>', 'Default warehouse')\n .option('--database <db>', 'Default database')\n .option('--schema <schema>', 'Default schema')\n .action(async (opts) => {\n const auth = String(opts.auth).toUpperCase() as ConnectionProfile['auth']['method'];\n let authBlock: ConnectionProfile['auth'];\n switch (auth) {\n case 'PASSWORD':\n if (!opts.password) throw new Error('--password is required for PASSWORD auth');\n authBlock = {\n method: 'PASSWORD',\n username: String(opts.user),\n password: String(opts.password),\n };\n break;\n case 'KEY_PAIR':\n if (!opts.key) throw new Error('--key is required for KEY_PAIR auth');\n authBlock = {\n method: 'KEY_PAIR',\n username: String(opts.user),\n privateKeyPath: String(opts.key),\n privateKeyPassphrase: opts.keyPassphrase ? String(opts.keyPassphrase) : undefined,\n };\n break;\n case 'OAUTH':\n if (!opts.password)\n throw new Error('--password (token, or env:VAR) is required for OAUTH auth');\n authBlock = {\n method: 'OAUTH',\n username: String(opts.user),\n token: String(opts.password),\n };\n break;\n case 'EXTERNAL_BROWSER':\n authBlock = { method: 'EXTERNAL_BROWSER', username: String(opts.user) };\n break;\n case 'MFA':\n if (!opts.password) throw new Error('--password is required for MFA auth');\n authBlock = {\n method: 'MFA',\n username: String(opts.user),\n password: String(opts.password),\n };\n break;\n default:\n throw new Error(`Unsupported auth method: ${auth}`);\n }\n const profile: ConnectionProfile = {\n name: String(opts.name),\n account: String(opts.account),\n auth: authBlock,\n role: opts.role ? String(opts.role) : undefined,\n warehouse: opts.warehouse ? String(opts.warehouse) : undefined,\n database: opts.database ? String(opts.database) : undefined,\n schema: opts.schema ? String(opts.schema) : undefined,\n };\n await upsertProfile(profile);\n logger.success(`Saved profile \"${profile.name}\".`);\n });\n\n cmd\n .command('get <name>')\n .description('Print a profile (secrets are redacted).')\n .action(async (name) => {\n const profile = await getProfile(String(name));\n const redacted: ConnectionProfile = { ...profile, auth: redactAuth(profile.auth) };\n logger.info(JSON.stringify(redacted, null, 2));\n });\n\n cmd\n .command('remove')\n .description('Remove a connection profile.')\n .argument('<name>')\n .action(async (name) => {\n const ok = await removeProfile(String(name));\n if (ok) logger.success(`Removed profile \"${name}\".`);\n else logger.warn(`No profile named \"${name}\".`);\n });\n\n cmd\n .command('test')\n .description('Test connectivity for a profile.')\n .argument('<name>')\n .action(async (name) => {\n const profile = await getProfile(String(name));\n const conn = new SnowflakeConnection(profile);\n try {\n const result = await conn.test();\n logger.success(`OK — Snowflake ${result.version}`);\n } finally {\n await conn.disconnect();\n }\n });\n\n return cmd;\n}\n\n/**\n * Redact inline secrets for `connection get`. `env:`/`keyring:` placeholders are\n * not secrets (they only name where the value resolves from at runtime), so they\n * are preserved; literal secret values are replaced with `<redacted>`.\n */\nfunction redactAuth(auth: SnowflakeAuth): SnowflakeAuth {\n const isPlaceholder = (v: string): boolean => v.startsWith('env:') || v.startsWith('keyring:');\n switch (auth.method) {\n case 'PASSWORD':\n case 'MFA':\n return auth.password && !isPlaceholder(auth.password)\n ? { ...auth, password: '<redacted>' }\n : auth;\n case 'OAUTH':\n return auth.token && !isPlaceholder(auth.token) ? { ...auth, token: '<redacted>' } : auth;\n case 'KEY_PAIR':\n return auth.privateKeyPassphrase && !isPlaceholder(auth.privateKeyPassphrase)\n ? { ...auth, privateKeyPassphrase: '<redacted>' }\n : auth;\n case 'EXTERNAL_BROWSER':\n return auth;\n default: {\n const _exhaustive: never = auth;\n return _exhaustive;\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -60,7 +60,7 @@ function teardownErrorReporting() {
60
60
  function activeConsentForTests() {
61
61
  return activeConsent;
62
62
  }
63
- var BETA_VERSION = "0.2.5";
63
+ var BETA_VERSION = "0.2.6";
64
64
  function shouldPromptFirstRun(consent) {
65
65
  return consent === "unset";
66
66
  }
@@ -106,4 +106,4 @@ export {
106
106
  shouldPromptFirstRun,
107
107
  teardownErrorReporting
108
108
  };
109
- //# sourceMappingURL=errorReporting-ZRNJ3VW7.js.map
109
+ //# sourceMappingURL=errorReporting-AQXKKGZH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/util/errorReporting.ts"],"sourcesContent":["/**\n * CLI error-reporting wiring (ERR.2).\n *\n * Lazily imported from `cli.ts` hooks so the cold-start path pays zero cost\n * until a command actually runs (preAction) or fails (catch handler).\n *\n * Responsibilities:\n * - first-run consent prompt (TTY only, default Yes, one keystroke)\n * - crash-hook installation when consent allows capture\n * - end-of-run drain: spool → `POST /errors` when consent is `on`\n * - manual \"Report this error? [y/N]\" prompt when consent is NOT `on`\n * and a command fails\n *\n * @see @sdt-tools/core/errorReport (capture substrate + consent + transport)\n */\nimport { createInterface } from 'node:readline';\n// Subpath import, NOT the `@sdt-tools/core` barrel — this module runs in the\n// preAction hook of every command; the barrel would drag ~85 core modules in.\nimport * as errorReport from '@sdt-tools/core/errorReport';\nimport { logger } from './logger.js';\n\n/** Commands that must never trigger the consent prompt or auto-drain. */\nconst EXEMPT_COMMANDS = new Set(['telemetry', 'feedback', 'help', 'completion']);\n\nlet activeConsent: errorReport.ErrorReportConsent = 'unset';\nlet uninstallHooks: (() => void) | null = null;\n\n/**\n * preAction hook body. Reads (and on first run, prompts for) consent, then\n * installs crash capture unless the user opted out.\n */\nexport async function setupErrorReporting(commandName: string): Promise<void> {\n if (EXEMPT_COMMANDS.has(commandName)) return;\n const stored = await errorReport.readConsent();\n activeConsent = stored.consent;\n\n // First-run consent prompt — explicit, one keystroke, default Yes.\n // Skipped when not interactive (CI, pipes) so scripted runs never block.\n if (\n shouldPromptFirstRun(stored.consent) &&\n process.stdout.isTTY &&\n process.stdin.isTTY &&\n !isCi()\n ) {\n // Beta install-time messaging — shown ONCE, immediately before the very\n // first consent question (true first run, consent still `unset`).\n printBetaNotice();\n activeConsent = (await promptFirstRunConsent()) ? 'on' : 'off';\n await errorReport.writeConsent(activeConsent === 'on' ? 'on' : 'off');\n }\n\n // Crash capture is installed unless the user said no. Capture is local-only;\n // nothing leaves the machine without `isErrorReportingEnabled` saying so.\n if (activeConsent !== 'off') {\n uninstallHooks = errorReport.installProcessHooks();\n }\n}\n\n/**\n * postAction hook body. Flushes buffered events and, when consent is `on`,\n * drains the spool to the Worker. No-ops fast when there is nothing to send.\n * `transport` is injectable for tests.\n */\nexport async function finishErrorReporting(\n productVersion: string,\n transport: errorReport.TransportOptions = {},\n): Promise<void> {\n await errorReport.flushErrorEvents();\n\n // Anonymous usage ping (opt-in) — gated internally by the SAME consent +\n // env opt-outs as error reporting and throttled to once per 24h. It is\n // awaited here (not detached) so the postAction lifecycle has a\n // deterministic completion point: `sendUsagePing` is self-bounded (3s hard\n // timeout) and never throws, so awaiting it can block command exit by at\n // most that timeout — the same bound the spool drain below already imposes.\n // Detaching it left the send racing process teardown, which both dropped\n // pings in practice and made the wiring untestable without a sleep.\n // `transport.fetchImpl` is threaded through so tests can intercept it.\n await errorReport\n .sendUsagePing({\n product: 'sdt',\n version: productVersion,\n surface: 'cli',\n ...(transport.fetchImpl ? { fetchImpl: transport.fetchImpl } : {}),\n })\n .catch(() => undefined);\n\n if (!errorReport.isErrorReportingEnabled(activeConsent)) return;\n const spooled = await errorReport.listSpooled(transport.dir);\n if (spooled.length === 0) return;\n const result = await errorReport.drainSpool({ productVersion }, transport);\n if (result.sent > 0) {\n logger.dim(` (${result.sent} error report${result.sent === 1 ? '' : 's'} sent — thank you)`);\n }\n}\n\n/**\n * Top-level command-failure handler. Reports the error as `handled` (real\n * crashes go through `uncaughtExceptionMonitor`), then either auto-sends\n * (consent `on`) or offers a one-keystroke manual report.\n * `transport` is injectable for tests.\n */\nexport async function reportCliFailure(\n err: unknown,\n productVersion: string,\n transport: errorReport.TransportOptions = {},\n): Promise<void> {\n errorReport.reportError(err, 'handled', 'cli:main');\n await errorReport.flushErrorEvents(transport.dir);\n\n if (errorReport.isErrorReportingEnabled(activeConsent)) {\n await errorReport.drainSpool({ productVersion }, transport);\n return;\n }\n\n // Manual push path — only when interactive.\n if (!process.stdout.isTTY || !process.stdin.isTTY || isCi()) return;\n const yes = await promptYesNo('Report this error to the SDT team? [y/N] ', false);\n if (!yes) return;\n const result = await errorReport.drainSpool({ productVersion }, transport);\n if (result.sent > 0) logger.dim(' Report sent — thank you.');\n else logger.dim(' Could not reach the error endpoint; the report is queued locally.');\n}\n\n/** Uninstall crash hooks (tests). */\nexport function teardownErrorReporting(): void {\n uninstallHooks?.();\n uninstallHooks = null;\n activeConsent = 'unset';\n}\n\n/** Current consent as seen by the hooks (tests). */\nexport function activeConsentForTests(): errorReport.ErrorReportConsent {\n return activeConsent;\n}\n\n/** SDT version surfaced in the first-run beta notice. */\nconst BETA_VERSION = '0.2.5';\n\n/**\n * Whether the first-run flow (beta notice + consent prompt) should fire.\n * True ONLY on true first run — when consent has never been decided\n * (`unset`). Exported so the \"first run only\" contract is unit-testable\n * without faking a TTY.\n */\nexport function shouldPromptFirstRun(consent: errorReport.ErrorReportConsent): boolean {\n return consent === 'unset';\n}\n\n/**\n * Beta install-time messaging — printed ONCE, on true first run (consent\n * `unset`), immediately before the consent question. Tells the user, at\n * install time: it's a 30-day public beta with all features free; what\n * happens after the beta (core stays free forever, Pro features keep\n * working but show license notices); that AI features are bring-your-own\n * key; and how to report a bug. Plain ASCII box to match CLI output style.\n */\nexport function printBetaNotice(): void {\n const lines = [\n '┌─────────────────────────────────────────────────────────┐',\n `│ SDT ${BETA_VERSION} — Public Beta │`,\n '│ • All features are free during the beta. │',\n '│ • After the beta: core features stay free forever; │',\n '│ Pro features keep working and show license notices. │',\n '│ • AI features use your own API key (never ours). │',\n '│ • Found a bug? Run: sdt feedback \"<what happened>\" │',\n '└─────────────────────────────────────────────────────────┘',\n ];\n for (const line of lines) logger.info(line);\n}\n\nasync function promptFirstRunConsent(): Promise<boolean> {\n logger.info('SDT can report errors automatically (sanitized diagnostics + OS context,');\n logger.info('never your SQL, identifiers, or credentials) so they get fixed fast.');\n logger.info(errorReport.CONSENT_WARNING);\n return promptYesNo('Enable automatic error reporting? [Y/n] ', true);\n}\n\nfunction promptYesNo(question: string, defaultYes: boolean): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(question, (answer) => {\n rl.close();\n const normalized = answer.trim().toLowerCase();\n if (normalized === '') resolve(defaultYes);\n else resolve(normalized === 'y' || normalized === 'yes');\n });\n });\n}\n\nfunction isCi(): boolean {\n return process.env['CI'] === 'true';\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/util/errorReporting.ts"],"sourcesContent":["/**\n * CLI error-reporting wiring (ERR.2).\n *\n * Lazily imported from `cli.ts` hooks so the cold-start path pays zero cost\n * until a command actually runs (preAction) or fails (catch handler).\n *\n * Responsibilities:\n * - first-run consent prompt (TTY only, default Yes, one keystroke)\n * - crash-hook installation when consent allows capture\n * - end-of-run drain: spool → `POST /errors` when consent is `on`\n * - manual \"Report this error? [y/N]\" prompt when consent is NOT `on`\n * and a command fails\n *\n * @see @sdt-tools/core/errorReport (capture substrate + consent + transport)\n */\nimport { createInterface } from 'node:readline';\n// Subpath import, NOT the `@sdt-tools/core` barrel — this module runs in the\n// preAction hook of every command; the barrel would drag ~85 core modules in.\nimport * as errorReport from '@sdt-tools/core/errorReport';\nimport { logger } from './logger.js';\n\n/** Commands that must never trigger the consent prompt or auto-drain. */\nconst EXEMPT_COMMANDS = new Set(['telemetry', 'feedback', 'help', 'completion']);\n\nlet activeConsent: errorReport.ErrorReportConsent = 'unset';\nlet uninstallHooks: (() => void) | null = null;\n\n/**\n * preAction hook body. Reads (and on first run, prompts for) consent, then\n * installs crash capture unless the user opted out.\n */\nexport async function setupErrorReporting(commandName: string): Promise<void> {\n if (EXEMPT_COMMANDS.has(commandName)) return;\n const stored = await errorReport.readConsent();\n activeConsent = stored.consent;\n\n // First-run consent prompt — explicit, one keystroke, default Yes.\n // Skipped when not interactive (CI, pipes) so scripted runs never block.\n if (\n shouldPromptFirstRun(stored.consent) &&\n process.stdout.isTTY &&\n process.stdin.isTTY &&\n !isCi()\n ) {\n // Beta install-time messaging — shown ONCE, immediately before the very\n // first consent question (true first run, consent still `unset`).\n printBetaNotice();\n activeConsent = (await promptFirstRunConsent()) ? 'on' : 'off';\n await errorReport.writeConsent(activeConsent === 'on' ? 'on' : 'off');\n }\n\n // Crash capture is installed unless the user said no. Capture is local-only;\n // nothing leaves the machine without `isErrorReportingEnabled` saying so.\n if (activeConsent !== 'off') {\n uninstallHooks = errorReport.installProcessHooks();\n }\n}\n\n/**\n * postAction hook body. Flushes buffered events and, when consent is `on`,\n * drains the spool to the Worker. No-ops fast when there is nothing to send.\n * `transport` is injectable for tests.\n */\nexport async function finishErrorReporting(\n productVersion: string,\n transport: errorReport.TransportOptions = {},\n): Promise<void> {\n await errorReport.flushErrorEvents();\n\n // Anonymous usage ping (opt-in) — gated internally by the SAME consent +\n // env opt-outs as error reporting and throttled to once per 24h. It is\n // awaited here (not detached) so the postAction lifecycle has a\n // deterministic completion point: `sendUsagePing` is self-bounded (3s hard\n // timeout) and never throws, so awaiting it can block command exit by at\n // most that timeout — the same bound the spool drain below already imposes.\n // Detaching it left the send racing process teardown, which both dropped\n // pings in practice and made the wiring untestable without a sleep.\n // `transport.fetchImpl` is threaded through so tests can intercept it.\n await errorReport\n .sendUsagePing({\n product: 'sdt',\n version: productVersion,\n surface: 'cli',\n ...(transport.fetchImpl ? { fetchImpl: transport.fetchImpl } : {}),\n })\n .catch(() => undefined);\n\n if (!errorReport.isErrorReportingEnabled(activeConsent)) return;\n const spooled = await errorReport.listSpooled(transport.dir);\n if (spooled.length === 0) return;\n const result = await errorReport.drainSpool({ productVersion }, transport);\n if (result.sent > 0) {\n logger.dim(` (${result.sent} error report${result.sent === 1 ? '' : 's'} sent — thank you)`);\n }\n}\n\n/**\n * Top-level command-failure handler. Reports the error as `handled` (real\n * crashes go through `uncaughtExceptionMonitor`), then either auto-sends\n * (consent `on`) or offers a one-keystroke manual report.\n * `transport` is injectable for tests.\n */\nexport async function reportCliFailure(\n err: unknown,\n productVersion: string,\n transport: errorReport.TransportOptions = {},\n): Promise<void> {\n errorReport.reportError(err, 'handled', 'cli:main');\n await errorReport.flushErrorEvents(transport.dir);\n\n if (errorReport.isErrorReportingEnabled(activeConsent)) {\n await errorReport.drainSpool({ productVersion }, transport);\n return;\n }\n\n // Manual push path — only when interactive.\n if (!process.stdout.isTTY || !process.stdin.isTTY || isCi()) return;\n const yes = await promptYesNo('Report this error to the SDT team? [y/N] ', false);\n if (!yes) return;\n const result = await errorReport.drainSpool({ productVersion }, transport);\n if (result.sent > 0) logger.dim(' Report sent — thank you.');\n else logger.dim(' Could not reach the error endpoint; the report is queued locally.');\n}\n\n/** Uninstall crash hooks (tests). */\nexport function teardownErrorReporting(): void {\n uninstallHooks?.();\n uninstallHooks = null;\n activeConsent = 'unset';\n}\n\n/** Current consent as seen by the hooks (tests). */\nexport function activeConsentForTests(): errorReport.ErrorReportConsent {\n return activeConsent;\n}\n\n/** SDT version surfaced in the first-run beta notice. */\nconst BETA_VERSION = '0.2.6';\n\n/**\n * Whether the first-run flow (beta notice + consent prompt) should fire.\n * True ONLY on true first run — when consent has never been decided\n * (`unset`). Exported so the \"first run only\" contract is unit-testable\n * without faking a TTY.\n */\nexport function shouldPromptFirstRun(consent: errorReport.ErrorReportConsent): boolean {\n return consent === 'unset';\n}\n\n/**\n * Beta install-time messaging — printed ONCE, on true first run (consent\n * `unset`), immediately before the consent question. Tells the user, at\n * install time: it's a 30-day public beta with all features free; what\n * happens after the beta (core stays free forever, Pro features keep\n * working but show license notices); that AI features are bring-your-own\n * key; and how to report a bug. Plain ASCII box to match CLI output style.\n */\nexport function printBetaNotice(): void {\n const lines = [\n '┌─────────────────────────────────────────────────────────┐',\n `│ SDT ${BETA_VERSION} — Public Beta │`,\n '│ • All features are free during the beta. │',\n '│ • After the beta: core features stay free forever; │',\n '│ Pro features keep working and show license notices. │',\n '│ • AI features use your own API key (never ours). │',\n '│ • Found a bug? Run: sdt feedback \"<what happened>\" │',\n '└─────────────────────────────────────────────────────────┘',\n ];\n for (const line of lines) logger.info(line);\n}\n\nasync function promptFirstRunConsent(): Promise<boolean> {\n logger.info('SDT can report errors automatically (sanitized diagnostics + OS context,');\n logger.info('never your SQL, identifiers, or credentials) so they get fixed fast.');\n logger.info(errorReport.CONSENT_WARNING);\n return promptYesNo('Enable automatic error reporting? [Y/n] ', true);\n}\n\nfunction promptYesNo(question: string, defaultYes: boolean): Promise<boolean> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(question, (answer) => {\n rl.close();\n const normalized = answer.trim().toLowerCase();\n if (normalized === '') resolve(defaultYes);\n else resolve(normalized === 'y' || normalized === 'yes');\n });\n });\n}\n\nfunction isCi(): boolean {\n return process.env['CI'] === 'true';\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,83 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
3
+ // src/commands/import-script.ts
4
+ import { promises as fs } from "fs";
5
+ import path from "path";
6
+ import { Command } from "commander";
7
+ import {
8
+ importScript,
9
+ loadProject,
10
+ parseScript
11
+ } from "@sdt-tools/core/project";
12
+ function importScriptCommand() {
13
+ const cmd = new Command("import-script");
14
+ cmd.description(
15
+ "Parse a SQL script and write each DDL statement into the .sdtproj tree under its canonical folder."
16
+ ).requiredOption("--script <path>", "Path to the SQL script to import.").requiredOption("-p, --project <path>", "Path to the .sdtproj file.").option("--dry-run", "Report what would be written without touching disk.", false).option("--force", "Overwrite existing files (default refuses on conflict).", false).option(
17
+ "--ignore-errors",
18
+ "Import classifiable statements even when others have errors. Default refuses on any error.",
19
+ false
20
+ ).action(async (opts) => {
21
+ const scriptPath = path.resolve(String(opts.script));
22
+ const projectPath = path.resolve(String(opts.project));
23
+ const sql = await fs.readFile(scriptPath, "utf8");
24
+ const parsed = parseScript(sql);
25
+ printParseReport(scriptPath, parsed);
26
+ if (parsed.totalErrors > 0 && !opts.ignoreErrors) {
27
+ console.error(
28
+ `
29
+ Refusing to import: ${parsed.totalErrors} parse error(s) above. Fix the script and re-run, or pass --ignore-errors to import the clean statements.`
30
+ );
31
+ process.exitCode = 2;
32
+ return;
33
+ }
34
+ const loaded = await loadProject(projectPath);
35
+ const result = await importScript(parsed, loaded, {
36
+ dryRun: !!opts.dryRun,
37
+ force: !!opts.force
38
+ });
39
+ console.log("");
40
+ const verb = opts.dryRun ? "would write" : "wrote";
41
+ for (const item of result.imported) {
42
+ const rel = path.relative(loaded.rootDir, item.targetPath);
43
+ console.log(
44
+ ` ${verb} ${item.statement.objectType} ${qualified(item.statement)} \u2192 ${rel}`
45
+ );
46
+ }
47
+ for (const item of result.skipped) {
48
+ const head = item.statement.objectType && item.statement.fqn ? `${item.statement.objectType} ${qualified(item.statement)}` : `<unclassified statement at line ${item.statement.startLine}>`;
49
+ console.log(` skip ${head} \u2014 ${item.reason}`);
50
+ }
51
+ console.log("");
52
+ console.log(
53
+ `Summary: ${result.imported.length} ${verb}, ${result.skipped.length} skipped, ${parsed.totalErrors} errors, ${parsed.totalWarnings} warnings.`
54
+ );
55
+ if (result.imported.length === 0 && result.skipped.length > 0) {
56
+ process.exitCode = 1;
57
+ }
58
+ });
59
+ return cmd;
60
+ }
61
+ function qualified(stmt) {
62
+ if (!stmt.fqn) return "<no fqn>";
63
+ return [stmt.fqn.database, stmt.fqn.schema, stmt.fqn.name].filter(Boolean).join(".");
64
+ }
65
+ function printParseReport(scriptPath, parsed) {
66
+ console.log(`Parsed ${parsed.statements.length} statement(s) from ${scriptPath}.`);
67
+ if (parsed.totalErrors === 0 && parsed.totalWarnings === 0) {
68
+ console.log("All statements classified cleanly.");
69
+ return;
70
+ }
71
+ for (const stmt of parsed.statements) {
72
+ if (stmt.errors.length === 0 && stmt.warnings.length === 0) continue;
73
+ const head = stmt.objectType && stmt.fqn ? `${stmt.objectType} ${qualified(stmt)}` : "<unclassified>";
74
+ console.log(`
75
+ [line ${stmt.startLine}\u2013${stmt.endLine}] ${head}`);
76
+ for (const e of stmt.errors) console.log(` ERROR: ${e}`);
77
+ for (const w of stmt.warnings) console.log(` warning: ${w}`);
78
+ }
79
+ }
80
+ export {
81
+ importScriptCommand
82
+ };
83
+ //# sourceMappingURL=import-script-2OF5BI6A.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/import-script.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport {\n importScript,\n loadProject,\n parseScript,\n type ParsedStatement,\n} from '@sdt-tools/core/project';\n\n/**\n * `sdt import-script` — parse a SQL script and apply each DDL statement to a\n * `.sdtproj` tree, writing each into the canonical folder for its object\n * type (`databases/<db>/schemas/<sch>/<type-folder>/<name>.sql`).\n *\n * This is the script→tree splitter. For converting another tool's artifacts\n * (schemachange / SnowDDL / dacpac / dbt / Terraform / …) into a fresh\n * project, use `sdt import` instead. Byte-aligned with `ddt import-script`.\n *\n * Default mode is safe:\n * - Parses the whole script first; refuses to write anything if any\n * statement has hard errors. The user reviews the report, fixes the\n * script, and re-runs.\n * - Refuses to overwrite existing files. Pass `--force` to clobber.\n * - `--dry-run` shows the plan without writing.\n */\nexport function importScriptCommand(): Command {\n const cmd = new Command('import-script');\n cmd\n .description(\n 'Parse a SQL script and write each DDL statement into the .sdtproj tree under its canonical folder.',\n )\n .requiredOption('--script <path>', 'Path to the SQL script to import.')\n .requiredOption('-p, --project <path>', 'Path to the .sdtproj file.')\n .option('--dry-run', 'Report what would be written without touching disk.', false)\n .option('--force', 'Overwrite existing files (default refuses on conflict).', false)\n .option(\n '--ignore-errors',\n 'Import classifiable statements even when others have errors. Default refuses on any error.',\n false,\n )\n .action(async (opts) => {\n const scriptPath = path.resolve(String(opts.script));\n const projectPath = path.resolve(String(opts.project));\n const sql = await fs.readFile(scriptPath, 'utf8');\n const parsed = parseScript(sql);\n\n // Up-front parse report — surfaces every error/warning verbatim.\n printParseReport(scriptPath, parsed);\n\n if (parsed.totalErrors > 0 && !opts.ignoreErrors) {\n console.error(\n `\\nRefusing to import: ${parsed.totalErrors} parse error(s) above. ` +\n `Fix the script and re-run, or pass --ignore-errors to import the clean statements.`,\n );\n process.exitCode = 2;\n return;\n }\n\n const loaded = await loadProject(projectPath);\n const result = await importScript(parsed, loaded, {\n dryRun: !!opts.dryRun,\n force: !!opts.force,\n });\n\n console.log('');\n const verb = opts.dryRun ? 'would write' : 'wrote';\n for (const item of result.imported) {\n const rel = path.relative(loaded.rootDir, item.targetPath);\n console.log(\n ` ${verb} ${item.statement.objectType} ${qualified(item.statement)} → ${rel}`,\n );\n }\n for (const item of result.skipped) {\n const head =\n item.statement.objectType && item.statement.fqn\n ? `${item.statement.objectType} ${qualified(item.statement)}`\n : `<unclassified statement at line ${item.statement.startLine}>`;\n console.log(` skip ${head} — ${item.reason}`);\n }\n console.log('');\n console.log(\n `Summary: ${result.imported.length} ${verb}, ${result.skipped.length} skipped, ` +\n `${parsed.totalErrors} errors, ${parsed.totalWarnings} warnings.`,\n );\n\n if (result.imported.length === 0 && result.skipped.length > 0) {\n process.exitCode = 1;\n }\n });\n return cmd;\n}\n\nfunction qualified(stmt: ParsedStatement): string {\n if (!stmt.fqn) return '<no fqn>';\n return [stmt.fqn.database, stmt.fqn.schema, stmt.fqn.name].filter(Boolean).join('.');\n}\n\nfunction printParseReport(scriptPath: string, parsed: ReturnType<typeof parseScript>): void {\n console.log(`Parsed ${parsed.statements.length} statement(s) from ${scriptPath}.`);\n if (parsed.totalErrors === 0 && parsed.totalWarnings === 0) {\n console.log('All statements classified cleanly.');\n return;\n }\n for (const stmt of parsed.statements) {\n if (stmt.errors.length === 0 && stmt.warnings.length === 0) continue;\n const head =\n stmt.objectType && stmt.fqn ? `${stmt.objectType} ${qualified(stmt)}` : '<unclassified>';\n console.log(`\\n[line ${stmt.startLine}–${stmt.endLine}] ${head}`);\n for (const e of stmt.errors) console.log(` ERROR: ${e}`);\n for (const w of stmt.warnings) console.log(` warning: ${w}`);\n }\n}\n"],"mappings":"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","names":[]}