@hypequery/cli 1.1.0 → 1.1.2

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.
@@ -38,7 +38,7 @@ import { mkdir, writeFile, readFile, access } from 'node:fs/promises';
38
38
  import path from 'node:path';
39
39
  import ora from 'ora';
40
40
  import { logger } from '../utils/logger.js';
41
- import { promptDatabaseType, promptClickHouseConnection, promptOutputDirectory, promptGenerateExample, promptTableSelection, confirmOverwrite, promptRetry, promptContinueWithoutDb, } from '../utils/prompts.js';
41
+ import { promptClickHouseConnection, promptOutputDirectory, promptGenerateExample, promptTableSelection, confirmOverwrite, promptRetry, promptContinueWithoutDb, } from '../utils/prompts.js';
42
42
  import { validateConnection, getTableCount, getTables, } from '../utils/detect-database.js';
43
43
  import { hasEnvFile, hasGitignore } from '../utils/find-files.js';
44
44
  import { generateEnvTemplate, appendToEnv } from '../templates/env.js';
@@ -46,53 +46,25 @@ import { generateClientTemplate } from '../templates/client.js';
46
46
  import { generateQueriesTemplate } from '../templates/queries.js';
47
47
  import { appendToGitignore } from '../templates/gitignore.js';
48
48
  import { getTypeGenerator } from '../generators/index.js';
