@hypequery/cli 1.1.1 → 1.2.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 (77) hide show
  1. package/README.md +71 -149
  2. package/dist/bin/cli.js +21 -81
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +74 -105
  6. package/dist/commands/dev.d.ts +1 -0
  7. package/dist/commands/dev.d.ts.map +1 -1
  8. package/dist/commands/dev.js +180 -255
  9. package/dist/commands/generate-datasets.d.ts +14 -0
  10. package/dist/commands/generate-datasets.d.ts.map +1 -0
  11. package/dist/commands/generate-datasets.js +96 -0
  12. package/dist/commands/generate.d.ts +2 -0
  13. package/dist/commands/generate.d.ts.map +1 -1
  14. package/dist/commands/generate.js +112 -167
  15. package/dist/commands/init.d.ts +7 -1
  16. package/dist/commands/init.d.ts.map +1 -1
  17. package/dist/commands/init.js +337 -390
  18. package/dist/generators/clickhouse.d.ts +1 -1
  19. package/dist/generators/clickhouse.d.ts.map +1 -1
  20. package/dist/generators/clickhouse.js +10 -269
  21. package/dist/generators/dataset-generator.d.ts +16 -0
  22. package/dist/generators/dataset-generator.d.ts.map +1 -0
  23. package/dist/generators/dataset-generator.js +213 -0
  24. package/dist/generators/index.js +4 -4
  25. package/dist/templates/api.d.ts +9 -0
  26. package/dist/templates/api.d.ts.map +1 -0
  27. package/dist/templates/api.js +26 -0
  28. package/dist/templates/auth-scaffold.d.ts +17 -0
  29. package/dist/templates/auth-scaffold.d.ts.map +1 -0
  30. package/dist/templates/auth-scaffold.js +41 -0
  31. package/dist/templates/client.js +10 -1
  32. package/dist/templates/datasets.d.ts +5 -0
  33. package/dist/templates/datasets.d.ts.map +1 -0
  34. package/dist/templates/datasets.js +23 -0
  35. package/dist/templates/env.d.ts +2 -1
  36. package/dist/templates/env.d.ts.map +1 -1
  37. package/dist/templates/env.js +19 -6
  38. package/dist/templates/gitignore.js +4 -1
  39. package/dist/templates/queries.d.ts +3 -0
  40. package/dist/templates/queries.d.ts.map +1 -1
  41. package/dist/templates/queries.js +66 -9
  42. package/dist/test-utils.d.ts +0 -72
  43. package/dist/test-utils.d.ts.map +1 -1
  44. package/dist/test-utils.js +12 -138
  45. package/dist/utils/clickhouse-client.js +11 -58
  46. package/dist/utils/clickhouse-sql.d.ts +6 -0
  47. package/dist/utils/clickhouse-sql.d.ts.map +1 -0
  48. package/dist/utils/clickhouse-sql.js +18 -0
  49. package/dist/utils/clickhouse-type-utils.d.ts +6 -0
  50. package/dist/utils/clickhouse-type-utils.d.ts.map +1 -0
  51. package/dist/utils/clickhouse-type-utils.js +59 -0
  52. package/dist/utils/dependency-installer.d.ts +5 -1
  53. package/dist/utils/dependency-installer.d.ts.map +1 -1
  54. package/dist/utils/dependency-installer.js +117 -134
  55. package/dist/utils/detect-database.js +84 -195
  56. package/dist/utils/find-files.d.ts +3 -1
  57. package/dist/utils/find-files.d.ts.map +1 -1
  58. package/dist/utils/find-files.js +82 -148
  59. package/dist/utils/load-api.d.ts.map +1 -1
  60. package/dist/utils/load-api.js +207 -396
  61. package/dist/utils/logger.js +38 -42
  62. package/dist/utils/prompts.d.ts +14 -5
  63. package/dist/utils/prompts.d.ts.map +1 -1
  64. package/dist/utils/prompts.js +170 -244
  65. package/dist/utils/runtime-guards.d.ts +4 -0
  66. package/dist/utils/runtime-guards.d.ts.map +1 -0
  67. package/dist/utils/runtime-guards.js +9 -0
  68. package/dist/utils/sha256.d.ts +2 -0
  69. package/dist/utils/sha256.d.ts.map +1 -0
  70. package/dist/utils/sha256.js +4 -0
  71. package/package.json +4 -4
  72. package/dist/utils/error-messages.d.ts +0 -6
  73. package/dist/utils/error-messages.d.ts.map +0 -1
  74. package/dist/utils/error-messages.js +0 -19
  75. package/dist/utils/load-hypequery-config.d.ts +0 -7
  76. package/dist/utils/load-hypequery-config.d.ts.map +0 -1
  77. package/dist/utils/load-hypequery-config.js +0 -89
