@datachonk/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +200 -0
  2. package/dist/__tests__/cache.test.d.ts +2 -0
  3. package/dist/__tests__/cache.test.d.ts.map +1 -0
  4. package/dist/__tests__/cache.test.js +40 -0
  5. package/dist/__tests__/cache.test.js.map +1 -0
  6. package/dist/__tests__/config.test.d.ts +2 -0
  7. package/dist/__tests__/config.test.d.ts.map +1 -0
  8. package/dist/__tests__/config.test.js +113 -0
  9. package/dist/__tests__/config.test.js.map +1 -0
  10. package/dist/__tests__/templates.test.d.ts +2 -0
  11. package/dist/__tests__/templates.test.d.ts.map +1 -0
  12. package/dist/__tests__/templates.test.js +51 -0
  13. package/dist/__tests__/templates.test.js.map +1 -0
  14. package/dist/commands/analyze.d.ts +10 -0
  15. package/dist/commands/analyze.d.ts.map +1 -0
  16. package/dist/commands/analyze.js +156 -0
  17. package/dist/commands/analyze.js.map +1 -0
  18. package/dist/commands/chat.d.ts +3 -0
  19. package/dist/commands/chat.d.ts.map +1 -0
  20. package/dist/commands/chat.js +121 -0
  21. package/dist/commands/chat.js.map +1 -0
  22. package/dist/commands/config.d.ts +2 -0
  23. package/dist/commands/config.d.ts.map +1 -0
  24. package/dist/commands/config.js +287 -0
  25. package/dist/commands/config.js.map +1 -0
  26. package/dist/commands/docs.d.ts +7 -0
  27. package/dist/commands/docs.d.ts.map +1 -0
  28. package/dist/commands/docs.js +208 -0
  29. package/dist/commands/docs.js.map +1 -0
  30. package/dist/commands/generate.d.ts +9 -0
  31. package/dist/commands/generate.d.ts.map +1 -0
  32. package/dist/commands/generate.js +130 -0
  33. package/dist/commands/generate.js.map +1 -0
  34. package/dist/commands/init.d.ts +7 -0
  35. package/dist/commands/init.d.ts.map +1 -0
  36. package/dist/commands/init.js +149 -0
  37. package/dist/commands/init.js.map +1 -0
  38. package/dist/commands/lineage.d.ts +9 -0
  39. package/dist/commands/lineage.d.ts.map +1 -0
  40. package/dist/commands/lineage.js +186 -0
  41. package/dist/commands/lineage.js.map +1 -0
  42. package/dist/commands/migrate.d.ts +3 -0
  43. package/dist/commands/migrate.d.ts.map +1 -0
  44. package/dist/commands/migrate.js +213 -0
  45. package/dist/commands/migrate.js.map +1 -0
  46. package/dist/commands/review.d.ts +8 -0
  47. package/dist/commands/review.d.ts.map +1 -0
  48. package/dist/commands/review.js +215 -0
  49. package/dist/commands/review.js.map +1 -0
  50. package/dist/commands/scan.d.ts +18 -0
  51. package/dist/commands/scan.d.ts.map +1 -0
  52. package/dist/commands/scan.js +335 -0
  53. package/dist/commands/scan.js.map +1 -0
  54. package/dist/commands/test.d.ts +3 -0
  55. package/dist/commands/test.d.ts.map +1 -0
  56. package/dist/commands/test.js +244 -0
  57. package/dist/commands/test.js.map +1 -0
  58. package/dist/index.d.ts +3 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +232 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/utils/analyzer.d.ts +39 -0
  63. package/dist/utils/analyzer.d.ts.map +1 -0
  64. package/dist/utils/analyzer.js +310 -0
  65. package/dist/utils/analyzer.js.map +1 -0
  66. package/dist/utils/cache.d.ts +98 -0
  67. package/dist/utils/cache.d.ts.map +1 -0
  68. package/dist/utils/cache.js +253 -0
  69. package/dist/utils/cache.js.map +1 -0
  70. package/dist/utils/config.d.ts +56 -0
  71. package/dist/utils/config.d.ts.map +1 -0
  72. package/dist/utils/config.js +108 -0
  73. package/dist/utils/config.js.map +1 -0
  74. package/dist/utils/generators.d.ts +8 -0
  75. package/dist/utils/generators.d.ts.map +1 -0
  76. package/dist/utils/generators.js +265 -0
  77. package/dist/utils/generators.js.map +1 -0
  78. package/dist/utils/plugins.d.ts +94 -0
  79. package/dist/utils/plugins.d.ts.map +1 -0
  80. package/dist/utils/plugins.js +164 -0
  81. package/dist/utils/plugins.js.map +1 -0
  82. package/dist/utils/templates.d.ts +57 -0
  83. package/dist/utils/templates.d.ts.map +1 -0
  84. package/dist/utils/templates.js +458 -0
  85. package/dist/utils/templates.js.map +1 -0
  86. package/package.json +69 -0