49
- import { installServeDependencies } from '../utils/dependency-installer.js';
50
- function determineDatabase(options) {
51
- return __awaiter(this, void 0, void 0, function () {
52
- var dbType, _a;
53
- var _b;
54
- return __generator(this, function (_c) {
55
- switch (_c.label) {
56
- case 0:
57
- if (!((_b = options.database) !== null && _b !== void 0)) return [3 /*break*/, 1];
58
- _a = _b;
59
- return [3 /*break*/, 3];
60
- case 1: return [4 /*yield*/, promptDatabaseType()];
61
- case 2:
62
- _a = (_c.sent());
63
- _c.label = 3;
64
- case 3:
65
- dbType = _a;
66
- if (!dbType) {
67
- logger.info('Setup cancelled');
68
- process.exit(0);
69
- }
70
- if (dbType !== 'clickhouse') {
71
- logger.error("".concat(dbType, " is not yet supported. Only ClickHouse is available."));
72
- process.exit(1);
73
- }
74
- return [2 /*return*/, dbType];
75
- }
76
- });
77
- });
78
- }
49
+ import { installScaffoldDependencies } from '../utils/dependency-installer.js';
79
50
  function resolveConnectionConfig(options) {
80
51
  return __awaiter(this, void 0, void 0, function () {
81
52
  var required;
82
53
  var _a;
83
54
  return __generator(this, function (_b) {
84
55
  if (options.noInteractive) {
85
- required = function (key) {
86
- var value = process.env[key];
56
+ required = function (keys) {
57
+ var values = Array.isArray(keys) ? keys : [keys];
58
+ var value = values.map(function (key) { return process.env[key]; }).find(Boolean);
87
59
  if (!value) {
88
- throw new Error("Missing ".concat(key, ". Provide ClickHouse connection info via environment variables when using --no-interactive."));
60
+ throw new Error("Missing ".concat(values.join(' or '), ". Provide ClickHouse connection info via environment variables when using --no-interactive."));
89
61
  }
90
62
  return value;
91
63
  };
92
64
  return [2 /*return*/, {
93
- host: required('CLICKHOUSE_HOST'),
65
+ host: required(['CLICKHOUSE_URL', 'CLICKHOUSE_HOST']),
94
66
  database: required('CLICKHOUSE_DATABASE'),
95
- username: required('CLICKHOUSE_USERNAME'),
67
+ username: required(['CLICKHOUSE_USERNAME', 'CLICKHOUSE_USER']),
96
68
  password: (_a = process.env.CLICKHOUSE_PASSWORD) !== null && _a !== void 0 ? _a : '',
97
69
  }];
98
70
  }
@@ -100,18 +72,19 @@ function resolveConnectionConfig(options) {
100
72
  });
101
73
  });
102
74
  }
103
- function testConnection(connectionConfig, dbType) {
75
+ function testConnection(connectionConfig) {
104
76
  return __awaiter(this, void 0, void 0, function () {
105
77
  var spinner, isValid, tableCount;
106
78
  return __generator(this, function (_a) {
107
79
  switch (_a.label) {
108
80
  case 0:
109
81
  spinner = ora('Testing connection...').start();
82
+ process.env.CLICKHOUSE_URL = connectionConfig.host;
110
83
  process.env.CLICKHOUSE_HOST = connectionConfig.host;
111
84
  process.env.CLICKHOUSE_DATABASE = connectionConfig.database;
112
85
  process.env.CLICKHOUSE_USERNAME = connectionConfig.username;
113
86
  process.env.CLICKHOUSE_PASSWORD = connectionConfig.password;
114
- return [4 /*yield*/, validateConnection(dbType)];
87
+ return [4 /*yield*/, validateConnection('clickhouse')];
115
88
  case 1:
116
89
  isValid = _a.sent();
117
90
  if (!isValid) {
@@ -127,7 +100,7 @@ function testConnection(connectionConfig, dbType) {
127
100
  logger.newline();
128
101
  return [2 /*return*/, { hasValidConnection: false, tableCount: 0 }];
129
102
  }
130
- return [4 /*yield*/, getTableCount(dbType)];
103
+ return [4 /*yield*/, getTableCount('clickhouse')];
131
104
  case 2:
132
105
  tableCount = _a.sent();
133
106
  spinner.succeed("Connected successfully (".concat(tableCount, " tables found)"));
@@ -139,47 +112,48 @@ function testConnection(connectionConfig, dbType) {
139
112
  }
140
113
  export function initCommand() {
141
114
  return __awaiter(this, arguments, void 0, function (options) {
142
- var dbType, connectionConfig, hasValidConnection, tableCount, _a, valid, count, retry, continueWithout, outputDir, resolvedOutputDir, filesToCreate, existingFiles, _i, filesToCreate_1, file, _b, shouldOverwrite, generateExample, selectedTable, tables, envPath, envExists, existingEnv, newEnv, envPath, envExists, placeholderConfig, schemaPath, typeSpinner, generator, error_1, clientPath, queriesPath, gitignorePath, gitignoreExists, existingGitignore, newGitignore, exampleQueryKey;
115
+ var noInteractive, connectionConfig, hasValidConnection, tableCount, _a, valid, count, retry, continueWithout, outputDir, resolvedOutputDir, filesToCreate, existingFiles, _i, filesToCreate_1, file, _b, shouldOverwrite, _c, generateExample, selectedTable, tables, envPath, envExists, existingEnv, newEnv, envPath, envExists, placeholderConfig, schemaPath, typeSpinner, generator, error_1, clientPath, queriesPath, gitignorePath, gitignoreExists, existingGitignore, newGitignore, exampleQueryKey;
143
116
  if (options === void 0) { options = {}; }
144
- return __generator(this, function (_c) {
145
- switch (_c.label) {
117
+ return __generator(this, function (_d) {
118
+ switch (_d.label) {
146
119
  case 0:
120
+ noInteractive = options.noInteractive === true || options.interactive === false;
147
121
  logger.newline();
148
122
  logger.header('Welcome to hypequery!');
149
123
  logger.info("Let's set up your analytics layer.");
150
124
  logger.newline();
151
- return [4 /*yield*/, determineDatabase(options)];
152
- case 1:
153
- dbType = _c.sent();
154
125
  return [4 /*yield*/, resolveConnectionConfig(options)];
155
- case 2:
156
- connectionConfig = _c.sent();
126
+ case 1:
127
+ connectionConfig = _d.sent();
157
128
  hasValidConnection = false;
158
129
  tableCount = 0;
159
- if (!!connectionConfig) return [3 /*break*/, 3];
130
+ if (!!connectionConfig) return [3 /*break*/, 2];
160
131
  logger.info('Skipping database connection for now.');
161
132
  logger.newline();
162
- return [3 /*break*/, 8];
163
- case 3:
164
- if (!options.skipConnection) return [3 /*break*/, 4];
133
+ return [3 /*break*/, 7];
134
+ case 2:
135
+ if (!options.skipConnection) return [3 /*break*/, 3];
165
136
  logger.info('Skipping database connection test (requested).');
166
137
  logger.newline();
167
- return [3 /*break*/, 8];
168
- case 4: return [4 /*yield*/, testConnection(connectionConfig, dbType)];
169
- case 5:
170
- _a = _c.sent(), valid = _a.hasValidConnection, count = _a.tableCount;
138
+ return [3 /*break*/, 7];
139
+ case 3: return [4 /*yield*/, testConnection(connectionConfig)];
140
+ case 4:
141
+ _a = _d.sent(), valid = _a.hasValidConnection, count = _a.tableCount;
171
142
  hasValidConnection = valid;
172
143
  tableCount = count;
173
- if (!!hasValidConnection) return [3 /*break*/, 8];
144
+ if (!!hasValidConnection) return [3 /*break*/, 7];
145
+ if (noInteractive) {
146
+ throw new Error('Failed to connect to ClickHouse in non-interactive mode. Check your environment variables or use interactive setup.');
147
+ }
174
148
  return [4 /*yield*/, promptRetry('Try again?')];
175
- case 6:
176
- retry = _c.sent();
149
+ case 5:
150
+ retry = _d.sent();
177
151
  if (retry) {
178
152
  return [2 /*return*/, initCommand(options)];
179
153
  }
180
154
  return [4 /*yield*/, promptContinueWithoutDb()];
181
- case 7:
182
- continueWithout = _c.sent();
155
+ case 6:
156
+ continueWithout = _d.sent();
183
157
  if (!continueWithout) {
184
158
  logger.info('Setup cancelled');
185
159
  process.exit(0);
@@ -189,20 +163,20 @@ export function initCommand() {
189
163
  logger.info('You can configure the connection later in .env');
190
164
  logger.newline();
191
165
  connectionConfig = null;
192
- _c.label = 8;
193
- case 8:
166
+ _d.label = 7;
167
+ case 7:
194
168
  outputDir = options.path;
195
- if (!(!outputDir && !options.noInteractive)) return [3 /*break*/, 10];
169
+ if (!(!outputDir && !noInteractive)) return [3 /*break*/, 9];
196
170
  return [4 /*yield*/, promptOutputDirectory()];
171
+ case 8:
172
+ outputDir = _d.sent();
173
+ return [3 /*break*/, 10];
197
174
  case 9:
198
- outputDir = _c.sent();
199
- return [3 /*break*/, 11];
200
- case 10:
201
175
  if (!outputDir) {
202
176
  outputDir = 'analytics';
203
177
  }
204
- _c.label = 11;
205
- case 11:
178
+ _d.label = 10;
179
+ case 10:
206
180
  resolvedOutputDir = path.resolve(process.cwd(), outputDir);
207
181
  filesToCreate = [
208
182
  path.join(resolvedOutputDir, 'client.ts'),
@@ -211,170 +185,176 @@ export function initCommand() {
211
185
  ];
212
186
  existingFiles = [];
213
187
  _i = 0, filesToCreate_1 = filesToCreate;
214
- _c.label = 12;
215
- case 12:
216
- if (!(_i < filesToCreate_1.length)) return [3 /*break*/, 17];
188
+ _d.label = 11;
189
+ case 11:
190
+ if (!(_i < filesToCreate_1.length)) return [3 /*break*/, 16];
217
191
  file = filesToCreate_1[_i];
218
- _c.label = 13;
219
- case 13:
220
- _c.trys.push([13, 15, , 16]);
192
+ _d.label = 12;
193
+ case 12:
194
+ _d.trys.push([12, 14, , 15]);
221
195
  return [4 /*yield*/, access(file)];
222
- case 14:
223
- _c.sent();
196
+ case 13:
197
+ _d.sent();
224
198
  existingFiles.push(path.relative(process.cwd(), file));
225
- return [3 /*break*/, 16];
199
+ return [3 /*break*/, 15];
200
+ case 14:
201
+ _b = _d.sent();
202
+ return [3 /*break*/, 15];
226
203
  case 15:
227
- _b = _c.sent();
228
- return [3 /*break*/, 16];
229
- case 16:
230
204
  _i++;
231
- return [3 /*break*/, 12];
232
- case 17:
233
- if (!(existingFiles.length > 0 && !options.force)) return [3 /*break*/, 19];
205
+ return [3 /*break*/, 11];
206
+ case 16:
207
+ if (!(existingFiles.length > 0 && !options.force)) return [3 /*break*/, 20];
234
208
  logger.warn('Files already exist');
235
209
  logger.newline();
236
- return [4 /*yield*/, confirmOverwrite(existingFiles)];
210
+ if (!noInteractive) return [3 /*break*/, 17];
211
+ _c = false;
212
+ return [3 /*break*/, 19];
213
+ case 17: return [4 /*yield*/, confirmOverwrite(existingFiles)];
237
214
  case 18:
238
- shouldOverwrite = _c.sent();
215
+ _c = _d.sent();
216
+ _d.label = 19;
217
+ case 19:
218
+ shouldOverwrite = _c;
239
219
  if (!shouldOverwrite) {
240
220
  logger.info('Setup cancelled');
241
221
  process.exit(0);
242
222
  }
243
223
  logger.newline();
244
- _c.label = 19;
245
- case 19:
224
+ _d.label = 20;
225
+ case 20:
246
226
  generateExample = !options.noExample && hasValidConnection;
247
227
  selectedTable = null;
248
- if (!(generateExample && !options.noInteractive && hasValidConnection)) return [3 /*break*/, 23];
228
+ if (!(generateExample && !noInteractive && hasValidConnection)) return [3 /*break*/, 24];
249
229
  return [4 /*yield*/, promptGenerateExample()];
250
- case 20:
251
- generateExample = _c.sent();
252
- if (!generateExample) return [3 /*break*/, 23];
253
- return [4 /*yield*/, getTables(dbType)];
254
230
  case 21:
255
- tables = _c.sent();
256
- return [4 /*yield*/, promptTableSelection(tables)];
231
+ generateExample = _d.sent();
232
+ if (!generateExample) return [3 /*break*/, 24];
233
+ return [4 /*yield*/, getTables('clickhouse')];
257
234
  case 22:
258
- selectedTable = _c.sent();
259
- generateExample = selectedTable !== null;
260
- _c.label = 23;
235
+ tables = _d.sent();
236
+ return [4 /*yield*/, promptTableSelection(tables)];
261
237
  case 23:
238
+ selectedTable = _d.sent();
239
+ generateExample = selectedTable !== null;
240
+ _d.label = 24;
241
+ case 24:
262
242
  logger.newline();
263
243
  // Step 7: Create directory
264
244
  return [4 /*yield*/, mkdir(resolvedOutputDir, { recursive: true })];
265
- case 24:
245
+ case 25:
266
246
  // Step 7: Create directory
267
- _c.sent();
268
- if (!connectionConfig) return [3 /*break*/, 31];
247
+ _d.sent();
248
+ if (!connectionConfig) return [3 /*break*/, 32];
269
249
  envPath = path.join(process.cwd(), '.env');
270
250
  return [4 /*yield*/, hasEnvFile()];
271
- case 25:
272
- envExists = _c.sent();
273
- if (!envExists) return [3 /*break*/, 28];
274
- return [4 /*yield*/, readFile(envPath, 'utf-8')];
275
251
  case 26:
276
- existingEnv = _c.sent();
252
+ envExists = _d.sent();
253
+ if (!envExists) return [3 /*break*/, 29];
254
+ return [4 /*yield*/, readFile(envPath, 'utf-8')];
255
+ case 27:
256
+ existingEnv = _d.sent();
277
257
  newEnv = appendToEnv(existingEnv, generateEnvTemplate(connectionConfig));
278
258
  return [4 /*yield*/, writeFile(envPath, newEnv)];
279
- case 27:
280
- _c.sent();
259
+ case 28:
260
+ _d.sent();
281
261
  logger.success('Updated .env');
282
- return [3 /*break*/, 30];
283
- case 28: return [4 /*yield*/, writeFile(envPath, generateEnvTemplate(connectionConfig))];
284
- case 29:
285
- _c.sent();
262
+ return [3 /*break*/, 31];
263
+ case 29: return [4 /*yield*/, writeFile(envPath, generateEnvTemplate(connectionConfig))];
264
+ case 30:
265
+ _d.sent();
286
266
  logger.success('Created .env');
287
- _c.label = 30;
288
- case 30: return [3 /*break*/, 34];
289
- case 31:
267
+ _d.label = 31;
268
+ case 31: return [3 /*break*/, 35];
269
+ case 32:
290
270
  envPath = path.join(process.cwd(), '.env');
291
271
  return [4 /*yield*/, hasEnvFile()];
292
- case 32:
293
- envExists = _c.sent();
272
+ case 33:
273
+ envExists = _d.sent();
294
274
  placeholderConfig = {
295
- host: 'YOUR_CLICKHOUSE_HOST',
275
+ url: 'YOUR_CLICKHOUSE_URL',
296
276
  database: 'YOUR_DATABASE',
297
277
  username: 'YOUR_USERNAME',
298
278
  password: 'YOUR_PASSWORD',
299
279
  };
300
- if (!!envExists) return [3 /*break*/, 34];
280
+ if (!!envExists) return [3 /*break*/, 35];
301
281
  return [4 /*yield*/, writeFile(envPath, generateEnvTemplate(placeholderConfig))];
302
- case 33:
303
- _c.sent();
304
- logger.success('Created .env (configure your credentials)');
305
- _c.label = 34;
306
282
  case 34:
283
+ _d.sent();
284
+ logger.success('Created .env (configure your credentials)');
285
+ _d.label = 35;
286
+ case 35:
307
287
  schemaPath = path.join(resolvedOutputDir, 'schema.ts');
308
- if (!hasValidConnection) return [3 /*break*/, 39];
288
+ if (!hasValidConnection) return [3 /*break*/, 40];
309
289
  typeSpinner = ora('Generating TypeScript types...').start();
310
- _c.label = 35;
311
- case 35:
312
- _c.trys.push([35, 37, , 38]);
290
+ _d.label = 36;
291
+ case 36:
292
+ _d.trys.push([36, 38, , 39]);
313
293
  generator = getTypeGenerator('clickhouse');
314
294
  return [4 /*yield*/, generator({ outputPath: schemaPath })];
315
- case 36:
316
- _c.sent();
317
- typeSpinner.succeed("Generated TypeScript types (".concat(path.relative(process.cwd(), schemaPath), ")"));
318
- return [3 /*break*/, 38];
319
295
  case 37:
320
- error_1 = _c.sent();
296
+ _d.sent();
297
+ typeSpinner.succeed("Generated TypeScript types (".concat(path.relative(process.cwd(), schemaPath), ")"));
298
+ return [3 /*break*/, 39];
299
+ case 38:
300
+ error_1 = _d.sent();
321
301
  typeSpinner.fail('Failed to generate types');
322
302
  logger.error(error_1 instanceof Error ? error_1.message : String(error_1));
323
303
  process.exit(1);
324
- return [3 /*break*/, 38];
325
- case 38: return [3 /*break*/, 41];
326
- case 39:
304
+ return [3 /*break*/, 39];
305
+ case 39: return [3 /*break*/, 42];
306
+ case 40:
327
307
  // Create placeholder schema file
328
308
  return [4 /*yield*/, writeFile(schemaPath, "// Generated by hypequery\n// Run 'npx hypequery generate' after configuring your database connection\n\nexport interface IntrospectedSchema {\n // Your table types will appear here after generation\n}\n")];
329
- case 40:
309
+ case 41:
330
310
  // Create placeholder schema file
331
- _c.sent();
311
+ _d.sent();
332
312
  logger.success("Created placeholder schema (".concat(path.relative(process.cwd(), schemaPath), ")"));
333
- _c.label = 41;
334
- case 41:
313
+ _d.label = 42;
314
+ case 42:
335
315
  clientPath = path.join(resolvedOutputDir, 'client.ts');
336
316
  return [4 /*yield*/, writeFile(clientPath, generateClientTemplate())];
337
- case 42:
338
- _c.sent();
317
+ case 43:
318
+ _d.sent();
339
319
  logger.success("Created ClickHouse client (".concat(path.relative(process.cwd(), clientPath), ")"));
340
320
  queriesPath = path.join(resolvedOutputDir, 'queries.ts');
341
321
  return [4 /*yield*/, writeFile(queriesPath, generateQueriesTemplate({
342
322
  hasExample: generateExample,
343
323
  tableName: selectedTable || undefined,
344
324
  }))];
345
- case 43:
346
- _c.sent();
325
+ case 44:
326
+ _d.sent();
347
327
  logger.success("Created queries file (".concat(path.relative(process.cwd(), queriesPath), ")"));
348
328
  if (generateExample && selectedTable) {
349
329
  logger.success("Created example query using '".concat(selectedTable, "' table"));
350
330
  }
351
331
  gitignorePath = path.join(process.cwd(), '.gitignore');
352
332
  return [4 /*yield*/, hasGitignore()];
353
- case 44:
354
- gitignoreExists = _c.sent();
355
- if (!gitignoreExists) return [3 /*break*/, 48];
356
- return [4 /*yield*/, readFile(gitignorePath, 'utf-8')];
357
333
  case 45:
358
- existingGitignore = _c.sent();
334
+ gitignoreExists = _d.sent();
335
+ if (!gitignoreExists) return [3 /*break*/, 49];
336
+ return [4 /*yield*/, readFile(gitignorePath, 'utf-8')];
337
+ case 46:
338
+ existingGitignore = _d.sent();
359
339
  newGitignore = appendToGitignore(existingGitignore);
360
- if (!(newGitignore !== existingGitignore)) return [3 /*break*/, 47];
340
+ if (!(newGitignore !== existingGitignore)) return [3 /*break*/, 48];
361
341
  return [4 /*yield*/, writeFile(gitignorePath, newGitignore)];
362
- case 46:
363
- _c.sent();
342
+ case 47:
343
+ _d.sent();
364
344
  logger.success('Updated .gitignore');
365
- _c.label = 47;
366
- case 47: return [3 /*break*/, 50];
367
- case 48: return [4 /*yield*/, writeFile(gitignorePath, appendToGitignore(''))];
368
- case 49:
369
- _c.sent();
345
+ _d.label = 48;
346
+ case 48: return [3 /*break*/, 51];
347
+ case 49: return [4 /*yield*/, writeFile(gitignorePath, appendToGitignore(''))];
348
+ case 50:
349
+ _d.sent();
370
350
  logger.success('Created .gitignore');
371
- _c.label = 50;
372
- case 50:
351
+ _d.label = 51;
352
+ case 51:
373
353
  // Step 13: Ensure required hypequery packages are installed
374
- return [4 /*yield*/, installServeDependencies()];
375
- case 51:
354
+ return [4 /*yield*/, installScaffoldDependencies()];
355
+ case 52:
376
356
  // Step 13: Ensure required hypequery packages are installed
377
- _c.sent();
357
+ _d.sent();
378
358
  // Step 14: Success message
379
359
  logger.newline();
380
360
  logger.header('Setup complete!');
@@ -3,5 +3,7 @@ export interface ClickHouseGeneratorOptions {
3
3
  includeTables?: string[];
4
4
  excludeTables?: string[];
5
5
  }
6
+ declare const clickhouseToTsType: (type: string) => string;
7
+ export { clickhouseToTsType };
6
8
  export declare function generateClickHouseTypes(options: ClickHouseGeneratorOptions): Promise<void>;
7
9
  //# sourceMappingURL=clickhouse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/generators/clickhouse.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AA4HD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,iBA0ChF"}
1
+ {"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/generators/clickhouse.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAmGD,QAAA,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAsC1C,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAgC9B,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,iBA0ChF"}
@@ -39,57 +39,53 @@ import path from 'node:path';
39
39
  import { getClickHouseClient } from '../utils/clickhouse-client.js';
40
40
  var DEFAULT_WARNING = 'Warning: No tables match the filter criteria. Check your include/exclude options.';
41
41
  var capitalizeFirstLetter = function (value) { return value.charAt(0).toUpperCase() + value.slice(1); };
42
- var clickhouseToTsType = function (type) {
43
- if (type.startsWith('Array(')) {
44
- var innerType = type.slice(6, -1);
45
- return "Array<".concat(clickhouseToTsType(innerType), ">");
46
- }
47
- if (type.startsWith('Nullable(')) {
48
- var innerType = type.slice(9, -1);
49
- return "".concat(clickhouseToTsType(innerType), " | null");
50
- }
51
- if (type.startsWith('Map(')) {
52
- var mapContent = type.slice(4, -1);
53
- var commaIndex = mapContent.lastIndexOf(',');
54
- if (commaIndex !== -1) {
55
- var keyType = mapContent.substring(0, commaIndex).trim();
56
- var valueType = mapContent.substring(commaIndex + 1).trim();
57
- var keyTsType = 'string';
58
- if (keyType === 'LowCardinality(String)') {
59
- keyTsType = 'string';
60
- }
61
- else if (keyType.includes('Int') || keyType.includes('UInt')) {
62
- keyTsType = 'number';
63
- }
64
- var valueTsType = 'unknown';
65
- if (valueType.startsWith('Array(')) {
66
- var innerType = valueType.slice(6, -1);
67
- valueTsType = "Array<".concat(clickhouseToTsType(innerType), ">");
68
- }
69
- else if (valueType.startsWith('Nullable(')) {
70
- var innerType = valueType.slice(9, -1);
71
- valueTsType = "".concat(clickhouseToTsType(innerType), " | null");
72
- }
73
- else {
74
- valueTsType = clickhouseToTsType(valueType);
75
- }
76
- return "Record<".concat(keyTsType, ", ").concat(valueTsType, ">");
42
+ function splitTopLevelArgs(value) {
43
+ var parts = [];
44
+ var current = '';
45
+ var depth = 0;
46
+ for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
47
+ var char = value_1[_i];
48
+ if (char === '(') {
49
+ depth += 1;
50
+ current += char;
51
+ continue;
77
52
  }
78
- return 'Record<string, unknown>';
53
+ if (char === ')') {
54
+ depth -= 1;
55
+ current += char;
56
+ continue;
57
+ }
58
+ if (char === ',' && depth === 0) {
59
+ parts.push(current.trim());
60
+ current = '';
61
+ continue;
62
+ }
63
+ current += char;
79
64
  }
80
- switch (type.toLowerCase()) {
65
+ if (current.trim()) {
66
+ parts.push(current.trim());
67
+ }
68
+ return parts;
69
+ }
70
+ function unwrapType(type, wrapperName) {
71
+ var prefix = "".concat(wrapperName, "(");
72
+ return type.startsWith(prefix) && type.endsWith(')') ? type.slice(prefix.length, -1) : null;
73
+ }
74
+ function getPrimitiveTsType(type) {
75
+ var lowerType = type.toLowerCase();
76
+ switch (lowerType) {
81
77
  case 'string':
82
- case 'fixedstring':
78
+ case 'uuid':
83
79
  return 'string';
84
80
  case 'int8':
85
81
  case 'int16':
86
82
  case 'int32':
87
83
  case 'uint8':
88
- case 'int64':
89
84
  case 'uint16':
90
85
  case 'uint32':
91
- case 'uint64':
92
86
  return 'number';
87
+ case 'int64':
88
+ case 'uint64':
93
89
  case 'uint128':
94
90
  case 'uint256':
95
91
  case 'int128':
@@ -108,9 +104,56 @@ var clickhouseToTsType = function (type) {
108
104
  case 'boolean':
109
105
  return 'boolean';
110
106
  default:
111
- return 'string';
107
+ if (type.startsWith('FixedString('))
108
+ return 'string';
109
+ if (type.startsWith('Decimal('))
110
+ return 'number';
111
+ if (type.startsWith('DateTime64('))
112
+ return 'string';
113
+ if (type.startsWith('DateTime('))
114
+ return 'string';
115
+ if (type.startsWith('Enum8('))
116
+ return 'string';
117
+ if (type.startsWith('Enum16('))
118
+ return 'string';
119
+ return null;
120
+ }
121
+ }
122
+ var clickhouseToTsType = function (type) {
123
+ var wrappedArrayType = unwrapType(type, 'Array');
124
+ if (wrappedArrayType) {
125
+ return "Array<".concat(clickhouseToTsType(wrappedArrayType), ">");
126
+ }
127
+ var wrappedNullableType = unwrapType(type, 'Nullable');
128
+ if (wrappedNullableType) {
129
+ return "".concat(clickhouseToTsType(wrappedNullableType), " | null");
130
+ }
131
+ var wrappedLowCardinalityType = unwrapType(type, 'LowCardinality');
132
+ if (wrappedLowCardinalityType) {
133
+ return clickhouseToTsType(wrappedLowCardinalityType);
134
+ }
135
+ var wrappedTupleType = unwrapType(type, 'Tuple');
136
+ if (wrappedTupleType) {
137
+ var tupleParts = splitTopLevelArgs(wrappedTupleType);
138
+ return "[".concat(tupleParts.map(clickhouseToTsType).join(', '), "]");
139
+ }
140
+ var wrappedMapType = unwrapType(type, 'Map');
141
+ if (wrappedMapType) {
142
+ var mapParts = splitTopLevelArgs(wrappedMapType);
143
+ if (mapParts.length === 2) {
144
+ var valueType = mapParts[1];
145
+ // JSON object keys are strings even when ClickHouse map keys are numeric.
146
+ return "Record<string, ".concat(clickhouseToTsType(valueType), ">");
147
+ }
148
+ return 'Record<string, unknown>';
112
149
  }
150
+ var primitiveType = getPrimitiveTsType(type);
151
+ if (primitiveType)
152
+ return primitiveType;
153
+ // Unsupported or more complex ClickHouse types currently preserve the historical fallback.
154
+ return 'string';
113
155
  };
156
+ export { clickhouseToTsType };
114
157
  function fetchTables(includeTables, excludeTables) {
115
158
  return __awaiter(this, void 0, void 0, function () {
116
159
  var client, tablesQuery, tables;
@@ -6,7 +6,7 @@ export function getTypeGenerator(dbType) {
6
6
  var generator = generators[dbType];
7
7
  if (!generator) {
8
8
  throw new Error(dbType === 'unknown'
9
- ? 'Unable to detect database type. Re-run `hypequery init --database <type>` or pass `--database` explicitly.'
9
+ ? 'Unable to detect database type. Re-run `hypequery generate --database <type>` or pass `--database` explicitly.'
10
10
  : "Type generation for ".concat(dbType, " is not supported yet."));
11
11
  }
12
12
  return generator;