@@ -3,120 +3,116 @@ import chalk from 'chalk';
3
3
  * Calm, professional CLI logger
4
4
  * Follows Vercel-style output: informative, actionable, no noise
5
5
  */
6
- var Logger = /** @class */ (function () {
7
- function Logger(quiet) {
8
- if (quiet === void 0) { quiet = false; }
6
+ export class Logger {
7
+ quiet;
8
+ constructor(quiet = false) {
9
9
  this.quiet = quiet;
10
10
  }
11
11
  /**
12
12
  * Success message with checkmark
13
13
  */
14
- Logger.prototype.success = function (message) {
14
+ success(message) {
15
15
  if (!this.quiet) {
16
16
  console.log(chalk.green('✓') + ' ' + message);
17
17
  }
18
- };
18
+ }
19
19
  /**
20
20
  * Error message with X mark
21
21
  */
22
- Logger.prototype.error = function (message) {
22
+ error(message) {
23
23
  console.error(chalk.red('✗') + ' ' + message);
24
- };
24
+ }
25
25
  /**
26
26
  * Warning message with warning symbol
27
27
  */
28
- Logger.prototype.warn = function (message) {
28
+ warn(message) {
29
29
  if (!this.quiet) {
30
30
  console.warn(chalk.yellow('⚠') + ' ' + message);
31
31
  }
32
- };
32
+ }
33
33
  /**
34
34
  * Info message (no symbol)
35
35
  */
36
- Logger.prototype.info = function (message) {
36
+ info(message) {
37
37
  if (!this.quiet) {
38
38
  console.log(' ' + message);
39
39
  }
40
- };
40
+ }
41
41
  /**
42
42
  * Reload/change message
43
43
  */
44
- Logger.prototype.reload = function (message) {
44
+ reload(message) {
45
45
  if (!this.quiet) {
46
46
  console.log(chalk.blue('↻') + ' ' + message);
47
47
  }
48
- };
48
+ }
49
49
  /**
50
50
  * Section header
51
51
  */
52
- Logger.prototype.header = function (message) {
52
+ header(message) {
53
53
  if (!this.quiet) {
54
54
  console.log('\n' + chalk.bold(message) + '\n');
55
55
  }
56
- };
56
+ }
57
57
  /**
58
58
  * Empty line
59
59
  */
60
- Logger.prototype.newline = function () {
60
+ newline() {
61
61
  if (!this.quiet) {
62
62
  console.log();
63
63
  }
64
- };
64
+ }
65
65
  /**
66
66
  * Indented message (for sub-items)
67
67
  */
68
- Logger.prototype.indent = function (message) {
68
+ indent(message) {
69
69
  if (!this.quiet) {
70
70
  console.log(' ' + message);
71
71
  }
72
- };
72
+ }
73
73
  /**
74
74
  * Boxed URL output
75
75
  */
76
- Logger.prototype.box = function (lines) {
76
+ box(lines) {
77
77
  if (!this.quiet) {
78
- var maxLength = Math.max.apply(Math, lines.map(function (l) { return l.length; }));
79
- var border = '─'.repeat(maxLength + 4);
78
+ const maxLength = Math.max(...lines.map(l => l.length));
79
+ const border = '─'.repeat(maxLength + 4);
80
80
  console.log(' ┌' + border + '┐');
81
- for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
82
- var line = lines_1[_i];
83
- var padding = ' '.repeat(maxLength - line.length);
81
+ for (const line of lines) {
82
+ const padding = ' '.repeat(maxLength - line.length);
84
83
  console.log(' │ ' + line + padding + ' │');
85
84
  }
86
85
  console.log(' └' + border + '┘');
87
86
  }
88
- };
87
+ }
89
88
  /**
90
89
  * Table output (for dev server stats)
91
90
  */
92
- Logger.prototype.table = function (headers, rows) {
91
+ table(headers, rows) {
93
92
  if (!this.quiet) {
94
- var columnWidths_1 = headers.map(function (header, i) {
95
- var maxContentWidth = Math.max.apply(Math, rows.map(function (row) { return (row[i] || '').length; }));
93
+ const columnWidths = headers.map((header, i) => {
94
+ const maxContentWidth = Math.max(...rows.map(row => (row[i] || '').length));
96
95
  return Math.max(header.length, maxContentWidth);
97
96
  });
98
97
  // Header
99
- var headerRow = headers
100
- .map(function (h, i) { return h.padEnd(columnWidths_1[i]); })
98
+ const headerRow = headers
99
+ .map((h, i) => h.padEnd(columnWidths[i]))
101
100
  .join(' ');
102
101
  console.log(' ' + chalk.bold(headerRow));
103
102
  // Rows
104
- for (var _i = 0, rows_1 = rows; _i < rows_1.length; _i++) {
105
- var row = rows_1[_i];
106
- var formattedRow = row
107
- .map(function (cell, i) { return cell.padEnd(columnWidths_1[i]); })
103
+ for (const row of rows) {
104
+ const formattedRow = row
105
+ .map((cell, i) => cell.padEnd(columnWidths[i]))
108
106
  .join(' ');
109
107
  console.log(' ' + formattedRow);
110
108
  }
111
109
  }
112
- };
110
+ }
113
111
  /**
114
112
  * Raw console.log (bypass quiet mode)
115
113
  */
116
- Logger.prototype.raw = function (message) {
114
+ raw(message) {
117
115
  console.log(message);
118
- };
119
- return Logger;
120
- }());
121
- export { Logger };
122
- export var logger = new Logger();
116
+ }
117
+ }
118
+ export const logger = new Logger();
@@ -1,8 +1,3 @@
1
- import type { DatabaseType } from './detect-database.js';
2
- /**
3
- * Prompt for database type selection
4
- */
5
- export declare function promptDatabaseType(): Promise<DatabaseType | null>;
6
1
  /**
7
2
  * Prompt for ClickHouse connection details
8
3
  */
@@ -16,6 +11,8 @@ export declare function promptClickHouseConnection(): Promise<{
16
11
  * Prompt for output directory
17
12
  */
18
13
  export declare function promptOutputDirectory(): Promise<string>;
14
+ export type InitStyle = 'queries' | 'datasets';
15
+ export declare function promptInitStyle(): Promise<InitStyle>;
19
16
  /**
20
17
  * Prompt for example query generation
21
18
  */
@@ -24,6 +21,10 @@ export declare function promptGenerateExample(): Promise<boolean>;
24
21
  * Prompt for table selection (for example query)
25
22
  */
26
23
  export declare function promptTableSelection(tables: string[]): Promise<string | null>;
24
+ /**
25
+ * Prompt for dataset table selection.
26
+ */
27
+ export declare function promptDatasetTableSelection(tables: string[], defaultTables?: string[]): Promise<string[]>;
27
28
  /**
28
29
  * Confirm overwrite of existing files
29
30
  */
@@ -36,4 +37,12 @@ export declare function promptRetry(message: string): Promise<boolean>;
36
37
  * Ask if user wants to continue without DB connection
37
38
  */
38
39
  export declare function promptContinueWithoutDb(): Promise<boolean>;
40
+ /**
41
+ * Confirm destructive operations (DROP TABLE, DROP COLUMN)
42
+ */
43
+ export declare function confirmDestructiveOperation(operations: string[]): Promise<boolean>;
44
+ /**
45
+ * Confirm mutation operations (type changes that trigger ClickHouse mutations)
46
+ */
47
+ export declare function confirmMutationOperation(): Promise<boolean>;
39
48
  //# sourceMappingURL=prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAQzD;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAavE;AAED;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CAAC,CAkCR;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,CA6B7D;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAS9D;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA0BnF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CASxE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASnE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC,CAShE"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/utils/prompts.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CAAC,CAkCR;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,CA6B7D;AAED,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAE/C,wBAAsB,eAAe,IAAI,OAAO,CAAC,SAAS,CAAC,CAa1D;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAS9D;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA0BnF;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,MAAM,EAAE,EAChB,aAAa,GAAE,MAAM,EAAO,GAC3B,OAAO,CAAC,MAAM,EAAE,CAAC,CA2BnB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CASxE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASnE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC,CAShE;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CASxF;AAED;;GAEG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,OAAO,CAAC,CASjE"}
@@ -1,283 +1,209 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
- function verb(n) { return function (v) { return step([n, v]); }; }
14
- function step(op) {
15
- if (f) throw new TypeError("Generator is already executing.");
16
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
- if (y = 0, t) op = [op[0] & 2, t.value];
19
- switch (op[0]) {
20
- case 0: case 1: t = op; break;
21
- case 4: _.label++; return { value: op[1], done: false };
22
- case 5: _.label++; y = op[1]; op = [0]; continue;
23
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
- default:
25
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
- if (t[2]) _.ops.pop();
30
- _.trys.pop(); continue;
31
- }
32
- op = body.call(thisArg, _);
33
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
- }
36
- };
37
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
38
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
39
- if (ar || !(i in from)) {
40
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
41
- ar[i] = from[i];
42
- }
43
- }
44
- return to.concat(ar || Array.prototype.slice.call(from));
45
- };
46
1
  import prompts from 'prompts';
47
2
  import { logger } from './logger.js';
48
- var noop = function () { return undefined; };
3
+ const noop = () => undefined;
49
4
  // Configure prompts to not exit on cancel
50
5
  prompts.override({ onCancel: noop });
51
- /**
52
- * Prompt for database type selection
53
- */
54
- export function promptDatabaseType() {
55
- return __awaiter(this, void 0, void 0, function () {
56
- var response;
57
- return __generator(this, function (_a) {
58
- switch (_a.label) {
59
- case 0: return [4 /*yield*/, prompts({
60
- type: 'select',
61
- name: 'database',
62
- message: 'Which database are you using?',
63
- choices: [
64
- { title: 'ClickHouse', value: 'clickhouse' },
65
- { title: 'BigQuery (coming soon)', value: 'bigquery', disabled: true },
66
- ],
67
- initial: 0,
68
- })];
69
- case 1:
70
- response = _a.sent();
71
- return [2 /*return*/, response.database || null];
72
- }
73
- });
74
- });
75
- }
76
6
  /**
77
7
  * Prompt for ClickHouse connection details
78
8
  */
79
- export function promptClickHouseConnection() {
80
- return __awaiter(this, void 0, void 0, function () {
81
- var response;
82
- var _a, _b, _c, _d;
83
- return __generator(this, function (_e) {
84
- switch (_e.label) {
85
- case 0: return [4 /*yield*/, prompts([
86
- {
87
- type: 'text',
88
- name: 'host',
89
- message: 'ClickHouse host (or skip to configure later):',
90
- initial: (_a = process.env.CLICKHOUSE_HOST) !== null && _a !== void 0 ? _a : '',
91
- },
92
- {
93
- type: 'text',
94
- name: 'database',
95
- message: 'Database:',
96
- initial: (_b = process.env.CLICKHOUSE_DATABASE) !== null && _b !== void 0 ? _b : '',
97
- },
98
- {
99
- type: 'text',
100
- name: 'username',
101
- message: 'Username:',
102
- initial: (_c = process.env.CLICKHOUSE_USERNAME) !== null && _c !== void 0 ? _c : '',
103
- },
104
- {
105
- type: 'password',
106
- name: 'password',
107
- message: 'Password:',
108
- initial: (_d = process.env.CLICKHOUSE_PASSWORD) !== null && _d !== void 0 ? _d : '',
109
- },
110
- ])];
111
- case 1:
112
- response = _e.sent();
113
- // If user cancelled or skipped
114
- if (!response.host) {
115
- return [2 /*return*/, null];
116
- }
117
- return [2 /*return*/, response];
118
- }
119
- });
120
- });
9
+ export async function promptClickHouseConnection() {
10
+ const response = await prompts([
11
+ {
12
+ type: 'text',
13
+ name: 'host',
14
+ message: 'ClickHouse URL (or skip to configure later):',
15
+ initial: process.env.CLICKHOUSE_URL ?? process.env.CLICKHOUSE_HOST ?? '',
16
+ },
17
+ {
18
+ type: 'text',
19
+ name: 'database',
20
+ message: 'Database:',
21
+ initial: process.env.CLICKHOUSE_DATABASE ?? '',
22
+ },
23
+ {
24
+ type: 'text',
25
+ name: 'username',
26
+ message: 'Username:',
27
+ initial: process.env.CLICKHOUSE_USERNAME ?? '',
28
+ },
29
+ {
30
+ type: 'password',
31
+ name: 'password',
32
+ message: 'Password:',
33
+ initial: process.env.CLICKHOUSE_PASSWORD ?? '',
34
+ },
35
+ ]);
36
+ // If user cancelled or skipped
37
+ if (!response.host) {
38
+ return null;
39
+ }
40
+ return response;
121
41
  }
122
42
  /**
123
43
  * Prompt for output directory
124
44
  */
125
- export function promptOutputDirectory() {
126
- return __awaiter(this, void 0, void 0, function () {
127
- var response, customResponse;
128
- return __generator(this, function (_a) {
129
- switch (_a.label) {
130
- case 0: return [4 /*yield*/, prompts({
131
- type: 'select',
132
- name: 'directory',
133
- message: 'Where should we create your analytics files?',
134
- choices: [
135
- { title: 'analytics/ (recommended)', value: 'analytics' },
136
- { title: 'src/analytics/', value: 'src/analytics' },
137
- { title: 'Custom path...', value: 'custom' },
138
- ],
139
- initial: 0,
140
- })];
141
- case 1:
142
- response = _a.sent();
143
- if (!response.directory) {
144
- return [2 /*return*/, 'analytics']; // Default fallback
145
- }
146
- if (!(response.directory === 'custom')) return [3 /*break*/, 3];
147
- return [4 /*yield*/, prompts({
148
- type: 'text',
149
- name: 'path',
150
- message: 'Enter custom path:',
151
- initial: 'analytics',
152
- })];
153
- case 2:
154
- customResponse = _a.sent();
155
- return [2 /*return*/, customResponse.path || 'analytics'];
156
- case 3: return [2 /*return*/, response.directory];
157
- }
45
+ export async function promptOutputDirectory() {
46
+ const response = await prompts({
47
+ type: 'select',
48
+ name: 'directory',
49
+ message: 'Where should we create your analytics files?',
50
+ choices: [
51
+ { title: 'analytics/ (recommended)', value: 'analytics' },
52
+ { title: 'src/analytics/', value: 'src/analytics' },
53
+ { title: 'Custom path...', value: 'custom' },
54
+ ],
55
+ initial: 0,
56
+ });
57
+ if (!response.directory) {
58
+ return 'analytics'; // Default fallback
59
+ }
60
+ if (response.directory === 'custom') {
61
+ const customResponse = await prompts({
62
+ type: 'text',
63
+ name: 'path',
64
+ message: 'Enter custom path:',
65
+ initial: 'analytics',
158
66
  });
67
+ return customResponse.path || 'analytics';
68
+ }
69
+ return response.directory;
70
+ }
71
+ export async function promptInitStyle() {
72
+ const response = await prompts({
73
+ type: 'select',
74
+ name: 'style',
75
+ message: 'Choose your dev API style',
76
+ choices: [
77
+ { title: 'Query builder routes', value: 'queries' },
78
+ { title: 'Datasets semantic API', value: 'datasets' },
79
+ ],
80
+ initial: 0,
159
81
  });
82
+ return response.style ?? 'queries';
160
83
  }
161
84
  /**
162
85
  * Prompt for example query generation
163
86
  */
164
- export function promptGenerateExample() {
165
- return __awaiter(this, void 0, void 0, function () {
166
- var response;
167
- var _a;
168
- return __generator(this, function (_b) {
169
- switch (_b.label) {
170
- case 0: return [4 /*yield*/, prompts({
171
- type: 'confirm',
172
- name: 'generate',
173
- message: 'Generate an example query?',
174
- initial: true,
175
- })];
176
- case 1:
177
- response = _b.sent();
178
- return [2 /*return*/, (_a = response.generate) !== null && _a !== void 0 ? _a : false];
179
- }
180
- });
87
+ export async function promptGenerateExample() {
88
+ const response = await prompts({
89
+ type: 'confirm',
90
+ name: 'generate',
91
+ message: 'Generate an example query?',
92
+ initial: true,
181
93
  });
94
+ return response.generate ?? false;
182
95
  }
183
96
  /**
184
97
  * Prompt for table selection (for example query)
185
98
  */
186
- export function promptTableSelection(tables) {
187
- return __awaiter(this, void 0, void 0, function () {
188
- var choices, response;
189
- return __generator(this, function (_a) {
190
- switch (_a.label) {
191
- case 0:
192
- if (tables.length === 0) {
193
- return [2 /*return*/, null];
194
- }
195
- // Warn if showing truncated list
196
- if (tables.length > 10) {
197
- logger.warn("Showing first 10 of ".concat(tables.length, " tables"));
198
- logger.indent('You can select a different table by editing the generated file');
199
- logger.newline();
200
- }
201
- choices = __spreadArray(__spreadArray([], tables.slice(0, 10).map(function (table) { return ({ title: table, value: table }); }), true), [
202
- { title: 'Skip example', value: null },
203
- ], false);
204
- return [4 /*yield*/, prompts({
205
- type: 'select',
206
- name: 'table',
207
- message: 'Which table should we use for the example?',
208
- choices: choices,
209
- initial: 0,
210
- })];
211
- case 1:
212
- response = _a.sent();
213
- return [2 /*return*/, response.table];
214
- }
215
- });
99
+ export async function promptTableSelection(tables) {
100
+ if (tables.length === 0) {
101
+ return null;
102
+ }
103
+ // Warn if showing truncated list
104
+ if (tables.length > 10) {
105
+ logger.warn(`Showing first 10 of ${tables.length} tables`);
106
+ logger.indent('You can select a different table by editing the generated file');
107
+ logger.newline();
108
+ }
109
+ const choices = [
110
+ ...tables.slice(0, 10).map(table => ({ title: table, value: table })),
111
+ { title: 'Skip example', value: null },
112
+ ];
113
+ const response = await prompts({
114
+ type: 'select',
115
+ name: 'table',
116
+ message: 'Which table should we use for the example?',
117
+ choices,
118
+ initial: 0,
216
119
  });
120
+ return response.table;
121
+ }
122
+ /**
123
+ * Prompt for dataset table selection.
124
+ */
125
+ export async function promptDatasetTableSelection(tables, defaultTables = []) {
126
+ if (tables.length === 0) {
127
+ return [];
128
+ }
129
+ // Warn if showing truncated list
130
+ if (tables.length > 20) {
131
+ logger.warn(`Showing first 20 of ${tables.length} tables`);
132
+ logger.indent('Use --tables or --all-tables for more control in larger databases');
133
+ logger.newline();
134
+ }
135
+ const defaults = new Set(defaultTables);
136
+ const response = await prompts({
137
+ type: 'multiselect',
138
+ name: 'tables',
139
+ message: 'Which tables should we scaffold as datasets?',
140
+ choices: tables.slice(0, 20).map(table => ({
141
+ title: table,
142
+ value: table,
143
+ selected: defaults.has(table),
144
+ })),
145
+ min: 0,
146
+ instructions: false,
147
+ });
148
+ return response.tables ?? [];
217
149
  }
218
150
  /**
219
151
  * Confirm overwrite of existing files
220
152
  */
221
- export function confirmOverwrite(files) {
222
- return __awaiter(this, void 0, void 0, function () {
223
- var response;
224
- var _a;
225
- return __generator(this, function (_b) {
226
- switch (_b.label) {
227
- case 0: return [4 /*yield*/, prompts({
228
- type: 'confirm',
229
- name: 'overwrite',
230
- message: "The following files will be overwritten:\n".concat(files.map(function (f) { return " \u2022 ".concat(f); }).join('\n'), "\n\nContinue?"),
231
- initial: false,
232
- })];
233
- case 1:
234
- response = _b.sent();
235
- return [2 /*return*/, (_a = response.overwrite) !== null && _a !== void 0 ? _a : false];
236
- }
237
- });
153
+ export async function confirmOverwrite(files) {
154
+ const response = await prompts({
155
+ type: 'confirm',
156
+ name: 'overwrite',
157
+ message: `The following files will be overwritten:\n${files.map(f => ` • ${f}`).join('\n')}\n\nContinue?`,
158
+ initial: false,
238
159
  });
160
+ return response.overwrite ?? false;
239
161
  }
240
162
  /**
241
163
  * Retry prompt for failed operations
242
164
  */
243
- export function promptRetry(message) {
244
- return __awaiter(this, void 0, void 0, function () {
245
- var response;
246
- var _a;
247
- return __generator(this, function (_b) {
248
- switch (_b.label) {
249
- case 0: return [4 /*yield*/, prompts({
250
- type: 'confirm',
251
- name: 'retry',
252
- message: message,
253
- initial: true,
254
- })];
255
- case 1:
256
- response = _b.sent();
257
- return [2 /*return*/, (_a = response.retry) !== null && _a !== void 0 ? _a : false];
258
- }
259
- });
165
+ export async function promptRetry(message) {
166
+ const response = await prompts({
167
+ type: 'confirm',
168
+ name: 'retry',
169
+ message,
170
+ initial: true,
260
171
  });
172
+ return response.retry ?? false;
261
173
  }
262
174
  /**
263
175
  * Ask if user wants to continue without DB connection
264
176
  */
265
- export function promptContinueWithoutDb() {
266
- return __awaiter(this, void 0, void 0, function () {
267
- var response;
268
- var _a;
269
- return __generator(this, function (_b) {
270
- switch (_b.label) {
271
- case 0: return [4 /*yield*/, prompts({
272
- type: 'confirm',
273
- name: 'continue',
274
- message: 'Continue setup without database connection?',
275
- initial: true,
276
- })];
277
- case 1:
278
- response = _b.sent();
279
- return [2 /*return*/, (_a = response.continue) !== null && _a !== void 0 ? _a : false];
280
- }
281
- });
177
+ export async function promptContinueWithoutDb() {
178
+ const response = await prompts({
179
+ type: 'confirm',
180
+ name: 'continue',
181
+ message: 'Continue setup without database connection?',
182
+ initial: true,
183
+ });
184
+ return response.continue ?? false;
185
+ }
186
+ /**
187
+ * Confirm destructive operations (DROP TABLE, DROP COLUMN)
188
+ */
189
+ export async function confirmDestructiveOperation(operations) {
190
+ const response = await prompts({
191
+ type: 'confirm',
192
+ name: 'confirm',
193
+ message: `This migration includes ${operations.length} destructive operation(s). Continue?`,
194
+ initial: false,
195
+ });
196
+ return response.confirm ?? false;
197
+ }
198
+ /**
199
+ * Confirm mutation operations (type changes that trigger ClickHouse mutations)
200
+ */
201
+ export async function confirmMutationOperation() {
202
+ const response = await prompts({
203
+ type: 'confirm',
204
+ name: 'confirm',
205
+ message: 'This migration will trigger ClickHouse mutations. Continue?',
206
+ initial: false,
282
207
  });
208
+ return response.confirm ?? false;
283
209
  }