@hypequery/cli 0.0.1
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/LICENSE +201 -0
- package/README.md +246 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +3 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +189 -0
- package/dist/commands/create-api-types.d.ts +6 -0
- package/dist/commands/create-api-types.d.ts.map +1 -0
- package/dist/commands/create-api-types.js +149 -0
- package/dist/commands/dev.d.ts +12 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +253 -0
- package/dist/commands/generate.d.ts +7 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +193 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +363 -0
- package/dist/commands/toolkit.d.ts +6 -0
- package/dist/commands/toolkit.d.ts.map +1 -0
- package/dist/commands/toolkit.js +159 -0
- package/dist/templates/client.d.ts +5 -0
- package/dist/templates/client.d.ts.map +1 -0
- package/dist/templates/client.js +6 -0
- package/dist/templates/env.d.ts +14 -0
- package/dist/templates/env.d.ts.map +1 -0
- package/dist/templates/env.js +37 -0
- package/dist/templates/gitignore.d.ts +13 -0
- package/dist/templates/gitignore.d.ts.map +1 -0
- package/dist/templates/gitignore.js +22 -0
- package/dist/templates/queries.d.ts +8 -0
- package/dist/templates/queries.d.ts.map +1 -0
- package/dist/templates/queries.js +21 -0
- package/dist/test-utils.d.ts +86 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +153 -0
- package/dist/utils/detect-database.d.ts +21 -0
- package/dist/utils/detect-database.d.ts.map +1 -0
- package/dist/utils/detect-database.js +266 -0
- package/dist/utils/error-messages.d.ts +6 -0
- package/dist/utils/error-messages.d.ts.map +1 -0
- package/dist/utils/error-messages.js +19 -0
- package/dist/utils/find-files.d.ts +21 -0
- package/dist/utils/find-files.d.ts.map +1 -0
- package/dist/utils/find-files.js +183 -0
- package/dist/utils/load-api.d.ts +2 -0
- package/dist/utils/load-api.d.ts.map +1 -0
- package/dist/utils/load-api.js +163 -0
- package/dist/utils/logger.d.ts +54 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +122 -0
- package/dist/utils/prompts.d.ts +39 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +282 -0
- package/package.json +52 -0
|
@@ -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,CAmDT"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate queries.ts file
|
|
3
|
+
*/
|
|
4
|
+
export function generateQueriesTemplate(options) {
|
|
5
|
+
var hasExample = options.hasExample, tableName = options.tableName;
|
|
6
|
+
var template = "import { initServe } 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({";
|
|
7
|
+
if (hasExample && tableName) {
|
|
8
|
+
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 ),");
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
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 })),";
|
|
12
|
+
}
|
|
13
|
+
template += "\n }),\n});\n\n/**\n * Inline usage example:\n *\n * const result = await api.execute('".concat(hasExample && tableName ? camelCase(tableName) + 'Query' : 'exampleMetric', "');\n * console.log(result);\n *\n * Dev server:\n *\n * npx hypequery dev\n */\n");
|
|
14
|
+
return template;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Convert table name to camelCase
|
|
18
|
+
*/
|
|
19
|
+
function camelCase(str) {
|
|
20
|
+
return str.replace(/_([a-z])/g, function (_, letter) { return letter.toUpperCase(); });
|
|
21
|
+
}
|
|
@@ -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,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database type detection result
|
|
3
|
+
*/
|
|
4
|
+
export type DatabaseType = 'clickhouse' | 'bigquery' | 'unknown';
|
|
5
|
+
/**
|
|
6
|
+
* Auto-detect database type from environment or config files
|
|
7
|
+
*/
|
|
8
|
+
export declare function detectDatabase(): Promise<DatabaseType>;
|
|
9
|
+
/**
|
|
10
|
+
* Validate database connection
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateConnection(dbType: DatabaseType): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Get table count from database
|
|
15
|
+
*/
|
|
16
|
+
export declare function getTableCount(dbType: DatabaseType): Promise<number>;
|
|
17
|
+
/**
|
|
18
|
+
* Get list of tables from database
|
|
19
|
+
*/
|
|
20
|
+
export declare function getTables(dbType: DatabaseType): Promise<string[]>;
|
|
21
|
+
//# sourceMappingURL=detect-database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-database.d.ts","sourceRoot":"","sources":["../../src/utils/detect-database.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjE;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,YAAY,CAAC,CAyC5D;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAS/E;AAwBD;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAOzE;AA4BD;;GAEG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOvE"}
|
|
@@ -0,0 +1,266 @@
|
|
|
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 { access } from 'node:fs/promises';
|
|
38
|
+
import path from 'node:path';
|
|
39
|
+
/**
|
|
40
|
+
* Auto-detect database type from environment or config files
|
|
41
|
+
*/
|
|
42
|
+
export function detectDatabase() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
44
|
+
var envPath, readFile, envContent, _a;
|
|
45
|
+
return __generator(this, function (_b) {
|
|
46
|
+
switch (_b.label) {
|
|
47
|
+
case 0:
|
|
48
|
+
// Check environment variables
|
|
49
|
+
if (process.env.CLICKHOUSE_HOST ||
|
|
50
|
+
process.env.CLICKHOUSE_URL ||
|
|
51
|
+
process.env.CLICKHOUSE_DATABASE) {
|
|
52
|
+
return [2 /*return*/, 'clickhouse'];
|
|
53
|
+
}
|
|
54
|
+
if (process.env.BIGQUERY_PROJECT_ID || process.env.GOOGLE_APPLICATION_CREDENTIALS) {
|
|
55
|
+
return [2 /*return*/, 'bigquery'];
|
|
56
|
+
}
|
|
57
|
+
_b.label = 1;
|
|
58
|
+
case 1:
|
|
59
|
+
_b.trys.push([1, 5, , 6]);
|
|
60
|
+
envPath = path.join(process.cwd(), '.env');
|
|
61
|
+
return [4 /*yield*/, access(envPath)];
|
|
62
|
+
case 2:
|
|
63
|
+
_b.sent();
|
|
64
|
+
return [4 /*yield*/, import('node:fs/promises')];
|
|
65
|
+
case 3:
|
|
66
|
+
readFile = (_b.sent()).readFile;
|
|
67
|
+
return [4 /*yield*/, readFile(envPath, 'utf-8')];
|
|
68
|
+
case 4:
|
|
69
|
+
envContent = _b.sent();
|
|
70
|
+
if (envContent.includes('CLICKHOUSE_') ||
|
|
71
|
+
envContent.includes('CLICKHOUSE_HOST')) {
|
|
72
|
+
return [2 /*return*/, 'clickhouse'];
|
|
73
|
+
}
|
|
74
|
+
if (envContent.includes('BIGQUERY_') ||
|
|
75
|
+
envContent.includes('GOOGLE_APPLICATION_CREDENTIALS')) {
|
|
76
|
+
return [2 /*return*/, 'bigquery'];
|
|
77
|
+
}
|
|
78
|
+
return [3 /*break*/, 6];
|
|
79
|
+
case 5:
|
|
80
|
+
_a = _b.sent();
|
|
81
|
+
return [3 /*break*/, 6];
|
|
82
|
+
case 6: return [2 /*return*/, 'unknown'];
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate database connection
|
|
89
|
+
*/
|
|
90
|
+
export function validateConnection(dbType) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
92
|
+
return __generator(this, function (_a) {
|
|
93
|
+
switch (dbType) {
|
|
94
|
+
case 'clickhouse':
|
|
95
|
+
return [2 /*return*/, validateClickHouse()];
|
|
96
|
+
case 'bigquery':
|
|
97
|
+
return [2 /*return*/, validateBigQuery()];
|
|
98
|
+
default:
|
|
99
|
+
return [2 /*return*/, false];
|
|
100
|
+
}
|
|
101
|
+
return [2 /*return*/];
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function validateClickHouse() {
|
|
106
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
107
|
+
var client, result, error_1;
|
|
108
|
+
return __generator(this, function (_a) {
|
|
109
|
+
switch (_a.label) {
|
|
110
|
+
case 0:
|
|
111
|
+
_a.trys.push([0, 4, , 5]);
|
|
112
|
+
return [4 /*yield*/, getClickHouseClient()];
|
|
113
|
+
case 1:
|
|
114
|
+
client = _a.sent();
|
|
115
|
+
return [4 /*yield*/, client.query({
|
|
116
|
+
query: 'SELECT 1',
|
|
117
|
+
format: 'JSONEachRow',
|
|
118
|
+
})];
|
|
119
|
+
case 2:
|
|
120
|
+
result = _a.sent();
|
|
121
|
+
return [4 /*yield*/, result.json()];
|
|
122
|
+
case 3:
|
|
123
|
+
_a.sent();
|
|
124
|
+
return [2 /*return*/, true];
|
|
125
|
+
case 4:
|
|
126
|
+
error_1 = _a.sent();
|
|
127
|
+
return [2 /*return*/, false];
|
|
128
|
+
case 5: return [2 /*return*/];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function validateBigQuery() {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
135
|
+
return __generator(this, function (_a) {
|
|
136
|
+
// TODO: Implement when BigQuery support is added
|
|
137
|
+
return [2 /*return*/, false];
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get table count from database
|
|
143
|
+
*/
|
|
144
|
+
export function getTableCount(dbType) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
146
|
+
return __generator(this, function (_a) {
|
|
147
|
+
switch (dbType) {
|
|
148
|
+
case 'clickhouse':
|
|
149
|
+
return [2 /*return*/, getClickHouseTableCount()];
|
|
150
|
+
default:
|
|
151
|
+
return [2 /*return*/, 0];
|
|
152
|
+
}
|
|
153
|
+
return [2 /*return*/];
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Generic helper to execute ClickHouse queries with consistent error handling
|
|
159
|
+
*/
|
|
160
|
+
function executeClickHouseQuery(query, defaultValue) {
|
|
161
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
162
|
+
var client, result, _a;
|
|
163
|
+
return __generator(this, function (_b) {
|
|
164
|
+
switch (_b.label) {
|
|
165
|
+
case 0:
|
|
166
|
+
_b.trys.push([0, 4, , 5]);
|
|
167
|
+
return [4 /*yield*/, getClickHouseClient()];
|
|
168
|
+
case 1:
|
|
169
|
+
client = _b.sent();
|
|
170
|
+
return [4 /*yield*/, client.query({
|
|
171
|
+
query: query,
|
|
172
|
+
format: 'JSONEachRow',
|
|
173
|
+
})];
|
|
174
|
+
case 2:
|
|
175
|
+
result = _b.sent();
|
|
176
|
+
return [4 /*yield*/, result.json()];
|
|
177
|
+
case 3: return [2 /*return*/, (_b.sent())];
|
|
178
|
+
case 4:
|
|
179
|
+
_a = _b.sent();
|
|
180
|
+
return [2 /*return*/, defaultValue];
|
|
181
|
+
case 5: return [2 /*return*/];
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function getClickHouseTableCount() {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
188
|
+
var tables;
|
|
189
|
+
return __generator(this, function (_a) {
|
|
190
|
+
switch (_a.label) {
|
|
191
|
+
case 0: return [4 /*yield*/, executeClickHouseQuery('SHOW TABLES', [])];
|
|
192
|
+
case 1:
|
|
193
|
+
tables = _a.sent();
|
|
194
|
+
return [2 /*return*/, Array.isArray(tables) ? tables.length : 0];
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Get list of tables from database
|
|
201
|
+
*/
|
|
202
|
+
export function getTables(dbType) {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
204
|
+
return __generator(this, function (_a) {
|
|
205
|
+
switch (dbType) {
|
|
206
|
+
case 'clickhouse':
|
|
207
|
+
return [2 /*return*/, getClickHouseTables()];
|
|
208
|
+
default:
|
|
209
|
+
return [2 /*return*/, []];
|
|
210
|
+
}
|
|
211
|
+
return [2 /*return*/];
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function getClickHouseTables() {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
217
|
+
var tables;
|
|
218
|
+
return __generator(this, function (_a) {
|
|
219
|
+
switch (_a.label) {
|
|
220
|
+
case 0: return [4 /*yield*/, executeClickHouseQuery('SHOW TABLES', [])];
|
|
221
|
+
case 1:
|
|
222
|
+
tables = _a.sent();
|
|
223
|
+
return [2 /*return*/, tables.map(function (t) { return t.name; })];
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function getClickHouseClient() {
|
|
229
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
230
|
+
var ClickHouseConnection, config;
|
|
231
|
+
return __generator(this, function (_a) {
|
|
232
|
+
switch (_a.label) {
|
|
233
|
+
case 0: return [4 /*yield*/, import('@hypequery/clickhouse')];
|
|
234
|
+
case 1:
|
|
235
|
+
ClickHouseConnection = (_a.sent()).ClickHouseConnection;
|
|
236
|
+
try {
|
|
237
|
+
return [2 /*return*/, ClickHouseConnection.getClient()];
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
if (error instanceof Error && error.message.includes('ClickHouse connection not initialized')) {
|
|
241
|
+
config = getClickHouseEnvConfig();
|
|
242
|
+
if (!config) {
|
|
243
|
+
throw new Error('ClickHouse connection details are missing. Set CLICKHOUSE_HOST, CLICKHOUSE_DATABASE, CLICKHOUSE_USERNAME, and CLICKHOUSE_PASSWORD.');
|
|
244
|
+
}
|
|
245
|
+
ClickHouseConnection.initialize(config);
|
|
246
|
+
return [2 /*return*/, ClickHouseConnection.getClient()];
|
|
247
|
+
}
|
|
248
|
+
throw error;
|
|
249
|
+
}
|
|
250
|
+
return [2 /*return*/];
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function getClickHouseEnvConfig() {
|
|
256
|
+
var host = process.env.CLICKHOUSE_HOST || process.env.CLICKHOUSE_URL;
|
|
257
|
+
if (!host) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
host: host,
|
|
262
|
+
database: process.env.CLICKHOUSE_DATABASE || 'default',
|
|
263
|
+
username: process.env.CLICKHOUSE_USERNAME || process.env.CLICKHOUSE_USER || 'default',
|
|
264
|
+
password: process.env.CLICKHOUSE_PASSWORD || process.env.CLICKHOUSE_PASS || '',
|
|
265
|
+
};
|
|
266
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-messages.d.ts","sourceRoot":"","sources":["../../src/utils/error-messages.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAazE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { logger } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Display error when queries file cannot be found
|
|
4
|
+
* @param commandName - Name of the command for the usage example
|
|
5
|
+
*/
|
|
6
|
+
export function displayQueriesFileNotFoundError(commandName) {
|
|
7
|
+
logger.error('Could not find queries file');
|
|
8
|
+
logger.newline();
|
|
9
|
+
logger.info('Expected one of:');
|
|
10
|
+
logger.indent('• analytics/queries.ts');
|
|
11
|
+
logger.indent('• src/analytics/queries.ts');
|
|
12
|
+
logger.indent('• hypequery.ts');
|
|
13
|
+
logger.newline();
|
|
14
|
+
logger.info("Did you run 'hypequery init'?");
|
|
15
|
+
logger.newline();
|
|
16
|
+
logger.info('Or specify the file explicitly:');
|
|
17
|
+
logger.indent("hypequery ".concat(commandName, " ./path/to/queries.ts"));
|
|
18
|
+
logger.newline();
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the queries file in the project
|
|
3
|
+
*/
|
|
4
|
+
export declare function findQueriesFile(customPath?: string): Promise<string | null>;
|
|
5
|
+
/**
|
|
6
|
+
* Find the schema file (generated types)
|
|
7
|
+
*/
|
|
8
|
+
export declare function findSchemaFile(): Promise<string | null>;
|
|
9
|
+
/**
|
|
10
|
+
* Find the client file
|
|
11
|
+
*/
|
|
12
|
+
export declare function findClientFile(): Promise<string | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Check if .env file exists
|
|
15
|
+
*/
|
|
16
|
+
export declare function hasEnvFile(): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if .gitignore exists
|
|
19
|
+
*/
|
|
20
|
+
export declare function hasGitignore(): Promise<boolean>;
|
|
21
|
+
//# sourceMappingURL=find-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-files.d.ts","sourceRoot":"","sources":["../../src/utils/find-files.ts"],"names":[],"mappings":"AA+BA;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcjF;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAO7D;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAOnD;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAOrD"}
|