@@ -0,0 +1,335 @@
1
+ import chalk from "chalk";
2
+ import ora from "ora";
3
+ import inquirer from "inquirer";
4
+ import { readFileSync, existsSync, writeFileSync } from "fs";
5
+ import { join } from "path";
6
+ import yaml from "js-yaml";
7
+ import { table } from "table";
8
+ import { getApiKey } from "../utils/config.js";
9
+ export async function scanCommand(options) {
10
+ console.log(chalk.hex("#E8A54B").bold("\n DataChonk Discovery Engine\n"));
11
+ // Try to load connection from config or prompt
12
+ let connectionConfig = {};
13
+ let sourceType = options.type;
14
+ // Check for existing .datachonk.yml with connection info
15
+ const configPath = join(process.cwd(), ".datachonk.yml");
16
+ if (existsSync(configPath)) {
17
+ try {
18
+ const config = yaml.load(readFileSync(configPath, "utf-8"));
19
+ if (config.connections && typeof config.connections === "object") {
20
+ const connections = config.connections;
21
+ const names = Object.keys(connections);
22
+ if (names.length > 0) {
23
+ const { useExisting } = await inquirer.prompt([
24
+ {
25
+ type: "confirm",
26
+ name: "useExisting",
27
+ message: `Found ${names.length} saved connection(s). Use existing?`,
28
+ default: true,
29
+ },
30
+ ]);
31
+ if (useExisting) {
32
+ const { connectionName } = await inquirer.prompt([
33
+ {
34
+ type: "list",
35
+ name: "connectionName",
36
+ message: "Select connection:",
37
+ choices: names,
38
+ },
39
+ ]);
40
+ const savedConn = connections[connectionName];
41
+ sourceType = savedConn.type;
42
+ connectionConfig = savedConn;
43
+ }
44
+ }
45
+ }
46
+ }
47
+ catch {
48
+ // Ignore config errors
49
+ }
50
+ }
51
+ // If no connection from config, prompt for details
52
+ if (!sourceType) {
53
+ const answers = await inquirer.prompt([
54
+ {
55
+ type: "list",
56
+ name: "type",
57
+ message: "Select database type:",
58
+ choices: [
59
+ { name: "PostgreSQL", value: "postgresql" },
60
+ { name: "MySQL", value: "mysql" },
61
+ { name: "Snowflake", value: "snowflake" },
62
+ { name: "BigQuery", value: "bigquery" },
63
+ { name: "Redshift", value: "redshift" },
64
+ ],
65
+ },
66
+ ]);
67
+ sourceType = answers.type;
68
+ }
69
+ // Gather connection details based on type
70
+ if (Object.keys(connectionConfig).length === 0) {
71
+ switch (sourceType) {
72
+ case "postgresql":
73
+ case "mysql":
74
+ case "redshift":
75
+ const relationalAnswers = await inquirer.prompt([
76
+ {
77
+ type: "input",
78
+ name: "host",
79
+ message: "Host:",
80
+ default: options.host || "localhost",
81
+ },
82
+ {
83
+ type: "input",
84
+ name: "port",
85
+ message: "Port:",
86
+ default: options.port || (sourceType === "mysql" ? "3306" : sourceType === "redshift" ? "5439" : "5432"),
87
+ },
88
+ {
89
+ type: "input",
90
+ name: "database",
91
+ message: "Database:",
92
+ default: options.database,
93
+ },
94
+ {
95
+ type: "input",
96
+ name: "username",
97
+ message: "Username:",
98
+ default: options.user,
99
+ },
100
+ {
101
+ type: "password",
102
+ name: "password",
103
+ message: "Password:",
104
+ mask: "*",
105
+ },
106
+ ]);
107
+ connectionConfig = { ...relationalAnswers, type: sourceType };
108
+ break;
109
+ case "snowflake":
110
+ const snowflakeAnswers = await inquirer.prompt([
111
+ {
112
+ type: "input",
113
+ name: "account",
114
+ message: "Account (e.g., abc123.us-east-1):",
115
+ default: options.account,
116
+ },
117
+ {
118
+ type: "input",
119
+ name: "username",
120
+ message: "Username:",
121
+ default: options.user,
122
+ },
123
+ {
124
+ type: "password",
125
+ name: "password",
126
+ message: "Password:",
127
+ mask: "*",
128
+ },
129
+ {
130
+ type: "input",
131
+ name: "warehouse",
132
+ message: "Warehouse:",
133
+ default: options.warehouse,
134
+ },
135
+ {
136
+ type: "input",
137
+ name: "database",
138
+ message: "Database:",
139
+ default: options.database,
140
+ },
141
+ ]);
142
+ connectionConfig = { ...snowflakeAnswers, type: sourceType };
143
+ break;
144
+ case "bigquery":
145
+ const bqAnswers = await inquirer.prompt([
146
+ {
147
+ type: "input",
148
+ name: "project",
149
+ message: "GCP Project ID:",
150
+ default: options.project,
151
+ },
152
+ {
153
+ type: "input",
154
+ name: "keyFile",
155
+ message: "Service account key file path (optional):",
156
+ },
157
+ ]);
158
+ connectionConfig = { ...bqAnswers, type: sourceType };
159
+ break;
160
+ }
161
+ }
162
+ // Ask about schemas to scan
163
+ const schemasToScan = options.schemas?.split(",") || [];
164
+ if (schemasToScan.length === 0) {
165
+ const { schemas } = await inquirer.prompt([
166
+ {
167
+ type: "input",
168
+ name: "schemas",
169
+ message: "Schemas to scan (comma-separated, or blank for all):",
170
+ default: "",
171
+ },
172
+ ]);
173
+ if (schemas) {
174
+ schemasToScan.push(...schemas.split(",").map((s) => s.trim()));
175
+ }
176
+ }
177
+ // Ask to save connection
178
+ const { saveConnection } = await inquirer.prompt([
179
+ {
180
+ type: "confirm",
181
+ name: "saveConnection",
182
+ message: "Save this connection for future scans?",
183
+ default: true,
184
+ },
185
+ ]);
186
+ if (saveConnection) {
187
+ const { connectionName } = await inquirer.prompt([
188
+ {
189
+ type: "input",
190
+ name: "connectionName",
191
+ message: "Connection name:",
192
+ default: connectionConfig.database || sourceType,
193
+ },
194
+ ]);
195
+ // Save to .datachonk.yml
196
+ let config = {};
197
+ if (existsSync(configPath)) {
198
+ config = yaml.load(readFileSync(configPath, "utf-8"));
199
+ }
200
+ if (!config.connections) {
201
+ config.connections = {};
202
+ }
203
+ // Don't save password in plain text - note this
204
+ const connToSave = { ...connectionConfig };
205
+ delete connToSave.password;
206
+ config.connections[connectionName] = connToSave;
207
+ writeFileSync(configPath, yaml.dump(config, { indent: 2 }));
208
+ console.log(chalk.green(`\nConnection saved to .datachonk.yml (password not stored)`));
209
+ }
210
+ // Start scanning
211
+ const spinner = ora("Connecting to database...").start();
212
+ try {
213
+ // Call the scan API
214
+ const apiKey = getApiKey();
215
+ const { getApiUrl } = await import("../utils/config.js");
216
+ const scanEndpoint = getApiUrl();
217
+ const response = await fetch(`${scanEndpoint}/api/scan/cli`, {
218
+ method: "POST",
219
+ headers: {
220
+ "Content-Type": "application/json",
221
+ ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
222
+ },
223
+ body: JSON.stringify({
224
+ sourceType,
225
+ connectionConfig: {
226
+ ...connectionConfig,
227
+ password: connectionConfig.password, // Pass password for this request only
228
+ },
229
+ options: {
230
+ schemas: schemasToScan.length > 0 ? schemasToScan : undefined,
231
+ includeRowCounts: true,
232
+ },
233
+ }),
234
+ });
235
+ if (!response.ok) {
236
+ const errorData = await response.json();
237
+ throw new Error(errorData.error || "Scan failed");
238
+ }
239
+ const result = await response.json();
240
+ spinner.succeed("Scan complete!");
241
+ // Display results
242
+ console.log(chalk.bold("\n📊 Discovery Results\n"));
243
+ console.log(chalk.gray("─".repeat(60)));
244
+ // Tables summary
245
+ console.log(chalk.bold(`\nTables Found: ${result.tables.length}`));
246
+ if (result.tables.length > 0 && !options.json) {
247
+ const tableData = [
248
+ [chalk.bold("Schema"), chalk.bold("Table"), chalk.bold("Type"), chalk.bold("Rows")],
249
+ ...result.tables.slice(0, 20).map((t) => [
250
+ t.schemaName,
251
+ t.tableName,
252
+ t.tableType,
253
+ t.rowCount?.toLocaleString() || "N/A",
254
+ ]),
255
+ ];
256
+ if (result.tables.length > 20) {
257
+ tableData.push(["...", `+${result.tables.length - 20} more`, "", ""]);
258
+ }
259
+ console.log(table(tableData));
260
+ }
261
+ // Columns summary
262
+ console.log(chalk.bold(`Columns Found: ${result.columns.length}`));
263
+ // Relationships
264
+ const totalRels = result.foreignKeys.length + (result.inferredRelationships?.length || 0);
265
+ console.log(chalk.bold(`\nRelationships Discovered: ${totalRels}`));
266
+ console.log(chalk.gray(` • ${result.foreignKeys.length} foreign keys (database-defined)`));
267
+ console.log(chalk.gray(` • ${result.inferredRelationships?.length || 0} inferred from naming patterns`));
268
+ if (result.foreignKeys.length > 0 && !options.json) {
269
+ console.log(chalk.bold("\nKey Relationships:"));
270
+ for (const fk of result.foreignKeys.slice(0, 10)) {
271
+ console.log(chalk.cyan(` ${fk.fromSchema}.${fk.fromTable}.${fk.fromColumn}`));
272
+ console.log(chalk.gray(` → ${fk.toSchema}.${fk.toTable}.${fk.toColumn}`));
273
+ }
274
+ if (result.foreignKeys.length > 10) {
275
+ console.log(chalk.gray(` ... +${result.foreignKeys.length - 10} more`));
276
+ }
277
+ }
278
+ // Errors
279
+ if (result.errors.length > 0) {
280
+ console.log(chalk.yellow(`\nWarnings: ${result.errors.length}`));
281
+ for (const err of result.errors.slice(0, 5)) {
282
+ console.log(chalk.yellow(` ⚠ ${err}`));
283
+ }
284
+ }
285
+ // Output to file
286
+ if (options.output) {
287
+ writeFileSync(options.output, JSON.stringify(result, null, 2));
288
+ console.log(chalk.green(`\nResults saved to ${options.output}`));
289
+ }
290
+ // JSON output
291
+ if (options.json) {
292
+ console.log(JSON.stringify(result, null, 2));
293
+ }
294
+ // Sync to web app
295
+ if (options.sync) {
296
+ if (!apiKey) {
297
+ console.log(chalk.yellow("\nSync requires an API key. Run: datachonk config set apiKey <key>"));
298
+ }
299
+ else {
300
+ const syncSpinner = ora("Syncing to DataChonk...").start();
301
+ try {
302
+ const syncResponse = await fetch(`${scanEndpoint}/api/scan/sync`, {
303
+ method: "POST",
304
+ headers: {
305
+ "Content-Type": "application/json",
306
+ Authorization: `Bearer ${apiKey}`,
307
+ },
308
+ body: JSON.stringify(result),
309
+ });
310
+ if (syncResponse.ok) {
311
+ syncSpinner.succeed("Synced to DataChonk web app");
312
+ console.log(chalk.gray(` View your lineage at: ${scanEndpoint}/app`));
313
+ }
314
+ else {
315
+ syncSpinner.fail("Sync failed");
316
+ }
317
+ }
318
+ catch (err) {
319
+ syncSpinner.fail("Sync failed");
320
+ }
321
+ }
322
+ }
323
+ // Next steps
324
+ console.log(chalk.bold("\n📋 Next Steps\n"));
325
+ console.log(chalk.gray(" • Run 'datachonk lineage' to explore relationships"));
326
+ console.log(chalk.gray(" • Run 'datachonk generate staging --source <table>' to create dbt models"));
327
+ console.log(chalk.gray(" • Run 'datachonk scan --sync' to push results to the web app"));
328
+ }
329
+ catch (error) {
330
+ spinner.fail("Scan failed");
331
+ console.error(chalk.red(error instanceof Error ? error.message : "Unknown error"));
332
+ process.exit(1);
333
+ }
334
+ }
335
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const testCommand: Command;
3
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,eAAO,MAAM,WAAW,SA4GpB,CAAC"}
@@ -0,0 +1,244 @@
1
+ import { Command } from "commander";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+ import { glob } from "glob";
7
+ export const testCommand = new Command("test")
8
+ .description("Run data quality tests and validations")
9
+ .option("-m, --model <model>", "Test specific model")
10
+ .option("-t, --type <type>", "Test type: schema, data, freshness, all", "all")
11
+ .option("--dry-run", "Show tests that would run without executing")
12
+ .option("--generate", "Generate test suggestions for models")
13
+ .action(async (options) => {
14
+ const cwd = process.cwd();
15
+ const modelsPath = path.join(cwd, "models");
16
+ if (!fs.existsSync(modelsPath)) {
17
+ console.log(chalk.red("No models directory found. Run from dbt project root."));
18
+ process.exit(1);
19
+ }
20
+ if (options.generate) {
21
+ await generateTestSuggestions(cwd, options.model);
22
+ return;
23
+ }
24
+ console.log(chalk.cyan.bold("\n🧪 DataChonk Test Runner\n"));
25
+ const spinner = ora("Discovering tests...").start();
26
+ try {
27
+ const results = [];
28
+ // Find all schema YAML files
29
+ const yamlPattern = options.model
30
+ ? `models/**/*${options.model}*.yml`
31
+ : "models/**/*.yml";
32
+ const yamlFiles = await glob(yamlPattern, { cwd });
33
+ spinner.text = `Found ${yamlFiles.length} schema files`;
34
+ for (const yamlFile of yamlFiles) {
35
+ const content = fs.readFileSync(path.join(cwd, yamlFile), "utf-8");
36
+ const tests = extractTests(content, yamlFile);
37
+ for (const test of tests) {
38
+ if (options.dryRun) {
39
+ results.push({
40
+ model: test.model,
41
+ test: test.name,
42
+ status: "skip",
43
+ message: "Dry run - would execute",
44
+ });
45
+ }
46
+ else {
47
+ // Validate test configuration
48
+ const validation = validateTest(test);
49
+ results.push(validation);
50
+ }
51
+ }
52
+ }
53
+ // Run additional checks
54
+ if (options.type === "all" || options.type === "schema") {
55
+ const schemaResults = await runSchemaChecks(cwd, options.model);
56
+ results.push(...schemaResults);
57
+ }
58
+ spinner.succeed("Test discovery complete");
59
+ // Display results
60
+ console.log("\n" + chalk.bold("Test Results:"));
61
+ console.log("─".repeat(60));
62
+ const grouped = groupBy(results, "model");
63
+ for (const [model, modelResults] of Object.entries(grouped)) {
64
+ console.log(chalk.bold(`\n📦 ${model}`));
65
+ for (const result of modelResults) {
66
+ const icon = result.status === "pass" ? chalk.green("✓") :
67
+ result.status === "fail" ? chalk.red("✗") :
68
+ result.status === "warn" ? chalk.yellow("⚠") :
69
+ chalk.gray("○");
70
+ console.log(` ${icon} ${result.test}`);
71
+ if (result.message) {
72
+ console.log(chalk.gray(` ${result.message}`));
73
+ }
74
+ }
75
+ }
76
+ // Summary
77
+ const passed = results.filter(r => r.status === "pass").length;
78
+ const failed = results.filter(r => r.status === "fail").length;
79
+ const warned = results.filter(r => r.status === "warn").length;
80
+ const skipped = results.filter(r => r.status === "skip").length;
81
+ console.log("\n" + "─".repeat(60));
82
+ console.log(chalk.green(`✓ ${passed} passed`) + " " +
83
+ chalk.red(`✗ ${failed} failed`) + " " +
84
+ chalk.yellow(`⚠ ${warned} warnings`) + " " +
85
+ chalk.gray(`○ ${skipped} skipped`));
86
+ if (failed > 0) {
87
+ process.exit(1);
88
+ }
89
+ }
90
+ catch (error) {
91
+ spinner.fail("Test execution failed");
92
+ console.error(error);
93
+ process.exit(1);
94
+ }
95
+ });
96
+ function extractTests(yamlContent, filePath) {
97
+ const tests = [];
98
+ // Simple YAML parsing for tests
99
+ const modelMatch = yamlContent.match(/- name:\s*(\w+)/g);
100
+ const testMatches = yamlContent.match(/tests:\s*\n([\s\S]*?)(?=\n\s*-\s*name:|\n\s*columns:|\z)/g);
101
+ if (modelMatch) {
102
+ for (const match of modelMatch) {
103
+ const modelName = match.replace("- name:", "").trim();
104
+ // Check for common test patterns
105
+ if (yamlContent.includes("unique") && yamlContent.includes(modelName)) {
106
+ tests.push({ model: modelName, name: "unique", type: "schema" });
107
+ }
108
+ if (yamlContent.includes("not_null") && yamlContent.includes(modelName)) {
109
+ tests.push({ model: modelName, name: "not_null", type: "schema" });
110
+ }
111
+ if (yamlContent.includes("relationships") && yamlContent.includes(modelName)) {
112
+ tests.push({ model: modelName, name: "relationships", type: "schema" });
113
+ }
114
+ if (yamlContent.includes("accepted_values") && yamlContent.includes(modelName)) {
115
+ tests.push({ model: modelName, name: "accepted_values", type: "schema" });
116
+ }
117
+ }
118
+ }
119
+ return tests;
120
+ }
121
+ function validateTest(test) {
122
+ // Static validation of test configuration
123
+ return {
124
+ model: test.model,
125
+ test: test.name,
126
+ status: "pass",
127
+ message: "Test configuration valid",
128
+ };
129
+ }
130
+ async function runSchemaChecks(cwd, modelFilter) {
131
+ const results = [];
132
+ const sqlPattern = modelFilter
133
+ ? `models/**/*${modelFilter}*.sql`
134
+ : "models/**/*.sql";
135
+ const sqlFiles = await glob(sqlPattern, { cwd });
136
+ for (const sqlFile of sqlFiles) {
137
+ const modelName = path.basename(sqlFile, ".sql");
138
+ const content = fs.readFileSync(path.join(cwd, sqlFile), "utf-8");
139
+ // Check for SELECT *
140
+ if (content.includes("select *") || content.includes("SELECT *")) {
141
+ results.push({
142
+ model: modelName,
143
+ test: "no_select_star",
144
+ status: "warn",
145
+ message: "SELECT * detected - consider explicit columns",
146
+ });
147
+ }
148
+ // Check for missing config
149
+ if (!content.includes("config(") && !content.includes("{{config")) {
150
+ results.push({
151
+ model: modelName,
152
+ test: "has_config",
153
+ status: "warn",
154
+ message: "No config block found",
155
+ });
156
+ }
157
+ // Check for hardcoded dates
158
+ const datePattern = /'20\d{2}-\d{2}-\d{2}'/g;
159
+ if (datePattern.test(content)) {
160
+ results.push({
161
+ model: modelName,
162
+ test: "no_hardcoded_dates",
163
+ status: "warn",
164
+ message: "Hardcoded date literals detected",
165
+ });
166
+ }
167
+ // Check staging models don't use ref()
168
+ if (modelName.startsWith("stg_") && content.includes("ref(")) {
169
+ results.push({
170
+ model: modelName,
171
+ test: "staging_uses_source",
172
+ status: "fail",
173
+ message: "Staging models should use source(), not ref()",
174
+ });
175
+ }
176
+ }
177
+ return results;
178
+ }
179
+ async function generateTestSuggestions(cwd, modelFilter) {
180
+ console.log(chalk.cyan.bold("\n🔍 Generating Test Suggestions\n"));
181
+ const sqlPattern = modelFilter
182
+ ? `models/**/*${modelFilter}*.sql`
183
+ : "models/**/*.sql";
184
+ const sqlFiles = await glob(sqlPattern, { cwd });
185
+ for (const sqlFile of sqlFiles) {
186
+ const modelName = path.basename(sqlFile, ".sql");
187
+ const content = fs.readFileSync(path.join(cwd, sqlFile), "utf-8");
188
+ console.log(chalk.bold(`\n📦 ${modelName}`));
189
+ const suggestions = [];
190
+ // Detect potential primary keys
191
+ const idColumns = content.match(/(\w+_id|\w+_key|id)\b/gi);
192
+ if (idColumns) {
193
+ const uniqueIds = [...new Set(idColumns.map(c => c.toLowerCase()))];
194
+ for (const col of uniqueIds.slice(0, 3)) {
195
+ suggestions.push(`- unique: ${col}`);
196
+ suggestions.push(`- not_null: ${col}`);
197
+ }
198
+ }
199
+ // Detect status/type columns for accepted_values
200
+ const enumColumns = content.match(/(status|type|category|state)\b/gi);
201
+ if (enumColumns) {
202
+ for (const col of [...new Set(enumColumns)].slice(0, 2)) {
203
+ suggestions.push(`- accepted_values: ${col} (define valid values)`);
204
+ }
205
+ }
206
+ // Detect foreign key relationships
207
+ const fkColumns = content.match(/(\w+)_id\b/gi);
208
+ if (fkColumns) {
209
+ for (const col of [...new Set(fkColumns)].slice(0, 3)) {
210
+ const refTable = col.replace(/_id$/i, "");
211
+ if (refTable !== modelName) {
212
+ suggestions.push(`- relationships: ${col} -> ${refTable}.id`);
213
+ }
214
+ }
215
+ }
216
+ // Date columns
217
+ const dateColumns = content.match(/(\w+_at|\w+_date|created|updated|deleted)\b/gi);
218
+ if (dateColumns) {
219
+ for (const col of [...new Set(dateColumns)].slice(0, 2)) {
220
+ suggestions.push(`- not_null: ${col} (if required)`);
221
+ }
222
+ }
223
+ if (suggestions.length > 0) {
224
+ console.log(chalk.gray(" Suggested tests:"));
225
+ for (const s of suggestions) {
226
+ console.log(chalk.yellow(` ${s}`));
227
+ }
228
+ }
229
+ else {
230
+ console.log(chalk.gray(" No automatic suggestions - review manually"));
231
+ }
232
+ }
233
+ console.log(chalk.cyan("\n\nAdd these tests to your schema.yml files.\n"));
234
+ }
235
+ function groupBy(arr, key) {
236
+ return arr.reduce((acc, item) => {
237
+ const k = String(item[key]);
238
+ if (!acc[k])
239
+ acc[k] = [];
240
+ acc[k].push(item);
241
+ return acc;
242
+ }, {});
243
+ }
244
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}