@sdt-tools/cli 0.2.0 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/dist/advise-tests-6DRSZMBL.js +87 -0
  2. package/dist/advise-tests-6DRSZMBL.js.map +1 -0
  3. package/dist/ai-G4MJWHTM.js +89 -0
  4. package/dist/ai-G4MJWHTM.js.map +1 -0
  5. package/dist/anonymize-QR6JGXA7.js +123 -0
  6. package/dist/anonymize-QR6JGXA7.js.map +1 -0
  7. package/dist/approval-YVHYTV53.js +73 -0
  8. package/dist/approval-YVHYTV53.js.map +1 -0
  9. package/dist/approval-chain-54KKJZS3.js +120 -0
  10. package/dist/approval-chain-54KKJZS3.js.map +1 -0
  11. package/dist/audit-log-QZFH7LUX.js +159 -0
  12. package/dist/audit-log-QZFH7LUX.js.map +1 -0
  13. package/dist/backlog-V2YUIQDL.js +76 -0
  14. package/dist/backlog-V2YUIQDL.js.map +1 -0
  15. package/dist/bisect-GEVYAVL5.js +111 -0
  16. package/dist/bisect-GEVYAVL5.js.map +1 -0
  17. package/dist/bookmarks-57LKS7P6.js +107 -0
  18. package/dist/bookmarks-57LKS7P6.js.map +1 -0
  19. package/dist/branch-W2MGMPSH.js +88 -0
  20. package/dist/branch-W2MGMPSH.js.map +1 -0
  21. package/dist/build-VNIQFKSP.js +23 -0
  22. package/dist/build-VNIQFKSP.js.map +1 -0
  23. package/dist/catalog-JLB5VCEV.js +137 -0
  24. package/dist/catalog-JLB5VCEV.js.map +1 -0
  25. package/dist/changelog-M7XGDYSY.js +220 -0
  26. package/dist/changelog-M7XGDYSY.js.map +1 -0
  27. package/dist/chunk-DGUM43GV.js +11 -0
  28. package/dist/chunk-DGUM43GV.js.map +1 -0
  29. package/dist/chunk-EWXM4KJN.js +25 -0
  30. package/dist/chunk-EWXM4KJN.js.map +1 -0
  31. package/dist/chunk-JP2EZLR5.js +50 -0
  32. package/dist/chunk-JP2EZLR5.js.map +1 -0
  33. package/dist/chunk-VM2H4LAO.js +15 -0
  34. package/dist/chunk-VM2H4LAO.js.map +1 -0
  35. package/dist/chunk-ZWY4ZRHL.js +44 -0
  36. package/dist/chunk-ZWY4ZRHL.js.map +1 -0
  37. package/dist/cli.js +506 -19014
  38. package/dist/cli.js.map +1 -1
  39. package/dist/compare-5O6UTWPJ.js +405 -0
  40. package/dist/compare-5O6UTWPJ.js.map +1 -0
  41. package/dist/compare-profiles-7ZSNIW7B.js +218 -0
  42. package/dist/compare-profiles-7ZSNIW7B.js.map +1 -0
  43. package/dist/completion-I5U5VVAX.js +82 -0
  44. package/dist/completion-I5U5VVAX.js.map +1 -0
  45. package/dist/connection-SYTH4V53.js +110 -0
  46. package/dist/connection-SYTH4V53.js.map +1 -0
  47. package/dist/cost-estimate-TJDDH6TO.js +328 -0
  48. package/dist/cost-estimate-TJDDH6TO.js.map +1 -0
  49. package/dist/data-compare-UK2UXAS3.js +134 -0
  50. package/dist/data-compare-UK2UXAS3.js.map +1 -0
  51. package/dist/data-fit-Q45ENBRL.js +125 -0
  52. package/dist/data-fit-Q45ENBRL.js.map +1 -0
  53. package/dist/deploy-status-UUHKVDTI.js +58 -0
  54. package/dist/deploy-status-UUHKVDTI.js.map +1 -0
  55. package/dist/design-PO6UPBL7.js +138 -0
  56. package/dist/design-PO6UPBL7.js.map +1 -0
  57. package/dist/diagnose-6IFMELFR.js +145 -0
  58. package/dist/diagnose-6IFMELFR.js.map +1 -0
  59. package/dist/discover-A7OSZAHK.js +78 -0
  60. package/dist/discover-A7OSZAHK.js.map +1 -0
  61. package/dist/docs-CVRKGUSW.js +177 -0
  62. package/dist/docs-CVRKGUSW.js.map +1 -0
  63. package/dist/drift-XDA3BDYN.js +226 -0
  64. package/dist/drift-XDA3BDYN.js.map +1 -0
  65. package/dist/drift-gate-V7QSIOGZ.js +94 -0
  66. package/dist/drift-gate-V7QSIOGZ.js.map +1 -0
  67. package/dist/error-lookup-7ZWCZJ44.js +56 -0
  68. package/dist/error-lookup-7ZWCZJ44.js.map +1 -0
  69. package/dist/errorReporting-ZRNJ3VW7.js +109 -0
  70. package/dist/errorReporting-ZRNJ3VW7.js.map +1 -0
  71. package/dist/exec-PKBHLI7T.js +121 -0
  72. package/dist/exec-PKBHLI7T.js.map +1 -0
  73. package/dist/explain-LWKJOTL7.js +192 -0
  74. package/dist/explain-LWKJOTL7.js.map +1 -0
  75. package/dist/explorer-QOVM6VBD.js +61 -0
  76. package/dist/explorer-QOVM6VBD.js.map +1 -0
  77. package/dist/export-IYYBZ5HE.js +42 -0
  78. package/dist/export-IYYBZ5HE.js.map +1 -0
  79. package/dist/extract-VMMVRQVT.js +102 -0
  80. package/dist/extract-VMMVRQVT.js.map +1 -0
  81. package/dist/features-LE6BDZ2S.js +59 -0
  82. package/dist/features-LE6BDZ2S.js.map +1 -0
  83. package/dist/feedback-M7DM2EQC.js +161 -0
  84. package/dist/feedback-M7DM2EQC.js.map +1 -0
  85. package/dist/find-EME2JG2I.js +176 -0
  86. package/dist/find-EME2JG2I.js.map +1 -0
  87. package/dist/format-TRLWLMGS.js +141 -0
  88. package/dist/format-TRLWLMGS.js.map +1 -0
  89. package/dist/generate-6NAZGZDV.js +152 -0
  90. package/dist/generate-6NAZGZDV.js.map +1 -0
  91. package/dist/graph-QNQDAUO7.js +161 -0
  92. package/dist/graph-QNQDAUO7.js.map +1 -0
  93. package/dist/history-RONA7ZTI.js +199 -0
  94. package/dist/history-RONA7ZTI.js.map +1 -0
  95. package/dist/hosts-YBXY2ZG5.js +49 -0
  96. package/dist/hosts-YBXY2ZG5.js.map +1 -0
  97. package/dist/impact-T2JSANHS.js +59 -0
  98. package/dist/impact-T2JSANHS.js.map +1 -0
  99. package/dist/import-AELYLY6A.js +32 -0
  100. package/dist/import-AELYLY6A.js.map +1 -0
  101. package/dist/index.cjs +36 -6
  102. package/dist/index.cjs.map +1 -1
  103. package/dist/index.js +60 -25
  104. package/dist/index.js.map +1 -1
  105. package/dist/init-SWRRJMGI.js +57 -0
  106. package/dist/init-SWRRJMGI.js.map +1 -0
  107. package/dist/install-hooks-6SIAGTAF.js +109 -0
  108. package/dist/install-hooks-6SIAGTAF.js.map +1 -0
  109. package/dist/license-OAF22PLZ.js +46 -0
  110. package/dist/license-OAF22PLZ.js.map +1 -0
  111. package/dist/lineage-EW66XJ6O.js +552 -0
  112. package/dist/lineage-EW66XJ6O.js.map +1 -0
  113. package/dist/lint-FQ2OTYTQ.js +143 -0
  114. package/dist/lint-FQ2OTYTQ.js.map +1 -0
  115. package/dist/mcp-3QI4TH4N.js +344 -0
  116. package/dist/mcp-3QI4TH4N.js.map +1 -0
  117. package/dist/migrate-from-dbt-JVTXPWKQ.js +156 -0
  118. package/dist/migrate-from-dbt-JVTXPWKQ.js.map +1 -0
  119. package/dist/migrate-platform-NTRTOGNR.js +91 -0
  120. package/dist/migrate-platform-NTRTOGNR.js.map +1 -0
  121. package/dist/optimize-CJYWMAWA.js +105 -0
  122. package/dist/optimize-CJYWMAWA.js.map +1 -0
  123. package/dist/perf-LL2CPCJF.js +205 -0
  124. package/dist/perf-LL2CPCJF.js.map +1 -0
  125. package/dist/pii-FBDRDQ2E.js +136 -0
  126. package/dist/pii-FBDRDQ2E.js.map +1 -0
  127. package/dist/pilot-CCQERKPH.js +29 -0
  128. package/dist/pilot-CCQERKPH.js.map +1 -0
  129. package/dist/pr-comment-S5FF4QRX.js +79 -0
  130. package/dist/pr-comment-S5FF4QRX.js.map +1 -0
  131. package/dist/preview-5U4YVCRM.js +47 -0
  132. package/dist/preview-5U4YVCRM.js.map +1 -0
  133. package/dist/profile-7VC57KD2.js +101 -0
  134. package/dist/profile-7VC57KD2.js.map +1 -0
  135. package/dist/promote-AASEFTIA.js +408 -0
  136. package/dist/promote-AASEFTIA.js.map +1 -0
  137. package/dist/publish-Y2J56K4Y.js +715 -0
  138. package/dist/publish-Y2J56K4Y.js.map +1 -0
  139. package/dist/purge-QMXZKCMD.js +57 -0
  140. package/dist/purge-QMXZKCMD.js.map +1 -0
  141. package/dist/query-log-6OM4GI7W.js +112 -0
  142. package/dist/query-log-6OM4GI7W.js.map +1 -0
  143. package/dist/refactor-LTZQLJ35.js +5799 -0
  144. package/dist/refactor-LTZQLJ35.js.map +1 -0
  145. package/dist/refresh-4TY2AGOU.js +38 -0
  146. package/dist/refresh-4TY2AGOU.js.map +1 -0
  147. package/dist/replay-OOC25FZN.js +117 -0
  148. package/dist/replay-OOC25FZN.js.map +1 -0
  149. package/dist/revert-ODMUVJW6.js +110 -0
  150. package/dist/revert-ODMUVJW6.js.map +1 -0
  151. package/dist/review-XXPWOBFP.js +158 -0
  152. package/dist/review-XXPWOBFP.js.map +1 -0
  153. package/dist/rollback-suggest-6G2HEKFR.js +79 -0
  154. package/dist/rollback-suggest-6G2HEKFR.js.map +1 -0
  155. package/dist/safer-alternative-QFVNLG3L.js +89 -0
  156. package/dist/safer-alternative-QFVNLG3L.js.map +1 -0
  157. package/dist/safety-7QWRSUEZ.js +168 -0
  158. package/dist/safety-7QWRSUEZ.js.map +1 -0
  159. package/dist/savings-RHIXP6IT.js +95 -0
  160. package/dist/savings-RHIXP6IT.js.map +1 -0
  161. package/dist/scan-secrets-5YCQ4UCU.js +54 -0
  162. package/dist/scan-secrets-5YCQ4UCU.js.map +1 -0
  163. package/dist/schema-CIZXCQD2.js +429 -0
  164. package/dist/schema-CIZXCQD2.js.map +1 -0
  165. package/dist/script-K7CIN2P6.js +153 -0
  166. package/dist/script-K7CIN2P6.js.map +1 -0
  167. package/dist/search-BUZ5NXZZ.js +151 -0
  168. package/dist/search-BUZ5NXZZ.js.map +1 -0
  169. package/dist/seed-76QAK276.js +96 -0
  170. package/dist/seed-76QAK276.js.map +1 -0
  171. package/dist/sketch-PTLKDIK3.js +88 -0
  172. package/dist/sketch-PTLKDIK3.js.map +1 -0
  173. package/dist/snapshot-XLPR2OZ5.js +177 -0
  174. package/dist/snapshot-XLPR2OZ5.js.map +1 -0
  175. package/dist/snippets-EK4DK5CN.js +74 -0
  176. package/dist/snippets-EK4DK5CN.js.map +1 -0
  177. package/dist/standards-7T2UY6DD.js +241 -0
  178. package/dist/standards-7T2UY6DD.js.map +1 -0
  179. package/dist/suggest-VGRYSAR6.js +39 -0
  180. package/dist/suggest-VGRYSAR6.js.map +1 -0
  181. package/dist/suggest-constraints-MY5WKUHA.js +160 -0
  182. package/dist/suggest-constraints-MY5WKUHA.js.map +1 -0
  183. package/dist/suite-TRNGZWQM.js +88 -0
  184. package/dist/suite-TRNGZWQM.js.map +1 -0
  185. package/dist/telemetry-3U2QLA2S.js +75 -0
  186. package/dist/telemetry-3U2QLA2S.js.map +1 -0
  187. package/dist/template-ZERIXVXF.js +403 -0
  188. package/dist/template-ZERIXVXF.js.map +1 -0
  189. package/dist/test-5M2ED3WT.js +169 -0
  190. package/dist/test-5M2ED3WT.js.map +1 -0
  191. package/dist/trial-U732FONV.js +31 -0
  192. package/dist/trial-U732FONV.js.map +1 -0
  193. package/dist/validate-T6D2WCOK.js +106 -0
  194. package/dist/validate-T6D2WCOK.js.map +1 -0
  195. package/dist/verify-KXVASEEG.js +76 -0
  196. package/dist/verify-KXVASEEG.js.map +1 -0
  197. package/dist/watch-I6K4BNMA.js +80 -0
  198. package/dist/watch-I6K4BNMA.js.map +1 -0
  199. package/dist/xcompare-TPFLQO6W.js +87 -0
  200. package/dist/xcompare-TPFLQO6W.js.map +1 -0
  201. package/package.json +2 -2
  202. package/dist/cli.cjs +0 -19040
  203. package/dist/cli.cjs.map +0 -1
  204. package/dist/cli.d.cts +0 -1
  205. package/dist/cli.d.ts +0 -1
