@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.
- package/README.md +52 -154
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +15 -2
- package/dist/commands/generate.js +1 -1
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +140 -160
- package/dist/generators/clickhouse.d.ts +2 -0
- package/dist/generators/clickhouse.d.ts.map +1 -1
- package/dist/generators/clickhouse.js +84 -41
- package/dist/generators/index.js +1 -1
- package/dist/templates/client.js +1 -1
- package/dist/templates/env.d.ts +2 -1
- package/dist/templates/env.d.ts.map +1 -1
- package/dist/templates/env.js +5 -3
- package/dist/templates/queries.d.ts.map +1 -1
- package/dist/templates/queries.js +3 -2
- package/dist/test-utils.d.ts +0 -1
- package/dist/test-utils.d.ts.map +1 -1
- package/dist/test-utils.js +0 -1
- package/dist/utils/clickhouse-client.js +1 -1
- package/dist/utils/dependency-installer.d.ts +3 -1
- package/dist/utils/dependency-installer.d.ts.map +1 -1
- package/dist/utils/dependency-installer.js +75 -15
- package/dist/utils/load-api.d.ts +1 -0
- package/dist/utils/load-api.d.ts.map +1 -1
- package/dist/utils/load-api.js +79 -55
- package/dist/utils/load-hypequery-config.d.ts +7 -0
- package/dist/utils/load-hypequery-config.d.ts.map +1 -0
- package/dist/utils/load-hypequery-config.js +89 -0
- package/dist/utils/prompts.d.ts +0 -5
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +9 -34
- package/package.json +9 -4
package/dist/commands/init.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
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 (
|
|
86
|
-
var
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
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 (
|
|
145
|
-
switch (
|
|
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
|
|
156
|
-
connectionConfig =
|
|
126
|
+
case 1:
|
|
127
|
+
connectionConfig = _d.sent();
|
|
157
128
|
hasValidConnection = false;
|
|
158
129
|
tableCount = 0;
|
|
159
|
-
if (!!connectionConfig) return [3 /*break*/,
|
|
130
|
+
if (!!connectionConfig) return [3 /*break*/, 2];
|
|
160
131
|
logger.info('Skipping database connection for now.');
|
|
161
132
|
logger.newline();
|
|
162
|
-
return [3 /*break*/,
|
|
163
|
-
case
|
|
164
|
-
if (!options.skipConnection) return [3 /*break*/,
|
|
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*/,
|
|
168
|
-
case
|
|
169
|
-
case
|
|
170
|
-
_a =
|
|
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*/,
|
|
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
|
|
176
|
-
retry =
|
|
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
|
|
182
|
-
continueWithout =
|
|
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
|
-
|
|
193
|
-
case
|
|
166
|
+
_d.label = 7;
|
|
167
|
+
case 7:
|
|
194
168
|
outputDir = options.path;
|
|
195
|
-
if (!(!outputDir && !
|
|
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
|
-
|
|
205
|
-
case
|
|
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
|
-
|
|
215
|
-
case
|
|
216
|
-
if (!(_i < filesToCreate_1.length)) return [3 /*break*/,
|
|
188
|
+
_d.label = 11;
|
|
189
|
+
case 11:
|
|
190
|
+
if (!(_i < filesToCreate_1.length)) return [3 /*break*/, 16];
|
|
217
191
|
file = filesToCreate_1[_i];
|
|
218
|
-
|
|
219
|
-
case
|
|
220
|
-
|
|
192
|
+
_d.label = 12;
|
|
193
|
+
case 12:
|
|
194
|
+
_d.trys.push([12, 14, , 15]);
|
|
221
195
|
return [4 /*yield*/, access(file)];
|
|
222
|
-
case
|
|
223
|
-
|
|
196
|
+
case 13:
|
|
197
|
+
_d.sent();
|
|
224
198
|
existingFiles.push(path.relative(process.cwd(), file));
|
|
225
|
-
return [3 /*break*/,
|
|
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*/,
|
|
232
|
-
case
|
|
233
|
-
if (!(existingFiles.length > 0 && !options.force)) return [3 /*break*/,
|
|
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 [
|
|
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
|
-
|
|
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
|
-
|
|
245
|
-
case
|
|
224
|
+
_d.label = 20;
|
|
225
|
+
case 20:
|
|
246
226
|
generateExample = !options.noExample && hasValidConnection;
|
|
247
227
|
selectedTable = null;
|
|
248
|
-
if (!(generateExample && !
|
|
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
|
-
|
|
256
|
-
return [
|
|
231
|
+
generateExample = _d.sent();
|
|
232
|
+
if (!generateExample) return [3 /*break*/, 24];
|
|
233
|
+
return [4 /*yield*/, getTables('clickhouse')];
|
|
257
234
|
case 22:
|
|
258
|
-
|
|
259
|
-
|
|
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
|
|
245
|
+
case 25:
|
|
266
246
|
// Step 7: Create directory
|
|
267
|
-
|
|
268
|
-
if (!connectionConfig) return [3 /*break*/,
|
|
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
|
-
|
|
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
|
|
280
|
-
|
|
259
|
+
case 28:
|
|
260
|
+
_d.sent();
|
|
281
261
|
logger.success('Updated .env');
|
|
282
|
-
return [3 /*break*/,
|
|
283
|
-
case
|
|
284
|
-
case
|
|
285
|
-
|
|
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
|
-
|
|
288
|
-
case
|
|
289
|
-
case
|
|
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
|
|
293
|
-
envExists =
|
|
272
|
+
case 33:
|
|
273
|
+
envExists = _d.sent();
|
|
294
274
|
placeholderConfig = {
|
|
295
|
-
|
|
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*/,
|
|
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*/,
|
|
288
|
+
if (!hasValidConnection) return [3 /*break*/, 40];
|
|
309
289
|
typeSpinner = ora('Generating TypeScript types...').start();
|
|
310
|
-
|
|
311
|
-
case
|
|
312
|
-
|
|
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
|
-
|
|
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*/,
|
|
325
|
-
case
|
|
326
|
-
case
|
|
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
|
|
309
|
+
case 41:
|
|
330
310
|
// Create placeholder schema file
|
|
331
|
-
|
|
311
|
+
_d.sent();
|
|
332
312
|
logger.success("Created placeholder schema (".concat(path.relative(process.cwd(), schemaPath), ")"));
|
|
333
|
-
|
|
334
|
-
case
|
|
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
|
|
338
|
-
|
|
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
|
|
346
|
-
|
|
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
|
-
|
|
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*/,
|
|
340
|
+
if (!(newGitignore !== existingGitignore)) return [3 /*break*/, 48];
|
|
361
341
|
return [4 /*yield*/, writeFile(gitignorePath, newGitignore)];
|
|
362
|
-
case
|
|
363
|
-
|
|
342
|
+
case 47:
|
|
343
|
+
_d.sent();
|
|
364
344
|
logger.success('Updated .gitignore');
|
|
365
|
-
|
|
366
|
-
case
|
|
367
|
-
case
|
|
368
|
-
case
|
|
369
|
-
|
|
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
|
-
|
|
372
|
-
case
|
|
351
|
+
_d.label = 51;
|
|
352
|
+
case 51:
|
|
373
353
|
// Step 13: Ensure required hypequery packages are installed
|
|
374
|
-
return [4 /*yield*/,
|
|
375
|
-
case
|
|
354
|
+
return [4 /*yield*/, installScaffoldDependencies()];
|
|
355
|
+
case 52:
|
|
376
356
|
// Step 13: Ensure required hypequery packages are installed
|
|
377
|
-
|
|
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;
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 '
|
|
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
|
-
|
|
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;
|
package/dist/generators/index.js
CHANGED
|
@@ -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
|
|
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;
|