@hypequery/cli 0.0.7 → 0.0.9

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 (61) hide show
  1. package/dist/bin/cli.d.ts +3 -0
  2. package/dist/bin/cli.d.ts.map +1 -0
  3. package/dist/bin/cli.js +86 -0
  4. package/dist/cli.d.ts +4 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +163 -0
  7. package/dist/commands/dev.d.ts +12 -0
  8. package/dist/commands/dev.d.ts.map +1 -0
  9. package/dist/commands/dev.js +265 -0
  10. package/dist/commands/generate.d.ts +8 -0
  11. package/dist/commands/generate.d.ts.map +1 -0
  12. package/dist/commands/generate.js +175 -0
  13. package/dist/commands/init.d.ts +10 -0
  14. package/dist/commands/init.d.ts.map +1 -0
  15. package/dist/commands/init.js +408 -0
  16. package/dist/generators/clickhouse.d.ts +7 -0
  17. package/dist/generators/clickhouse.d.ts.map +1 -0
  18. package/dist/generators/clickhouse.js +229 -0
  19. package/dist/generators/index.d.ts +7 -0
  20. package/dist/generators/index.d.ts.map +1 -0
  21. package/dist/generators/index.js +13 -0
  22. package/dist/templates/client.d.ts +5 -0
  23. package/dist/templates/client.d.ts.map +1 -0
  24. package/dist/templates/client.js +6 -0
  25. package/dist/templates/env.d.ts +14 -0
  26. package/dist/templates/env.d.ts.map +1 -0
  27. package/dist/templates/env.js +37 -0
  28. package/dist/templates/gitignore.d.ts +13 -0
  29. package/dist/templates/gitignore.d.ts.map +1 -0
  30. package/dist/templates/gitignore.js +22 -0
  31. package/dist/templates/queries.d.ts +8 -0
  32. package/dist/templates/queries.d.ts.map +1 -0
  33. package/dist/templates/queries.js +27 -0
  34. package/dist/test-utils.d.ts +86 -0
  35. package/dist/test-utils.d.ts.map +1 -0
  36. package/dist/test-utils.js +153 -0
  37. package/dist/utils/clickhouse-client.d.ts +11 -0
  38. package/dist/utils/clickhouse-client.d.ts.map +1 -0
  39. package/dist/utils/clickhouse-client.js +86 -0
  40. package/dist/utils/dependency-installer.d.ts +2 -0
  41. package/dist/utils/dependency-installer.d.ts.map +1 -0
  42. package/dist/utils/dependency-installer.js +180 -0
  43. package/dist/utils/detect-database.d.ts +21 -0
  44. package/dist/utils/detect-database.d.ts.map +1 -0
  45. package/dist/utils/detect-database.js +224 -0
  46. package/dist/utils/error-messages.d.ts +6 -0
  47. package/dist/utils/error-messages.d.ts.map +1 -0
  48. package/dist/utils/error-messages.js +19 -0
  49. package/dist/utils/find-files.d.ts +21 -0
  50. package/dist/utils/find-files.d.ts.map +1 -0
  51. package/dist/utils/find-files.js +183 -0
  52. package/dist/utils/load-api.d.ts +2 -0
  53. package/dist/utils/load-api.d.ts.map +1 -0
  54. package/dist/utils/load-api.js +400 -0
  55. package/dist/utils/logger.d.ts +54 -0
  56. package/dist/utils/logger.d.ts.map +1 -0
  57. package/dist/utils/logger.js +122 -0
  58. package/dist/utils/prompts.d.ts +39 -0
  59. package/dist/utils/prompts.d.ts.map +1 -0
  60. package/dist/utils/prompts.js +282 -0
  61. package/package.json +2 -2