@@ -0,0 +1,57 @@
1
+ import {
2
+ logger
3
+ } from "./chunk-VM2H4LAO.js";
4
+ import "./chunk-DGUM43GV.js";
5
+
6
+ // src/commands/init.ts
7
+ import path from "path";
8
+ import { promises as fs } from "fs";
9
+ import { Command } from "commander";
10
+ import { newProjectTemplate, saveProject } from "@sdt-tools/core/project";
11
+ function initCommand() {
12
+ const cmd = new Command("init");
13
+ cmd.description("Initialize a new SDT project in the current directory.").option("--name <name>", "Project name", "NewSnowflakeProject").option("--scope <scope>", "Project scope: account | database | schema", "database").option("--db <database>", "Database name (required for database/schema scope)").option("--schema <schema>", "Schema name (required for schema scope)").option("--dir <dir>", "Target directory (default: cwd)", process.cwd()).option(
14
+ "--force",
15
+ "Overwrite an existing <name>.sdtproj in the target directory. Without this flag, init refuses to clobber an existing project file so a re-run never silently discards your project configuration."
16
+ ).action(async (opts) => {
17
+ const scopeType = String(opts.scope);
18
+ if (!["account", "database", "schema"].includes(scopeType)) {
19
+ throw new Error(`Invalid --scope: ${opts.scope}. Use account | database | schema.`);
20
+ }
21
+ const scope = { type: scopeType };
22
+ if (scopeType !== "account") {
23
+ if (!opts.db) throw new Error(`--db is required for scope=${scopeType}`);
24
+ scope.database = String(opts.db);
25
+ }
26
+ if (scopeType === "schema") {
27
+ if (!opts.schema) throw new Error("--schema is required for scope=schema");
28
+ scope.schema = String(opts.schema);
29
+ }
30
+ const root = path.resolve(String(opts.dir));
31
+ await fs.mkdir(root, { recursive: true });
32
+ const project = newProjectTemplate(String(opts.name), scope);
33
+ const projectPath = path.join(root, `${project.name}.sdtproj`);
34
+ if (!opts.force) {
35
+ try {
36
+ await fs.access(projectPath);
37
+ logger.error(`${projectPath} already exists; pass --force to overwrite.`);
38
+ process.exitCode = 1;
39
+ return;
40
+ } catch {
41
+ }
42
+ }
43
+ await saveProject(projectPath, project);
44
+ const seedFolders = ["databases", "scripts/pre", "scripts/post"];
45
+ for (const f of seedFolders) await fs.mkdir(path.join(root, f), { recursive: true });
46
+ logger.success(`Created ${projectPath}`);
47
+ logger.dim(
48
+ ` Scope: ${scopeType}${scope.database ? " / " + scope.database : ""}${scope.schema ? " / " + scope.schema : ""}`
49
+ );
50
+ logger.dim(` Next: sdt extract --connection <profile> --output ${root}`);
51
+ });
52
+ return cmd;
53
+ }
54
+ export {
55
+ initCommand
56
+ };
57
+ //# sourceMappingURL=init-SWRRJMGI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { Command } from 'commander';\nimport { newProjectTemplate, saveProject } from '@sdt-tools/core/project';\nimport type { ProjectScope } from '@sdt-tools/core/project';\nimport { logger } from '../util/logger.js';\n\nexport function initCommand(): Command {\n const cmd = new Command('init');\n cmd\n .description('Initialize a new SDT project in the current directory.')\n .option('--name <name>', 'Project name', 'NewSnowflakeProject')\n .option('--scope <scope>', 'Project scope: account | database | schema', 'database')\n .option('--db <database>', 'Database name (required for database/schema scope)')\n .option('--schema <schema>', 'Schema name (required for schema scope)')\n .option('--dir <dir>', 'Target directory (default: cwd)', process.cwd())\n .option(\n '--force',\n 'Overwrite an existing <name>.sdtproj in the target directory. Without ' +\n 'this flag, init refuses to clobber an existing project file so a ' +\n 're-run never silently discards your project configuration.',\n )\n .action(async (opts) => {\n const scopeType = String(opts.scope) as ProjectScope['type'];\n if (!['account', 'database', 'schema'].includes(scopeType)) {\n throw new Error(`Invalid --scope: ${opts.scope}. Use account | database | schema.`);\n }\n const scope: ProjectScope = { type: scopeType };\n if (scopeType !== 'account') {\n if (!opts.db) throw new Error(`--db is required for scope=${scopeType}`);\n scope.database = String(opts.db);\n }\n if (scopeType === 'schema') {\n if (!opts.schema) throw new Error('--schema is required for scope=schema');\n scope.schema = String(opts.schema);\n }\n const root = path.resolve(String(opts.dir));\n await fs.mkdir(root, { recursive: true });\n const project = newProjectTemplate(String(opts.name), scope);\n const projectPath = path.join(root, `${project.name}.sdtproj`);\n // Refuse to clobber an existing project file unless --force. Mirrors\n // the `sdt standards init --force` pattern: a silent overwrite can\n // discard hand-edited project configuration on an accidental re-run.\n if (!opts.force) {\n try {\n await fs.access(projectPath);\n logger.error(`${projectPath} already exists; pass --force to overwrite.`);\n process.exitCode = 1;\n return;\n } catch {\n // File doesn't exist — proceed.\n }\n }\n await saveProject(projectPath, project);\n // Seed conventional folders so the user sees the layout SDT expects.\n const seedFolders = ['databases', 'scripts/pre', 'scripts/post'];\n for (const f of seedFolders) await fs.mkdir(path.join(root, f), { recursive: true });\n logger.success(`Created ${projectPath}`);\n logger.dim(\n ` Scope: ${scopeType}${scope.database ? ' / ' + scope.database : ''}${scope.schema ? ' / ' + scope.schema : ''}`,\n );\n logger.dim(` Next: sdt extract --connection <profile> --output ${root}`);\n });\n return cmd;\n}\n"],"mappings":";;;;;;AAAA,OAAO,UAAU;AACjB,SAAS,YAAY,UAAU;AAC/B,SAAS,eAAe;AACxB,SAAS,oBAAoB,mBAAmB;AAIzC,SAAS,cAAuB;AACrC,QAAM,MAAM,IAAI,QAAQ,MAAM;AAC9B,MACG,YAAY,wDAAwD,EACpE,OAAO,iBAAiB,gBAAgB,qBAAqB,EAC7D,OAAO,mBAAmB,8CAA8C,UAAU,EAClF,OAAO,mBAAmB,oDAAoD,EAC9E,OAAO,qBAAqB,yCAAyC,EACrE,OAAO,eAAe,mCAAmC,QAAQ,IAAI,CAAC,EACtE;AAAA,IACC;AAAA,IACA;AAAA,EAGF,EACC,OAAO,OAAO,SAAS;AACtB,UAAM,YAAY,OAAO,KAAK,KAAK;AACnC,QAAI,CAAC,CAAC,WAAW,YAAY,QAAQ,EAAE,SAAS,SAAS,GAAG;AAC1D,YAAM,IAAI,MAAM,oBAAoB,KAAK,KAAK,oCAAoC;AAAA,IACpF;AACA,UAAM,QAAsB,EAAE,MAAM,UAAU;AAC9C,QAAI,cAAc,WAAW;AAC3B,UAAI,CAAC,KAAK,GAAI,OAAM,IAAI,MAAM,8BAA8B,SAAS,EAAE;AACvE,YAAM,WAAW,OAAO,KAAK,EAAE;AAAA,IACjC;AACA,QAAI,cAAc,UAAU;AAC1B,UAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,uCAAuC;AACzE,YAAM,SAAS,OAAO,KAAK,MAAM;AAAA,IACnC;AACA,UAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,GAAG,CAAC;AAC1C,UAAM,GAAG,MAAM,MAAM,EAAE,WAAW,KAAK,CAAC;AACxC,UAAM,UAAU,mBAAmB,OAAO,KAAK,IAAI,GAAG,KAAK;AAC3D,UAAM,cAAc,KAAK,KAAK,MAAM,GAAG,QAAQ,IAAI,UAAU;AAI7D,QAAI,CAAC,KAAK,OAAO;AACf,UAAI;AACF,cAAM,GAAG,OAAO,WAAW;AAC3B,eAAO,MAAM,GAAG,WAAW,6CAA6C;AACxE,gBAAQ,WAAW;AACnB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,YAAY,aAAa,OAAO;AAEtC,UAAM,cAAc,CAAC,aAAa,eAAe,cAAc;AAC/D,eAAW,KAAK,YAAa,OAAM,GAAG,MAAM,KAAK,KAAK,MAAM,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AACnF,WAAO,QAAQ,WAAW,WAAW,EAAE;AACvC,WAAO;AAAA,MACL,aAAa,SAAS,GAAG,MAAM,WAAW,QAAQ,MAAM,WAAW,EAAE,GAAG,MAAM,SAAS,QAAQ,MAAM,SAAS,EAAE;AAAA,IAClH;AACA,WAAO,IAAI,yDAAyD,IAAI,EAAE;AAAA,EAC5E,CAAC;AACH,SAAO;AACT;","names":[]}
@@ -0,0 +1,109 @@
1
+ import "./chunk-DGUM43GV.js";
2
+
3
+ // src/commands/install-hooks.ts
4
+ import { promises as fs } from "fs";
5
+ import { existsSync } from "fs";
6
+ import path from "path";
7
+ import { Command } from "commander";
8
+ var HOOK_MARKER = "# sdt-managed-hook";
9
+ var HOOK_BODY = `#!/bin/sh
10
+ ${HOOK_MARKER} \u2014 installed by \`sdt install-hooks\`. Remove this hook or re-install with --force to update.
11
+
12
+ # Find the project file relative to the repo root.
13
+ project=$(find . -maxdepth 3 -name '*.sdtproj' -not -path '*/node_modules/*' -not -path '*/dist/*' | head -1)
14
+ if [ -z "$project" ]; then
15
+ echo "sdt pre-commit hook: no .sdtproj found (skipping)."
16
+ exit 0
17
+ fi
18
+
19
+ echo "sdt pre-commit: validate + format-check on $project"
20
+
21
+ if ! command -v sdt >/dev/null 2>&1; then
22
+ echo "sdt CLI not on PATH. Install with \`npm i -g @sdt-tools/cli\`, or remove the hook at .git/hooks/pre-commit."
23
+ exit 1
24
+ fi
25
+
26
+ if ! sdt validate -p "$project"; then
27
+ echo ""
28
+ echo "Refusing commit: \`sdt validate\` failed."
29
+ exit 1
30
+ fi
31
+
32
+ if ! sdt format -p "$project" --check; then
33
+ echo ""
34
+ echo "Refusing commit: some .sql files are not formatted. Run \`sdt format -p $project\` and re-stage."
35
+ exit 1
36
+ fi
37
+ `;
38
+ function installHooksCommand() {
39
+ const cmd = new Command("install-hooks");
40
+ cmd.description(
41
+ "Install a git pre-commit hook that runs `sdt validate` + `sdt format --check` before each commit."
42
+ ).option("--force", "Overwrite an existing hook (refuses by default if the file exists).", false).option("--uninstall", "Remove the sdt-managed pre-commit hook instead of installing.", false).action(async (opts) => {
43
+ const cwd = process.cwd();
44
+ const gitDir = await findGitDir(cwd);
45
+ if (!gitDir) {
46
+ throw new Error(`No .git directory found at or above ${cwd}.`);
47
+ }
48
+ const hookPath = path.join(gitDir, "hooks", "pre-commit");
49
+ if (opts.uninstall) {
50
+ if (!existsSync(hookPath)) {
51
+ console.log("No pre-commit hook installed.");
52
+ return;
53
+ }
54
+ const existing = await fs.readFile(hookPath, "utf8");
55
+ if (!existing.includes(HOOK_MARKER)) {
56
+ console.error(
57
+ `Refusing to remove: ${hookPath} is not a sdt-managed hook (missing marker).`
58
+ );
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ await fs.unlink(hookPath);
63
+ console.log(`Removed ${hookPath}.`);
64
+ return;
65
+ }
66
+ if (existsSync(hookPath) && !opts.force) {
67
+ const existing = await fs.readFile(hookPath, "utf8");
68
+ if (existing.includes(HOOK_MARKER)) {
69
+ console.log(`Hook already installed at ${hookPath}. Re-run with --force to overwrite.`);
70
+ } else {
71
+ console.error(`Refusing to overwrite: ${hookPath} exists and is NOT a sdt-managed hook.`);
72
+ console.error("Inspect it, then re-run with --force if you want to replace it.");
73
+ process.exitCode = 1;
74
+ }
75
+ return;
76
+ }
77
+ await fs.mkdir(path.dirname(hookPath), { recursive: true });
78
+ await fs.writeFile(hookPath, HOOK_BODY, { mode: 493 });
79
+ console.log(`Installed pre-commit hook at ${hookPath}.`);
80
+ console.log(" Runs `sdt validate` + `sdt format --check` on every commit.");
81
+ console.log(
82
+ " Bypass once with `git commit --no-verify`. Remove with `sdt install-hooks --uninstall`."
83
+ );
84
+ });
85
+ return cmd;
86
+ }
87
+ async function findGitDir(start) {
88
+ let dir = path.resolve(start);
89
+ while (true) {
90
+ const candidate = path.join(dir, ".git");
91
+ if (existsSync(candidate)) {
92
+ const stat = await fs.stat(candidate);
93
+ if (stat.isDirectory()) return candidate;
94
+ const ptr = await fs.readFile(candidate, "utf8");
95
+ const m = ptr.match(/^gitdir:\s*(.+)$/m);
96
+ if (m && m[1]) {
97
+ const resolved = path.isAbsolute(m[1]) ? m[1] : path.resolve(dir, m[1]);
98
+ return resolved;
99
+ }
100
+ }
101
+ const parent = path.dirname(dir);
102
+ if (parent === dir) return void 0;
103
+ dir = parent;
104
+ }
105
+ }
106
+ export {
107
+ installHooksCommand
108
+ };
109
+ //# sourceMappingURL=install-hooks-6SIAGTAF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/install-hooks.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { Command } from 'commander';\n\n/**\n * `sdt install-hooks` — install a git pre-commit hook that runs\n * `sdt format --check` + `sdt validate` before allowing a commit.\n *\n * Husky-style: writes a single shell script to `.git/hooks/pre-commit`\n * that delegates to the CLI. Refuses to overwrite an existing hook\n * unless --force.\n */\nconst HOOK_MARKER = '# sdt-managed-hook';\n\nconst HOOK_BODY = `#!/bin/sh\n${HOOK_MARKER} — installed by \\`sdt install-hooks\\`. Remove this hook or re-install with --force to update.\n\n# Find the project file relative to the repo root.\nproject=$(find . -maxdepth 3 -name '*.sdtproj' -not -path '*/node_modules/*' -not -path '*/dist/*' | head -1)\nif [ -z \"$project\" ]; then\n echo \"sdt pre-commit hook: no .sdtproj found (skipping).\"\n exit 0\nfi\n\necho \"sdt pre-commit: validate + format-check on $project\"\n\nif ! command -v sdt >/dev/null 2>&1; then\n echo \"sdt CLI not on PATH. Install with \\`npm i -g @sdt-tools/cli\\`, or remove the hook at .git/hooks/pre-commit.\"\n exit 1\nfi\n\nif ! sdt validate -p \"$project\"; then\n echo \"\"\n echo \"Refusing commit: \\`sdt validate\\` failed.\"\n exit 1\nfi\n\nif ! sdt format -p \"$project\" --check; then\n echo \"\"\n echo \"Refusing commit: some .sql files are not formatted. Run \\`sdt format -p $project\\` and re-stage.\"\n exit 1\nfi\n`;\n\nexport function installHooksCommand(): Command {\n const cmd = new Command('install-hooks');\n cmd\n .description(\n 'Install a git pre-commit hook that runs `sdt validate` + `sdt format --check` before each commit.',\n )\n .option('--force', 'Overwrite an existing hook (refuses by default if the file exists).', false)\n .option('--uninstall', 'Remove the sdt-managed pre-commit hook instead of installing.', false)\n .action(async (opts) => {\n const cwd = process.cwd();\n const gitDir = await findGitDir(cwd);\n if (!gitDir) {\n throw new Error(`No .git directory found at or above ${cwd}.`);\n }\n const hookPath = path.join(gitDir, 'hooks', 'pre-commit');\n\n if (opts.uninstall) {\n if (!existsSync(hookPath)) {\n console.log('No pre-commit hook installed.');\n return;\n }\n const existing = await fs.readFile(hookPath, 'utf8');\n if (!existing.includes(HOOK_MARKER)) {\n console.error(\n `Refusing to remove: ${hookPath} is not a sdt-managed hook (missing marker).`,\n );\n process.exitCode = 1;\n return;\n }\n await fs.unlink(hookPath);\n console.log(`Removed ${hookPath}.`);\n return;\n }\n\n if (existsSync(hookPath) && !opts.force) {\n const existing = await fs.readFile(hookPath, 'utf8');\n if (existing.includes(HOOK_MARKER)) {\n console.log(`Hook already installed at ${hookPath}. Re-run with --force to overwrite.`);\n } else {\n console.error(`Refusing to overwrite: ${hookPath} exists and is NOT a sdt-managed hook.`);\n console.error('Inspect it, then re-run with --force if you want to replace it.');\n process.exitCode = 1;\n }\n return;\n }\n\n await fs.mkdir(path.dirname(hookPath), { recursive: true });\n await fs.writeFile(hookPath, HOOK_BODY, { mode: 0o755 });\n console.log(`Installed pre-commit hook at ${hookPath}.`);\n console.log(' Runs `sdt validate` + `sdt format --check` on every commit.');\n console.log(\n ' Bypass once with `git commit --no-verify`. Remove with `sdt install-hooks --uninstall`.',\n );\n });\n return cmd;\n}\n\nasync function findGitDir(start: string): Promise<string | undefined> {\n let dir = path.resolve(start);\n while (true) {\n const candidate = path.join(dir, '.git');\n if (existsSync(candidate)) {\n const stat = await fs.stat(candidate);\n if (stat.isDirectory()) return candidate;\n const ptr = await fs.readFile(candidate, 'utf8');\n const m = ptr.match(/^gitdir:\\s*(.+)$/m);\n if (m && m[1]) {\n const resolved = path.isAbsolute(m[1]) ? m[1] : path.resolve(dir, m[1]);\n return resolved;\n }\n }\n const parent = path.dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n"],"mappings":";;;AAAA,SAAS,YAAY,UAAU;AAC/B,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,SAAS,eAAe;AAUxB,IAAM,cAAc;AAEpB,IAAM,YAAY;AAAA,EAChB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BN,SAAS,sBAA+B;AAC7C,QAAM,MAAM,IAAI,QAAQ,eAAe;AACvC,MACG;AAAA,IACC;AAAA,EACF,EACC,OAAO,WAAW,uEAAuE,KAAK,EAC9F,OAAO,eAAe,iEAAiE,KAAK,EAC5F,OAAO,OAAO,SAAS;AACtB,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,SAAS,MAAM,WAAW,GAAG;AACnC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,uCAAuC,GAAG,GAAG;AAAA,IAC/D;AACA,UAAM,WAAW,KAAK,KAAK,QAAQ,SAAS,YAAY;AAExD,QAAI,KAAK,WAAW;AAClB,UAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,gBAAQ,IAAI,+BAA+B;AAC3C;AAAA,MACF;AACA,YAAM,WAAW,MAAM,GAAG,SAAS,UAAU,MAAM;AACnD,UAAI,CAAC,SAAS,SAAS,WAAW,GAAG;AACnC,gBAAQ;AAAA,UACN,uBAAuB,QAAQ;AAAA,QACjC;AACA,gBAAQ,WAAW;AACnB;AAAA,MACF;AACA,YAAM,GAAG,OAAO,QAAQ;AACxB,cAAQ,IAAI,WAAW,QAAQ,GAAG;AAClC;AAAA,IACF;AAEA,QAAI,WAAW,QAAQ,KAAK,CAAC,KAAK,OAAO;AACvC,YAAM,WAAW,MAAM,GAAG,SAAS,UAAU,MAAM;AACnD,UAAI,SAAS,SAAS,WAAW,GAAG;AAClC,gBAAQ,IAAI,6BAA6B,QAAQ,qCAAqC;AAAA,MACxF,OAAO;AACL,gBAAQ,MAAM,0BAA0B,QAAQ,wCAAwC;AACxF,gBAAQ,MAAM,iEAAiE;AAC/E,gBAAQ,WAAW;AAAA,MACrB;AACA;AAAA,IACF;AAEA,UAAM,GAAG,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAC1D,UAAM,GAAG,UAAU,UAAU,WAAW,EAAE,MAAM,IAAM,CAAC;AACvD,YAAQ,IAAI,gCAAgC,QAAQ,GAAG;AACvD,YAAQ,IAAI,+DAA+D;AAC3E,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF,CAAC;AACH,SAAO;AACT;AAEA,eAAe,WAAW,OAA4C;AACpE,MAAI,MAAM,KAAK,QAAQ,KAAK;AAC5B,SAAO,MAAM;AACX,UAAM,YAAY,KAAK,KAAK,KAAK,MAAM;AACvC,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,OAAO,MAAM,GAAG,KAAK,SAAS;AACpC,UAAI,KAAK,YAAY,EAAG,QAAO;AAC/B,YAAM,MAAM,MAAM,GAAG,SAAS,WAAW,MAAM;AAC/C,YAAM,IAAI,IAAI,MAAM,mBAAmB;AACvC,UAAI,KAAK,EAAE,CAAC,GAAG;AACb,cAAM,WAAW,KAAK,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ,KAAK,EAAE,CAAC,CAAC;AACtE,eAAO;AAAA,MACT;AAAA,IACF;AACA,UAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -0,0 +1,46 @@
1
+ import {
2
+ logger
3
+ } from "./chunk-VM2H4LAO.js";
4
+ import "./chunk-DGUM43GV.js";
5
+
6
+ // src/commands/license.ts
7
+ import { promises as fs } from "fs";
8
+ import { homedir } from "os";
9
+ import path from "path";
10
+ import { Command } from "commander";
11
+ import { license as licenseApi } from "@sdt-tools/core";
12
+ function licenseCommand() {
13
+ const cmd = new Command("license").description(
14
+ "Manage the SDT license key (open-core, offline, warn-mode in v0.1)."
15
+ );
16
+ cmd.command("show").description("Show the currently loaded license.").action(async () => {
17
+ const lic = await licenseApi.loadLicense();
18
+ logger.info(licenseApi.describeLicense(lic));
19
+ });
20
+ cmd.command("set").description("Install a license JWT to ~/.sdt/license.jwt.").requiredOption("--jwt <token>", "The full JWT (3 dot-separated base64url parts).").action(async (opts) => {
21
+ const target = process.env["SDT_LICENSE_PATH"] ?? path.join(homedir(), ".sdt", "license.jwt");
22
+ await fs.mkdir(path.dirname(target), { recursive: true });
23
+ await fs.writeFile(target, opts.jwt.trim() + "\n", "utf8");
24
+ const lic = await licenseApi.loadLicense();
25
+ logger.info(`Wrote ${target}.`);
26
+ logger.info(licenseApi.describeLicense(lic));
27
+ });
28
+ cmd.command("clear").description("Remove the local license file (returns to free tier).").action(async () => {
29
+ const target = process.env["SDT_LICENSE_PATH"] ?? path.join(homedir(), ".sdt", "license.jwt");
30
+ try {
31
+ await fs.unlink(target);
32
+ logger.info(`Removed ${target}. Now running free tier.`);
33
+ } catch (err) {
34
+ if (err.code === "ENOENT") {
35
+ logger.info(`No license file at ${target}; already on free tier.`);
36
+ } else {
37
+ throw err;
38
+ }
39
+ }
40
+ });
41
+ return cmd;
42
+ }
43
+ export {
44
+ licenseCommand
45
+ };
46
+ //# sourceMappingURL=license-OAF22PLZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/license.ts"],"sourcesContent":["/**\n * `sdt license show|set|clear` — manage the local license-key file.\n * Open-core, offline, warn-mode (this revision never blocks; missing Pro\n * license only prints a warning when running Pro features).\n *\n * Mirrors `ddt license` in shape.\n */\nimport { promises as fs } from 'node:fs';\nimport { homedir } from 'node:os';\nimport path from 'node:path';\nimport { Command } from 'commander';\n\nimport { license as licenseApi } from '@sdt-tools/core';\nimport { logger } from '../util/logger.js';\n\nexport function licenseCommand(): Command {\n const cmd = new Command('license').description(\n 'Manage the SDT license key (open-core, offline, warn-mode in v0.1).',\n );\n\n cmd\n .command('show')\n .description('Show the currently loaded license.')\n .action(async () => {\n const lic = await licenseApi.loadLicense();\n logger.info(licenseApi.describeLicense(lic));\n });\n\n cmd\n .command('set')\n .description('Install a license JWT to ~/.sdt/license.jwt.')\n .requiredOption('--jwt <token>', 'The full JWT (3 dot-separated base64url parts).')\n .action(async (opts: { jwt: string }) => {\n const target = process.env['SDT_LICENSE_PATH'] ?? path.join(homedir(), '.sdt', 'license.jwt');\n await fs.mkdir(path.dirname(target), { recursive: true });\n await fs.writeFile(target, opts.jwt.trim() + '\\n', 'utf8');\n const lic = await licenseApi.loadLicense();\n logger.info(`Wrote ${target}.`);\n logger.info(licenseApi.describeLicense(lic));\n });\n\n cmd\n .command('clear')\n .description('Remove the local license file (returns to free tier).')\n .action(async () => {\n const target = process.env['SDT_LICENSE_PATH'] ?? path.join(homedir(), '.sdt', 'license.jwt');\n try {\n await fs.unlink(target);\n logger.info(`Removed ${target}. Now running free tier.`);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n logger.info(`No license file at ${target}; already on free tier.`);\n } else {\n throw err;\n }\n }\n });\n\n return cmd;\n}\n"],"mappings":";;;;;;AAOA,SAAS,YAAY,UAAU;AAC/B,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,eAAe;AAExB,SAAS,WAAW,kBAAkB;AAG/B,SAAS,iBAA0B;AACxC,QAAM,MAAM,IAAI,QAAQ,SAAS,EAAE;AAAA,IACjC;AAAA,EACF;AAEA,MACG,QAAQ,MAAM,EACd,YAAY,oCAAoC,EAChD,OAAO,YAAY;AAClB,UAAM,MAAM,MAAM,WAAW,YAAY;AACzC,WAAO,KAAK,WAAW,gBAAgB,GAAG,CAAC;AAAA,EAC7C,CAAC;AAEH,MACG,QAAQ,KAAK,EACb,YAAY,8CAA8C,EAC1D,eAAe,iBAAiB,iDAAiD,EACjF,OAAO,OAAO,SAA0B;AACvC,UAAM,SAAS,QAAQ,IAAI,kBAAkB,KAAK,KAAK,KAAK,QAAQ,GAAG,QAAQ,aAAa;AAC5F,UAAM,GAAG,MAAM,KAAK,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AACxD,UAAM,GAAG,UAAU,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,MAAM;AACzD,UAAM,MAAM,MAAM,WAAW,YAAY;AACzC,WAAO,KAAK,SAAS,MAAM,GAAG;AAC9B,WAAO,KAAK,WAAW,gBAAgB,GAAG,CAAC;AAAA,EAC7C,CAAC;AAEH,MACG,QAAQ,OAAO,EACf,YAAY,uDAAuD,EACnE,OAAO,YAAY;AAClB,UAAM,SAAS,QAAQ,IAAI,kBAAkB,KAAK,KAAK,KAAK,QAAQ,GAAG,QAAQ,aAAa;AAC5F,QAAI;AACF,YAAM,GAAG,OAAO,MAAM;AACtB,aAAO,KAAK,WAAW,MAAM,0BAA0B;AAAA,IACzD,SAAS,KAAK;AACZ,UAAK,IAA8B,SAAS,UAAU;AACpD,eAAO,KAAK,sBAAsB,MAAM,yBAAyB;AAAA,MACnE,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,CAAC;AAEH,SAAO;AACT;","names":[]}