@@ -0,0 +1,229 @@
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
+ import fs from 'node:fs/promises';
38
+ import path from 'node:path';
39
+ import { getClickHouseClient } from '../utils/clickhouse-client.js';
40
+ var DEFAULT_WARNING = 'Warning: No tables match the filter criteria. Check your include/exclude options.';
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, ">");
77
+ }
78
+ return 'Record<string, unknown>';
79
+ }
80
+ switch (type.toLowerCase()) {
81
+ case 'string':
82
+ case 'fixedstring':
83
+ return 'string';
84
+ case 'int8':
85
+ case 'int16':
86
+ case 'int32':
87
+ case 'uint8':
88
+ case 'int64':
89
+ case 'uint16':
90
+ case 'uint32':
91
+ case 'uint64':
92
+ return 'number';
93
+ case 'uint128':
94
+ case 'uint256':
95
+ case 'int128':
96
+ case 'int256':
97
+ return 'string';
98
+ case 'float32':
99
+ case 'float64':
100
+ case 'decimal':
101
+ return 'number';
102
+ case 'datetime':
103
+ case 'datetime64':
104
+ case 'date':
105
+ case 'date32':
106
+ return 'string';
107
+ case 'bool':
108
+ case 'boolean':
109
+ return 'boolean';
110
+ default:
111
+ return 'string';
112
+ }
113
+ };
114
+ function fetchTables(includeTables, excludeTables) {
115
+ return __awaiter(this, void 0, void 0, function () {
116
+ var client, tablesQuery, tables;
117
+ return __generator(this, function (_a) {
118
+ switch (_a.label) {
119
+ case 0:
120
+ client = getClickHouseClient();
121
+ return [4 /*yield*/, client.query({
122
+ query: 'SHOW TABLES',
123
+ format: 'JSONEachRow',
124
+ })];
125
+ case 1:
126
+ tablesQuery = _a.sent();
127
+ return [4 /*yield*/, tablesQuery.json()];
128
+ case 2:
129
+ tables = (_a.sent());
130
+ if (includeTables === null || includeTables === void 0 ? void 0 : includeTables.length) {
131
+ tables = tables.filter(function (table) { return includeTables.includes(table.name); });
132
+ }
133
+ if (excludeTables === null || excludeTables === void 0 ? void 0 : excludeTables.length) {
134
+ tables = tables.filter(function (table) { return !excludeTables.includes(table.name); });
135
+ }
136
+ return [2 /*return*/, tables];
137
+ }
138
+ });
139
+ });
140
+ }
141
+ function fetchColumns(table) {
142
+ return __awaiter(this, void 0, void 0, function () {
143
+ var client, columnsQuery;
144
+ return __generator(this, function (_a) {
145
+ switch (_a.label) {
146
+ case 0:
147
+ client = getClickHouseClient();
148
+ return [4 /*yield*/, client.query({
149
+ query: "DESCRIBE TABLE ".concat(table),
150
+ format: 'JSONEachRow',
151
+ })];
152
+ case 1:
153
+ columnsQuery = _a.sent();
154
+ return [4 /*yield*/, columnsQuery.json()];
155
+ case 2: return [2 /*return*/, (_a.sent())];
156
+ }
157
+ });
158
+ });
159
+ }
160
+ export function generateClickHouseTypes(options) {
161
+ return __awaiter(this, void 0, void 0, function () {
162
+ var outputPath, includeTables, excludeTables, tables, typeDefinitions, _i, tables_1, table, columns, _a, columns_1, column, clickHouseType, _b, tables_2, table, columns, _c, columns_2, column, tsType, outputDir;
163
+ return __generator(this, function (_d) {
164
+ switch (_d.label) {
165
+ case 0:
166
+ outputPath = options.outputPath, includeTables = options.includeTables, excludeTables = options.excludeTables;
167
+ return [4 /*yield*/, fetchTables(includeTables, excludeTables)];
168
+ case 1:
169
+ tables = _d.sent();
170
+ if (tables.length === 0) {
171
+ console.warn(DEFAULT_WARNING);
172
+ }
173
+ typeDefinitions = "// Generated by hypequery\n" +
174
+ "// This file defines TypeScript types based on your ClickHouse database schema\n\n" +
175
+ "export interface IntrospectedSchema {";
176
+ _i = 0, tables_1 = tables;
177
+ _d.label = 2;
178
+ case 2:
179
+ if (!(_i < tables_1.length)) return [3 /*break*/, 5];
180
+ table = tables_1[_i];
181
+ return [4 /*yield*/, fetchColumns(table.name)];
182
+ case 3:
183
+ columns = _d.sent();
184
+ typeDefinitions += "\n ".concat(table.name, ": {");
185
+ for (_a = 0, columns_1 = columns; _a < columns_1.length; _a++) {
186
+ column = columns_1[_a];
187
+ clickHouseType = column.type.replace(/'/g, "\\'");
188
+ typeDefinitions += "\n '".concat(column.name, "': '").concat(clickHouseType, "';");
189
+ }
190
+ typeDefinitions += '\n };';
191
+ _d.label = 4;
192
+ case 4:
193
+ _i++;
194
+ return [3 /*break*/, 2];
195
+ case 5:
196
+ typeDefinitions += '\n}\n';
197
+ typeDefinitions += "\n// Type-safe record types for each table\n";
198
+ _b = 0, tables_2 = tables;
199
+ _d.label = 6;
200
+ case 6:
201
+ if (!(_b < tables_2.length)) return [3 /*break*/, 9];
202
+ table = tables_2[_b];
203
+ return [4 /*yield*/, fetchColumns(table.name)];
204
+ case 7:
205
+ columns = _d.sent();
206
+ typeDefinitions += "export interface ".concat(capitalizeFirstLetter(table.name), "Record {");
207
+ for (_c = 0, columns_2 = columns; _c < columns_2.length; _c++) {
208
+ column = columns_2[_c];
209
+ tsType = clickhouseToTsType(column.type).replace(/'/g, '');
210
+ typeDefinitions += "\n '".concat(column.name, "': ").concat(tsType, ";");
211
+ }
212
+ typeDefinitions += '\n}\n\n';
213
+ _d.label = 8;
214
+ case 8:
215
+ _b++;
216
+ return [3 /*break*/, 6];
217
+ case 9:
218
+ outputDir = path.dirname(path.resolve(outputPath));
219
+ return [4 /*yield*/, fs.mkdir(outputDir, { recursive: true })];
220
+ case 10:
221
+ _d.sent();
222
+ return [4 /*yield*/, fs.writeFile(path.resolve(outputPath), typeDefinitions)];
223
+ case 11:
224
+ _d.sent();
225
+ return [2 /*return*/];
226
+ }
227
+ });
228
+ });
229
+ }
@@ -0,0 +1,7 @@
1
+ import type { DatabaseType } from '../utils/detect-database.js';
2
+ import { type ClickHouseGeneratorOptions } from './clickhouse.js';
3
+ export type TypeGeneratorOptions = ClickHouseGeneratorOptions;
4
+ type GeneratorFn = (options: TypeGeneratorOptions) => Promise<void>;
5
+ export declare function getTypeGenerator(dbType: DatabaseType): GeneratorFn;
6
+ export {};
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAA2B,KAAK,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAE3F,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE9D,KAAK,WAAW,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAMpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAYlE"}
@@ -0,0 +1,13 @@
1
+ import { generateClickHouseTypes } from './clickhouse.js';
2
+ var generators = {
3
+ clickhouse: generateClickHouseTypes,
4
+ };
5
+ export function getTypeGenerator(dbType) {
6
+ var generator = generators[dbType];
7
+ if (!generator) {
8
+ throw new Error(dbType === 'unknown'
9
+ ? 'Unable to detect database type. Re-run `hypequery init --database <type>` or pass `--database` explicitly.'
10
+ : "Type generation for ".concat(dbType, " is not supported yet."));
11
+ }
12
+ return generator;
13
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generate client.ts file for ClickHouse
3
+ */
4
+ export declare function generateClientTemplate(): string;
5
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/templates/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAW/C"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Generate client.ts file for ClickHouse
3
+ */
4
+ export function generateClientTemplate() {
5
+ return "import { createQueryBuilder } from '@hypequery/clickhouse';\nimport type { IntrospectedSchema } from './schema';\n\nexport const db = createQueryBuilder<IntrospectedSchema>({\n host: process.env.CLICKHOUSE_HOST!,\n database: process.env.CLICKHOUSE_DATABASE!,\n username: process.env.CLICKHOUSE_USERNAME!,\n password: process.env.CLICKHOUSE_PASSWORD,\n});\n";
6
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Generate .env file content for ClickHouse
3
+ */
4
+ export declare function generateEnvTemplate(config: {
5
+ host: string;
6
+ database: string;
7
+ username: string;
8
+ password: string;
9
+ }): string;
10
+ /**
11
+ * Append to existing .env file
12
+ */
13
+ export declare function appendToEnv(existingContent: string, newContent: string): string;
14
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/templates/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAoBT;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,eAAe,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA4B/E"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Generate .env file content for ClickHouse
3
+ */
4
+ export function generateEnvTemplate(config) {
5
+ var isPlaceholder = config.host.includes('YOUR_');
6
+ if (isPlaceholder) {
7
+ return "# Hypequery Configuration\n# Replace these placeholder values with your actual ClickHouse credentials\n\nCLICKHOUSE_HOST=".concat(config.host, "\nCLICKHOUSE_DATABASE=").concat(config.database, "\nCLICKHOUSE_USERNAME=").concat(config.username, "\nCLICKHOUSE_PASSWORD=").concat(config.password, "\n");
8
+ }
9
+ return "# Hypequery Configuration\nCLICKHOUSE_HOST=".concat(config.host, "\nCLICKHOUSE_DATABASE=").concat(config.database, "\nCLICKHOUSE_USERNAME=").concat(config.username, "\nCLICKHOUSE_PASSWORD=").concat(config.password, "\n");
10
+ }
11
+ /**
12
+ * Append to existing .env file
13
+ */
14
+ export function appendToEnv(existingContent, newContent) {
15
+ // Check if hypequery section already exists
16
+ if (existingContent.includes('# Hypequery Configuration')) {
17
+ // Replace existing section
18
+ var lines = existingContent.split('\n');
19
+ var startIndex = lines.findIndex(function (l) { return l.includes('# Hypequery Configuration'); });
20
+ if (startIndex !== -1) {
21
+ // Find the end of the hypequery section
22
+ var endIndex = startIndex + 1;
23
+ while (endIndex < lines.length &&
24
+ (lines[endIndex].startsWith('CLICKHOUSE_') || lines[endIndex].trim() === '')) {
25
+ endIndex++;
26
+ }
27
+ // Replace the section
28
+ lines.splice(startIndex, endIndex - startIndex, newContent.trim());
29
+ return lines.join('\n');
30
+ }
31
+ }
32
+ // Append to end
33
+ if (!existingContent.endsWith('\n')) {
34
+ existingContent += '\n';
35
+ }
36
+ return existingContent + '\n' + newContent;
37
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Content to append to .gitignore
3
+ */
4
+ export declare const GITIGNORE_CONTENT = "\n# Hypequery\n.env\n";
5
+ /**
6
+ * Check if .gitignore already has hypequery entries
7
+ */
8
+ export declare function hasHypequeryEntries(content: string): boolean;
9
+ /**
10
+ * Append hypequery entries to .gitignore
11
+ */
12
+ export declare function appendToGitignore(existingContent: string): string;
13
+ //# sourceMappingURL=gitignore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/templates/gitignore.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,iBAAiB,0BAG7B,CAAC;AAEF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAUjE"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Content to append to .gitignore
3
+ */
4
+ export var GITIGNORE_CONTENT = "\n# Hypequery\n.env\n";
5
+ /**
6
+ * Check if .gitignore already has hypequery entries
7
+ */
8
+ export function hasHypequeryEntries(content) {
9
+ return content.includes('# Hypequery') || content.includes('.env');
10
+ }
11
+ /**
12
+ * Append hypequery entries to .gitignore
13
+ */
14
+ export function appendToGitignore(existingContent) {
15
+ if (hasHypequeryEntries(existingContent)) {
16
+ return existingContent;
17
+ }
18
+ if (!existingContent.endsWith('\n')) {
19
+ existingContent += '\n';
20
+ }
21
+ return existingContent + GITIGNORE_CONTENT;
22
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Generate queries.ts file
3
+ */
4
+ export declare function generateQueriesTemplate(options: {
5
+ hasExample: boolean;
6
+ tableName?: string;
7
+ }): string;
8
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/templates/queries.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CA6DT"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Generate queries.ts file
3
+ */
4
+ export function generateQueriesTemplate(options) {
5
+ var hasExample = options.hasExample, tableName = options.tableName;
6
+ var metricKey = hasExample && tableName ? "".concat(camelCase(tableName), "Query") : 'exampleMetric';
7
+ var typeAlias = "".concat(pascalCase(metricKey), "Result");
8
+ var template = "import { initServe } from '@hypequery/serve';\nimport type { InferApiType } from '@hypequery/serve';\nimport { z } from 'zod';\nimport { db } from './client';\n\nconst serve = initServe({\n context: () => ({ db }),\n});\nconst { query } = serve;\n\nexport const api = serve.define({\n queries: serve.queries({";
9
+ if (hasExample && tableName) {
10
+ template += "\n ".concat(camelCase(tableName), "Query: query\n .describe('Example query using the ").concat(tableName, " table')\n .query(async ({ ctx }) =>\n ctx.db\n .table('").concat(tableName, "')\n .select('*')\n .limit(10)\n .execute()\n ),");
11
+ }
12
+ else {
13
+ template += "\n exampleMetric: query\n .describe('Example metric that returns a simple value')\n .output(z.object({ ok: z.boolean() }))\n .query(async () => ({ ok: true })),";
14
+ }
15
+ template += "\n }),\n});\n\nexport type ApiDefinition = InferApiType<typeof api>;\n\n/**\n * Inline usage example:\n *\n * const result = await api.execute('".concat(metricKey, "');\n * console.log(result);\n *\n * // import type { InferQueryResult } from '@hypequery/serve';\n * type ").concat(typeAlias, " = InferQueryResult<typeof api, '").concat(metricKey, "'>;\n *\n * // Register HTTP route:\n * api.route('/metrics/").concat(metricKey, "', api.queries.").concat(metricKey, ");\n *\n * Dev server:\n * npx hypequery dev\n */\n");
16
+ return template;
17
+ }
18
+ /**
19
+ * Convert table name to camelCase
20
+ */
21
+ function camelCase(str) {
22
+ return str.replace(/_([a-z])/g, function (_, letter) { return letter.toUpperCase(); });
23
+ }
24
+ function pascalCase(str) {
25
+ var camel = camelCase(str);
26
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
27
+ }
@@ -0,0 +1,86 @@
1
+ import type { Mock } from 'vitest';
2
+ /**
3
+ * Mock prompts module for testing
4
+ */
5
+ export declare function createMockPrompts(): {
6
+ promptDatabaseType: Mock<(...args: any[]) => any>;
7
+ promptClickHouseConnection: Mock<(...args: any[]) => any>;
8
+ promptOutputDirectory: Mock<(...args: any[]) => any>;
9
+ promptGenerateExample: Mock<(...args: any[]) => any>;
10
+ promptTableSelection: Mock<(...args: any[]) => any>;
11
+ confirmOverwrite: Mock<(...args: any[]) => any>;
12
+ promptRetry: Mock<(...args: any[]) => any>;
13
+ promptContinueWithoutDb: Mock<(...args: any[]) => any>;
14
+ };
15
+ /**
16
+ * Mock database detection utilities
17
+ */
18
+ export declare function createMockDatabaseUtils(): {
19
+ validateConnection: Mock<(...args: any[]) => any>;
20
+ getTableCount: Mock<(...args: any[]) => any>;
21
+ getTables: Mock<(...args: any[]) => any>;
22
+ };
23
+ /**
24
+ * Mock file system utilities
25
+ */
26
+ export declare function createMockFileUtils(): {
27
+ hasEnvFile: Mock<(...args: any[]) => any>;
28
+ hasGitignore: Mock<(...args: any[]) => any>;
29
+ findQueriesFile: Mock<(...args: any[]) => any>;
30
+ findSchemaFile: Mock<(...args: any[]) => any>;
31
+ };
32
+ /**
33
+ * Mock logger to capture output
34
+ */
35
+ export declare function createMockLogger(): {
36
+ success: Mock<(...args: any[]) => any>;
37
+ error: Mock<(...args: any[]) => any>;
38
+ warn: Mock<(...args: any[]) => any>;
39
+ info: Mock<(...args: any[]) => any>;
40
+ reload: Mock<(...args: any[]) => any>;
41
+ header: Mock<(...args: any[]) => any>;
42
+ newline: Mock<(...args: any[]) => any>;
43
+ indent: Mock<(...args: any[]) => any>;
44
+ box: Mock<(...args: any[]) => any>;
45
+ table: Mock<(...args: any[]) => any>;
46
+ raw: Mock<(...args: any[]) => any>;
47
+ };
48
+ /**
49
+ * Mock ora spinner
50
+ */
51
+ export declare function createMockSpinner(): Mock<() => {
52
+ start: Mock<(...args: any[]) => any>;
53
+ succeed: Mock<(...args: any[]) => any>;
54
+ fail: Mock<(...args: any[]) => any>;
55
+ stop: Mock<(...args: any[]) => any>;
56
+ }>;
57
+ /**
58
+ * Mock fs/promises for file operations
59
+ */
60
+ export declare function createMockFs(): {
61
+ mkdir: Mock<(...args: any[]) => any>;
62
+ writeFile: Mock<(...args: any[]) => any>;
63
+ readFile: Mock<(...args: any[]) => any>;
64
+ access: Mock<(...args: any[]) => any>;
65
+ };
66
+ /**
67
+ * Capture console output
68
+ */
69
+ export declare function captureConsole(): {
70
+ logs: string[];
71
+ errors: string[];
72
+ restore: () => void;
73
+ };
74
+ /**
75
+ * Mock process.exit to prevent tests from exiting
76
+ * Throws a special error to stop execution
77
+ */
78
+ export declare class ProcessExitError extends Error {
79
+ code: number;
80
+ constructor(code: number);
81
+ }
82
+ export declare function mockProcessExit(): {
83
+ exitMock: Mock<(...args: any[]) => any>;
84
+ restore: () => void;
85
+ };
86
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC;;GAEG;AACH,wBAAgB,iBAAiB;;;;;;;;;EAWhC;AAED;;GAEG;AACH,wBAAgB,uBAAuB;;;;EAMtC;AAED;;GAEG;AACH,wBAAgB,mBAAmB;;;;;EAOlC;AAED;;GAEG;AACH,wBAAgB,gBAAgB;;;;;;;;;;;;EAc/B;AAED;;GAEG;AACH,wBAAgB,iBAAiB;;;;;GAQhC;AAED;;GAEG;AACH,wBAAgB,YAAY;;;;;EAO3B;AAED;;GAEG;AACH,wBAAgB,cAAc;;;;EAuB7B;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACtB,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM;CAIhC;AAED,wBAAgB,eAAe;;;EAe9B"}
@@ -0,0 +1,153 @@
1
+ var __extends = (this && this.__extends) || (function () {
2
+ var extendStatics = function (d, b) {
3
+ extendStatics = Object.setPrototypeOf ||
4
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
+ return extendStatics(d, b);
7
+ };
8
+ return function (d, b) {
9
+ if (typeof b !== "function" && b !== null)
10
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
11
+ extendStatics(d, b);
12
+ function __() { this.constructor = d; }
13
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14
+ };
15
+ })();
16
+ import { vi } from 'vitest';
17
+ /**
18
+ * Mock prompts module for testing
19
+ */
20
+ export function createMockPrompts() {
21
+ return {
22
+ promptDatabaseType: vi.fn(),
23
+ promptClickHouseConnection: vi.fn(),
24
+ promptOutputDirectory: vi.fn(),
25
+ promptGenerateExample: vi.fn(),
26
+ promptTableSelection: vi.fn(),
27
+ confirmOverwrite: vi.fn(),
28
+ promptRetry: vi.fn(),
29
+ promptContinueWithoutDb: vi.fn(),
30
+ };
31
+ }
32
+ /**
33
+ * Mock database detection utilities
34
+ */
35
+ export function createMockDatabaseUtils() {
36
+ return {
37
+ validateConnection: vi.fn(),
38
+ getTableCount: vi.fn(),
39
+ getTables: vi.fn(),
40
+ };
41
+ }
42
+ /**
43
+ * Mock file system utilities
44
+ */
45
+ export function createMockFileUtils() {
46
+ return {
47
+ hasEnvFile: vi.fn(),
48
+ hasGitignore: vi.fn(),
49
+ findQueriesFile: vi.fn(),
50
+ findSchemaFile: vi.fn(),
51
+ };
52
+ }
53
+ /**
54
+ * Mock logger to capture output
55
+ */
56
+ export function createMockLogger() {
57
+ return {
58
+ success: vi.fn(),
59
+ error: vi.fn(),
60
+ warn: vi.fn(),
61
+ info: vi.fn(),
62
+ reload: vi.fn(),
63
+ header: vi.fn(),
64
+ newline: vi.fn(),
65
+ indent: vi.fn(),
66
+ box: vi.fn(),
67
+ table: vi.fn(),
68
+ raw: vi.fn(),
69
+ };
70
+ }
71
+ /**
72
+ * Mock ora spinner
73
+ */
74
+ export function createMockSpinner() {
75
+ var spinner = {
76
+ start: vi.fn().mockReturnThis(),
77
+ succeed: vi.fn().mockReturnThis(),
78
+ fail: vi.fn().mockReturnThis(),
79
+ stop: vi.fn().mockReturnThis(),
80
+ };
81
+ return vi.fn(function () { return spinner; });
82
+ }
83
+ /**
84
+ * Mock fs/promises for file operations
85
+ */
86
+ export function createMockFs() {
87
+ return {
88
+ mkdir: vi.fn().mockResolvedValue(undefined),
89
+ writeFile: vi.fn().mockResolvedValue(undefined),
90
+ readFile: vi.fn().mockResolvedValue(''),
91
+ access: vi.fn().mockResolvedValue(undefined),
92
+ };
93
+ }
94
+ /**
95
+ * Capture console output
96
+ */
97
+ export function captureConsole() {
98
+ var logs = [];
99
+ var errors = [];
100
+ var originalLog = console.log;
101
+ var originalError = console.error;
102
+ console.log = vi.fn(function () {
103
+ var args = [];
104
+ for (var _i = 0; _i < arguments.length; _i++) {
105
+ args[_i] = arguments[_i];
106
+ }
107
+ logs.push(args.join(' '));
108
+ });
109
+ console.error = vi.fn(function () {
110
+ var args = [];
111
+ for (var _i = 0; _i < arguments.length; _i++) {
112
+ args[_i] = arguments[_i];
113
+ }
114
+ errors.push(args.join(' '));
115
+ });
116
+ return {
117
+ logs: logs,
118
+ errors: errors,
119
+ restore: function () {
120
+ console.log = originalLog;
121
+ console.error = originalError;
122
+ },
123
+ };
124
+ }
125
+ /**
126
+ * Mock process.exit to prevent tests from exiting
127
+ * Throws a special error to stop execution
128
+ */
129
+ var ProcessExitError = /** @class */ (function (_super) {
130
+ __extends(ProcessExitError, _super);
131
+ function ProcessExitError(code) {
132
+ var _this = _super.call(this, "process.exit called with code ".concat(code)) || this;
133
+ _this.code = code;
134
+ _this.name = 'ProcessExitError';
135
+ return _this;
136
+ }
137
+ return ProcessExitError;
138
+ }(Error));
139
+ export { ProcessExitError };
140
+ export function mockProcessExit() {
141
+ var originalExit = process.exit;
142
+ var exitMock = vi.fn(function (code) {
143
+ throw new ProcessExitError(code !== null && code !== void 0 ? code : 0);
144
+ });
145
+ // @ts-ignore
146
+ process.exit = exitMock;
147
+ return {
148
+ exitMock: exitMock,
149
+ restore: function () {
150
+ process.exit = originalExit;
151
+ },
152
+ };
153
+ }
@@ -0,0 +1,11 @@
1
+ import { type ClickHouseClient } from '@clickhouse/client';
2
+ export interface ClickHouseEnvConfig {
3
+ url: string;
4
+ username: string;
5
+ password: string;
6
+ database: string;
7
+ }
8
+ export declare function getClickHouseConfigFromEnv(): ClickHouseEnvConfig | null;
9
+ export declare function getClickHouseClient(): ClickHouseClient;
10
+ export declare function resetClickHouseClientForTesting(): Promise<void>;
11
+ //# sourceMappingURL=clickhouse-client.d.ts.map