@hypequery/clickhouse 0.2.1 → 0.2.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-CLI.md +1 -1
- package/dist/cli/bin.js +129 -37
- package/dist/cli/generate-types.js +104 -15
- package/dist/core/connection.d.ts +112 -0
- package/dist/core/connection.d.ts.map +1 -1
- package/dist/core/connection.js +148 -25
- package/dist/core/cross-filter.d.ts +69 -0
- package/dist/core/cross-filter.d.ts.map +1 -1
- package/dist/core/cross-filter.js +1 -83
- package/dist/core/features/aggregations.d.ts +102 -0
- package/dist/core/features/analytics.d.ts +66 -0
- package/dist/core/features/analytics.d.ts.map +1 -1
- package/dist/core/features/cross-filtering.d.ts +31 -0
- package/dist/core/features/cross-filtering.d.ts.map +1 -0
- package/dist/core/features/cross-filtering.js +123 -0
- package/dist/core/features/executor.d.ts +19 -0
- package/dist/core/features/executor.js +3 -3
- package/dist/core/features/filtering.d.ts +95 -0
- package/dist/core/features/filtering.d.ts.map +1 -1
- package/dist/core/features/filtering.js +89 -3
- package/dist/core/features/joins.d.ts +29 -0
- package/dist/core/features/pagination.d.ts +23 -0
- package/dist/core/features/query-modifiers.d.ts +119 -0
- package/dist/core/formatters/sql-formatter.d.ts +9 -0
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.js +61 -5
- package/dist/core/join-relationships.d.ts +50 -0
- package/dist/core/join-relationships.d.ts.map +1 -1
- package/dist/core/query-builder.d.ts +258 -0
- package/dist/core/query-builder.d.ts.map +1 -1
- package/dist/core/query-builder.js +88 -27
- package/dist/core/tests/index.d.ts +2 -0
- package/dist/core/tests/integration/pagination-test-tbc.d.ts +2 -0
- package/dist/core/tests/integration/pagination-test-tbc.d.ts.map +1 -0
- package/dist/core/tests/integration/pagination-test-tbc.js +189 -0
- package/dist/core/tests/integration/setup.d.ts +40 -0
- package/dist/core/tests/integration/setup.d.ts.map +1 -1
- package/dist/core/tests/integration/setup.js +279 -238
- package/dist/core/tests/integration/test-config.d.ts +15 -0
- package/dist/core/tests/integration/test-config.d.ts.map +1 -0
- package/dist/core/tests/integration/test-config.js +15 -0
- package/dist/core/tests/integration/test-initializer.d.ts +7 -0
- package/dist/core/tests/integration/test-initializer.d.ts.map +1 -0
- package/dist/core/tests/integration/test-initializer.js +32 -0
- package/dist/core/tests/test-utils.d.ts +29 -0
- package/dist/core/tests/test-utils.d.ts.map +1 -1
- package/dist/core/tests/test-utils.js +6 -2
- package/dist/core/utils/logger.d.ts +37 -0
- package/dist/core/utils/logger.js +6 -6
- package/dist/core/utils/sql-expressions.d.ts +63 -0
- package/dist/core/utils/sql-expressions.d.ts.map +1 -1
- package/dist/core/utils/sql-expressions.js +9 -5
- package/dist/core/utils.d.ts +3 -0
- package/dist/core/validators/filter-validator.d.ts +8 -0
- package/dist/core/validators/filter-validator.js +1 -1
- package/dist/core/validators/value-validator.d.ts +6 -0
- package/dist/formatters/index.d.ts +1 -0
- package/dist/index.d.ts +12 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/types/base.d.ts +77 -0
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/clickhouse-types.d.ts +13 -0
- package/dist/types/clickhouse-types.d.ts.map +1 -1
- package/dist/types/filters.d.ts +53 -0
- package/dist/types/filters.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/package.json +36 -13
- package/README.md +0 -276
package/README-CLI.md
CHANGED
package/dist/cli/bin.js
CHANGED
|
@@ -26,7 +26,7 @@ const colors = {
|
|
|
26
26
|
*/
|
|
27
27
|
function showBanner() {
|
|
28
28
|
console.log(`
|
|
29
|
-
${colors.bright}${colors.cyan}
|
|
29
|
+
${colors.bright}${colors.cyan}hypequery TypeScript Generator${colors.reset}
|
|
30
30
|
${colors.dim}Generate TypeScript types from your ClickHouse database schema${colors.reset}
|
|
31
31
|
`);
|
|
32
32
|
}
|
|
@@ -37,27 +37,84 @@ ${colors.dim}Generate TypeScript types from your ClickHouse database schema${col
|
|
|
37
37
|
function showHelp() {
|
|
38
38
|
console.log(`
|
|
39
39
|
${colors.bright}Usage:${colors.reset}
|
|
40
|
-
npx hypequery-generate-types [
|
|
40
|
+
npx hypequery-generate-types [options]
|
|
41
41
|
|
|
42
|
-
${colors.bright}
|
|
43
|
-
output
|
|
42
|
+
${colors.bright}Options:${colors.reset}
|
|
43
|
+
--output=<path> Path where TypeScript definitions will be saved (default: "./generated-schema.ts")
|
|
44
|
+
--host=<url> ClickHouse server URL (default: http://localhost:8123)
|
|
45
|
+
--username=<user> ClickHouse username (default: default)
|
|
46
|
+
--password=<password> ClickHouse password
|
|
47
|
+
--database=<db> ClickHouse database name (default: default)
|
|
48
|
+
--include-tables=<tables> Comma-separated list of tables to include (default: all)
|
|
49
|
+
--exclude-tables=<tables> Comma-separated list of tables to exclude (default: none)
|
|
50
|
+
--secure Use HTTPS/TLS for connection
|
|
51
|
+
--help, -h Show this help text
|
|
44
52
|
|
|
45
53
|
${colors.bright}Environment variables:${colors.reset}
|
|
46
|
-
CLICKHOUSE_HOST ClickHouse server URL
|
|
47
|
-
|
|
54
|
+
CLICKHOUSE_HOST ClickHouse server URL
|
|
55
|
+
VITE_CLICKHOUSE_HOST Alternative variable for Vite projects
|
|
56
|
+
NEXT_PUBLIC_CLICKHOUSE_HOST Alternative variable for Next.js projects
|
|
57
|
+
|
|
58
|
+
CLICKHOUSE_USER ClickHouse username
|
|
59
|
+
VITE_CLICKHOUSE_USER Alternative variable for Vite projects
|
|
60
|
+
NEXT_PUBLIC_CLICKHOUSE_USER Alternative variable for Next.js projects
|
|
61
|
+
|
|
48
62
|
CLICKHOUSE_PASSWORD ClickHouse password
|
|
49
|
-
|
|
63
|
+
VITE_CLICKHOUSE_PASSWORD Alternative variable for Vite projects
|
|
64
|
+
NEXT_PUBLIC_CLICKHOUSE_PASSWORD Alternative variable for Next.js projects
|
|
65
|
+
|
|
66
|
+
CLICKHOUSE_DATABASE ClickHouse database name
|
|
67
|
+
VITE_CLICKHOUSE_DATABASE Alternative variable for Vite projects
|
|
68
|
+
NEXT_PUBLIC_CLICKHOUSE_DATABASE Alternative variable for Next.js projects
|
|
50
69
|
|
|
51
70
|
${colors.bright}Examples:${colors.reset}
|
|
52
71
|
npx hypequery-generate-types
|
|
53
|
-
npx hypequery-generate-types
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
--help, -h Show this help text
|
|
72
|
+
npx hypequery-generate-types --output=./src/types/db-schema.ts
|
|
73
|
+
npx hypequery-generate-types --host=https://your-instance.clickhouse.cloud:8443 --secure
|
|
74
|
+
npx hypequery-generate-types --host=http://localhost:8123 --username=default --password=password --database=my_db
|
|
75
|
+
npx hypequery-generate-types --include-tables=users,orders,products
|
|
58
76
|
`);
|
|
59
77
|
}
|
|
60
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Parse command line arguments into a configuration object
|
|
81
|
+
*/
|
|
82
|
+
function parseArguments(args) {
|
|
83
|
+
const config = {
|
|
84
|
+
output: './generated-schema.ts',
|
|
85
|
+
includeTables: [],
|
|
86
|
+
excludeTables: [],
|
|
87
|
+
secure: false
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
for (const arg of args) {
|
|
91
|
+
if (arg.startsWith('--output=')) {
|
|
92
|
+
config.output = arg.substring('--output='.length);
|
|
93
|
+
} else if (arg.startsWith('--host=')) {
|
|
94
|
+
config.host = arg.substring('--host='.length);
|
|
95
|
+
} else if (arg.startsWith('--username=')) {
|
|
96
|
+
config.username = arg.substring('--username='.length);
|
|
97
|
+
} else if (arg.startsWith('--password=')) {
|
|
98
|
+
config.password = arg.substring('--password='.length);
|
|
99
|
+
} else if (arg.startsWith('--database=')) {
|
|
100
|
+
config.database = arg.substring('--database='.length);
|
|
101
|
+
} else if (arg.startsWith('--include-tables=')) {
|
|
102
|
+
config.includeTables = arg.substring('--include-tables='.length).split(',');
|
|
103
|
+
} else if (arg.startsWith('--exclude-tables=')) {
|
|
104
|
+
config.excludeTables = arg.substring('--exclude-tables='.length).split(',');
|
|
105
|
+
} else if (arg === '--secure') {
|
|
106
|
+
config.secure = true;
|
|
107
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
108
|
+
config.showHelp = true;
|
|
109
|
+
} else if (!arg.startsWith('-') && !config.output) {
|
|
110
|
+
// For backwards compatibility, treat the first non-flag argument as the output path
|
|
111
|
+
config.output = arg;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return config;
|
|
116
|
+
}
|
|
117
|
+
|
|
61
118
|
/**
|
|
62
119
|
* Main CLI function
|
|
63
120
|
*/
|
|
@@ -66,55 +123,82 @@ async function main() {
|
|
|
66
123
|
|
|
67
124
|
// Process command line arguments
|
|
68
125
|
const args = process.argv.slice(2);
|
|
126
|
+
const config = parseArguments(args);
|
|
69
127
|
|
|
70
128
|
// Check for help flag
|
|
71
|
-
if (
|
|
129
|
+
if (config.showHelp) {
|
|
72
130
|
showHelp();
|
|
73
131
|
return;
|
|
74
132
|
}
|
|
75
133
|
|
|
76
|
-
// Get output path (default or from args)
|
|
77
|
-
const outputPath = args.length > 0 && !args[0].startsWith('-')
|
|
78
|
-
? args[0]
|
|
79
|
-
: './generated-schema.ts';
|
|
80
|
-
|
|
81
134
|
try {
|
|
82
|
-
//
|
|
83
|
-
const host =
|
|
84
|
-
|
|
135
|
+
// Get connection parameters from args and environment variables
|
|
136
|
+
const host = config.host ||
|
|
137
|
+
process.env.CLICKHOUSE_HOST ||
|
|
138
|
+
process.env.VITE_CLICKHOUSE_HOST ||
|
|
139
|
+
process.env.NEXT_PUBLIC_CLICKHOUSE_HOST ||
|
|
140
|
+
'http://localhost:8123';
|
|
141
|
+
|
|
142
|
+
const username = config.username ||
|
|
143
|
+
process.env.CLICKHOUSE_USER ||
|
|
144
|
+
process.env.VITE_CLICKHOUSE_USER ||
|
|
145
|
+
process.env.NEXT_PUBLIC_CLICKHOUSE_USER ||
|
|
146
|
+
'default';
|
|
147
|
+
|
|
148
|
+
const password = config.password ||
|
|
149
|
+
process.env.CLICKHOUSE_PASSWORD ||
|
|
150
|
+
process.env.VITE_CLICKHOUSE_PASSWORD ||
|
|
151
|
+
process.env.NEXT_PUBLIC_CLICKHOUSE_PASSWORD;
|
|
152
|
+
|
|
153
|
+
const database = config.database ||
|
|
154
|
+
process.env.CLICKHOUSE_DATABASE ||
|
|
155
|
+
process.env.VITE_CLICKHOUSE_DATABASE ||
|
|
156
|
+
process.env.NEXT_PUBLIC_CLICKHOUSE_DATABASE ||
|
|
157
|
+
'default';
|
|
85
158
|
|
|
86
159
|
console.log(`${colors.dim}Connecting to ClickHouse at ${colors.reset}${colors.bright}${host}${colors.reset}`);
|
|
87
160
|
console.log(`${colors.dim}Database: ${colors.reset}${colors.bright}${database}${colors.reset}`);
|
|
88
161
|
|
|
89
|
-
//
|
|
90
|
-
|
|
162
|
+
// Configure connection
|
|
163
|
+
const connectionConfig = {
|
|
91
164
|
host,
|
|
92
|
-
username
|
|
93
|
-
password
|
|
165
|
+
username,
|
|
166
|
+
password,
|
|
94
167
|
database,
|
|
95
|
-
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Add secure connection options if needed
|
|
171
|
+
if (config.secure || host.startsWith('https://')) {
|
|
172
|
+
connectionConfig.secure = true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Initialize connection
|
|
176
|
+
ClickHouseConnection.initialize(connectionConfig);
|
|
96
177
|
|
|
97
178
|
console.log(`${colors.dim}Generating TypeScript definitions...${colors.reset}`);
|
|
98
179
|
|
|
99
180
|
// Ensure directory exists
|
|
100
|
-
const dir = path.dirname(path.resolve(
|
|
181
|
+
const dir = path.dirname(path.resolve(config.output));
|
|
101
182
|
await fs.mkdir(dir, { recursive: true });
|
|
102
183
|
|
|
103
184
|
// Generate types
|
|
104
|
-
await generateTypes(
|
|
185
|
+
await generateTypes(config.output, {
|
|
186
|
+
includeTables: config.includeTables.length > 0 ? config.includeTables : undefined,
|
|
187
|
+
excludeTables: config.excludeTables.length > 0 ? config.excludeTables : undefined
|
|
188
|
+
});
|
|
105
189
|
|
|
106
|
-
console.log(`${colors.green}✓ Success! ${colors.reset}Types generated at ${colors.bright}${path.resolve(
|
|
190
|
+
console.log(`${colors.green}✓ Success! ${colors.reset}Types generated at ${colors.bright}${path.resolve(config.output)}${colors.reset}`);
|
|
107
191
|
console.log(`
|
|
108
192
|
${colors.dim}To use these types in your project:${colors.reset}
|
|
109
193
|
|
|
110
194
|
import { createQueryBuilder } from '@hypequery/clickhouse';
|
|
111
|
-
import { IntrospectedSchema } from '${
|
|
195
|
+
import { IntrospectedSchema } from '${config.output.replace(/\.ts$/, '')}';
|
|
112
196
|
|
|
113
197
|
const db = createQueryBuilder<IntrospectedSchema>({
|
|
114
|
-
host:
|
|
115
|
-
username:
|
|
116
|
-
password:
|
|
117
|
-
database:
|
|
198
|
+
host: '${host}',
|
|
199
|
+
username: '${username}',
|
|
200
|
+
password: '********',
|
|
201
|
+
database: '${database}'
|
|
118
202
|
});
|
|
119
203
|
`);
|
|
120
204
|
} catch (error) {
|
|
@@ -124,21 +208,29 @@ const db = createQueryBuilder<IntrospectedSchema>({
|
|
|
124
208
|
if (error.message && error.message.includes('ECONNREFUSED')) {
|
|
125
209
|
console.error(`
|
|
126
210
|
${colors.yellow}Connection refused.${colors.reset} Please check:
|
|
127
|
-
- Is ClickHouse running at
|
|
211
|
+
- Is ClickHouse running at the specified host?
|
|
128
212
|
- Do you need to provide authentication credentials?
|
|
129
213
|
- Are there any network/firewall restrictions?
|
|
214
|
+
- For cloud instances, did you include the port (usually 8443) and use HTTPS?
|
|
130
215
|
`);
|
|
131
216
|
} else if (error.message && error.message.includes('Authentication failed')) {
|
|
132
217
|
console.error(`
|
|
133
218
|
${colors.yellow}Authentication failed.${colors.reset} Please check:
|
|
134
|
-
- Are your
|
|
219
|
+
- Are your username and password correct?
|
|
220
|
+
- For ClickHouse Cloud, did you use the correct credentials from your cloud dashboard?
|
|
135
221
|
- Does the user have sufficient permissions?
|
|
136
222
|
`);
|
|
137
223
|
} else if (error.message && error.message.includes('database does not exist')) {
|
|
138
224
|
console.error(`
|
|
139
225
|
${colors.yellow}Database not found.${colors.reset} Please check:
|
|
140
|
-
- Is the
|
|
226
|
+
- Is the database name correct?
|
|
141
227
|
- Does the database exist in your ClickHouse instance?
|
|
228
|
+
`);
|
|
229
|
+
} else if (error.message && error.message.includes('certificate')) {
|
|
230
|
+
console.error(`
|
|
231
|
+
${colors.yellow}SSL/TLS certificate issue.${colors.reset} For secure connections:
|
|
232
|
+
- Try adding the --secure flag
|
|
233
|
+
- For ClickHouse Cloud, make sure you're using https:// and port 8443
|
|
142
234
|
`);
|
|
143
235
|
}
|
|
144
236
|
|
|
@@ -12,6 +12,12 @@ dotenv.config();
|
|
|
12
12
|
* @property {string} type - The ClickHouse type of the column
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {Object} GenerateTypesOptions
|
|
17
|
+
* @property {string[]} [includeTables] - List of tables to include
|
|
18
|
+
* @property {string[]} [excludeTables] - List of tables to exclude
|
|
19
|
+
*/
|
|
20
|
+
|
|
15
21
|
/**
|
|
16
22
|
* Converts ClickHouse types to TypeScript types
|
|
17
23
|
* @param {string} type - The ClickHouse type to convert
|
|
@@ -20,72 +26,155 @@ dotenv.config();
|
|
|
20
26
|
const clickhouseToTsType = (type) => {
|
|
21
27
|
if (type.startsWith('Array(')) {
|
|
22
28
|
const innerType = type.slice(6, -1);
|
|
23
|
-
return `Array
|
|
29
|
+
return `Array<${clickhouseToTsType(innerType)}>`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Handle Nullable types
|
|
33
|
+
if (type.startsWith('Nullable(')) {
|
|
34
|
+
const innerType = type.slice(9, -1);
|
|
35
|
+
return `${clickhouseToTsType(innerType)} | null`;
|
|
24
36
|
}
|
|
25
37
|
|
|
26
38
|
switch (type.toLowerCase()) {
|
|
27
39
|
case 'string':
|
|
28
40
|
case 'fixedstring':
|
|
29
|
-
return '
|
|
41
|
+
return 'string';
|
|
30
42
|
case 'int8':
|
|
31
43
|
case 'int16':
|
|
32
44
|
case 'int32':
|
|
33
|
-
|
|
45
|
+
case 'uint8':
|
|
46
|
+
case 'uint16':
|
|
47
|
+
case 'uint32':
|
|
48
|
+
return 'number';
|
|
34
49
|
case 'int64':
|
|
35
|
-
|
|
50
|
+
case 'uint64':
|
|
51
|
+
return 'string'; // Use string for 64-bit integers to avoid precision loss
|
|
36
52
|
case 'float32':
|
|
37
53
|
case 'float64':
|
|
38
|
-
|
|
54
|
+
case 'decimal':
|
|
55
|
+
return 'number';
|
|
39
56
|
case 'datetime':
|
|
40
|
-
|
|
57
|
+
case 'datetime64':
|
|
58
|
+
return 'string'; // Use string for datetime
|
|
41
59
|
case 'date':
|
|
42
|
-
|
|
60
|
+
case 'date32':
|
|
61
|
+
return 'string'; // Use string for date
|
|
62
|
+
case 'bool':
|
|
63
|
+
case 'boolean':
|
|
64
|
+
return 'boolean';
|
|
43
65
|
default:
|
|
44
|
-
return
|
|
66
|
+
// For complex types or unknown types, return string as a safe default
|
|
67
|
+
return 'string';
|
|
45
68
|
}
|
|
46
69
|
};
|
|
47
70
|
|
|
48
71
|
/**
|
|
49
72
|
* Generates TypeScript type definitions from the ClickHouse database schema
|
|
50
73
|
* @param {string} outputPath - The file path where the type definitions will be written
|
|
74
|
+
* @param {GenerateTypesOptions} [options] - Options for type generation
|
|
51
75
|
* @returns {Promise<void>}
|
|
52
76
|
*/
|
|
53
|
-
export async function generateTypes(outputPath) {
|
|
77
|
+
export async function generateTypes(outputPath, options = {}) {
|
|
54
78
|
const client = ClickHouseConnection.getClient();
|
|
79
|
+
const { includeTables = [], excludeTables = [] } = options;
|
|
55
80
|
|
|
56
81
|
// Get all tables
|
|
57
82
|
const tablesQuery = await client.query({
|
|
58
83
|
query: 'SHOW TABLES',
|
|
59
84
|
format: 'JSONEachRow'
|
|
60
85
|
});
|
|
61
|
-
|
|
86
|
+
let tables = await tablesQuery.json();
|
|
87
|
+
|
|
88
|
+
// Filter tables if includeTables or excludeTables are specified
|
|
89
|
+
if (includeTables.length > 0) {
|
|
90
|
+
tables = tables.filter(table => includeTables.includes(table.name));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (excludeTables.length > 0) {
|
|
94
|
+
tables = tables.filter(table => !excludeTables.includes(table.name));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If no tables remain after filtering, log a warning
|
|
98
|
+
if (tables.length === 0) {
|
|
99
|
+
console.warn('Warning: No tables match the filter criteria. Check your include/exclude options.');
|
|
100
|
+
}
|
|
62
101
|
|
|
63
102
|
let typeDefinitions = `// Generated by @hypequery/clickhouse
|
|
64
|
-
|
|
103
|
+
// This file defines TypeScript types based on your ClickHouse database schema
|
|
65
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Schema interface for use with createQueryBuilder<IntrospectedSchema>()
|
|
107
|
+
* The string literals represent ClickHouse data types for each column
|
|
108
|
+
*/
|
|
66
109
|
export interface IntrospectedSchema {`;
|
|
67
110
|
|
|
68
111
|
// Get columns for each table
|
|
69
112
|
for (const table of tables) {
|
|
70
113
|
const columnsQuery = await client.query({
|
|
71
|
-
query: `DESCRIBE ${table.name}`,
|
|
114
|
+
query: `DESCRIBE TABLE ${table.name}`,
|
|
72
115
|
format: 'JSONEachRow'
|
|
73
116
|
});
|
|
74
117
|
const columns = await columnsQuery.json();
|
|
75
|
-
|
|
76
118
|
typeDefinitions += `\n ${table.name}: {`;
|
|
77
119
|
for (const column of columns) {
|
|
78
|
-
|
|
120
|
+
const clickHouseType = column.type.replace(/'/g, "\\'"); // Escape single quotes, e.g. `DateTime('UTC')`
|
|
121
|
+
typeDefinitions += `\n ${column.name}: '${clickHouseType}';`;
|
|
79
122
|
}
|
|
80
123
|
typeDefinitions += '\n };';
|
|
81
124
|
}
|
|
82
125
|
|
|
83
126
|
typeDefinitions += '\n}\n';
|
|
84
127
|
|
|
128
|
+
// Also generate a type-safe record type for each table
|
|
129
|
+
typeDefinitions += `\n// Type-safe record types for each table\n`;
|
|
130
|
+
for (const table of tables) {
|
|
131
|
+
const columnsQuery = await client.query({
|
|
132
|
+
query: `DESCRIBE TABLE ${table.name}`,
|
|
133
|
+
format: 'JSONEachRow'
|
|
134
|
+
});
|
|
135
|
+
const columns = await columnsQuery.json();
|
|
136
|
+
|
|
137
|
+
typeDefinitions += `export interface ${capitalizeFirstLetter(table.name)}Record {`;
|
|
138
|
+
for (const column of columns) {
|
|
139
|
+
const tsType = clickhouseToTsType(column.type).replace(/'/g, '');
|
|
140
|
+
typeDefinitions += `\n ${column.name}: ${tsType};`;
|
|
141
|
+
}
|
|
142
|
+
typeDefinitions += '\n}\n\n';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Add a usage example
|
|
146
|
+
typeDefinitions += `
|
|
147
|
+
/**
|
|
148
|
+
* Usage example:
|
|
149
|
+
*
|
|
150
|
+
* import { createQueryBuilder } from '@hypequery/clickhouse';
|
|
151
|
+
* import { IntrospectedSchema } from './path-to-this-file.js';
|
|
152
|
+
*
|
|
153
|
+
* // Create a type-safe query builder
|
|
154
|
+
* const db = createQueryBuilder<IntrospectedSchema>();
|
|
155
|
+
*
|
|
156
|
+
* // Now you have full type safety and autocomplete
|
|
157
|
+
* const results = await db
|
|
158
|
+
* .from('${tables.length > 0 ? tables[0].name : 'table_name'}')
|
|
159
|
+
* .select(['column1', 'column2'])
|
|
160
|
+
* .where('column1', 'eq', 'value')
|
|
161
|
+
* .execute();
|
|
162
|
+
*/
|
|
163
|
+
`;
|
|
164
|
+
|
|
85
165
|
// Ensure the output directory exists
|
|
86
166
|
const outputDir = path.dirname(path.resolve(outputPath));
|
|
87
167
|
await fs.mkdir(outputDir, { recursive: true });
|
|
88
168
|
|
|
89
169
|
// Write the file
|
|
90
170
|
await fs.writeFile(path.resolve(outputPath), typeDefinitions);
|
|
91
|
-
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Capitalize the first letter of a string
|
|
175
|
+
* @param {string} str - The string to capitalize
|
|
176
|
+
* @returns {string} - The capitalized string
|
|
177
|
+
*/
|
|
178
|
+
function capitalizeFirstLetter(str) {
|
|
179
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
180
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { ClickHouseSettings } from '@clickhouse/client-common';
|
|
2
|
+
import type { ClickHouseClient as NodeClickHouseClient } from '@clickhouse/client';
|
|
3
|
+
import type { ClickHouseClient as WebClickHouseClient } from '@clickhouse/client-web';
|
|
4
|
+
import type { ClickHouseConfig } from './query-builder';
|
|
5
|
+
type ClickHouseClient = NodeClickHouseClient | WebClickHouseClient;
|
|
6
|
+
/**
|
|
7
|
+
* The main entry point for connecting to a ClickHouse database.
|
|
8
|
+
* Provides static methods to initialize the connection and retrieve the client.
|
|
9
|
+
*
|
|
10
|
+
* Supports two modes of operation:
|
|
11
|
+
* 1. **Manual injection**: Provide a client instance via `config.client` (required for browser environments)
|
|
12
|
+
* 2. **Auto-detection**: Automatically uses @clickhouse/client for Node.js environments
|
|
13
|
+
*
|
|
14
|
+
* @category Core
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Method 1: Manual injection (required for browser environments)
|
|
18
|
+
* import { createClient } from '@clickhouse/client-web';
|
|
19
|
+
* const client = createClient({
|
|
20
|
+
* host: 'http://localhost:8123',
|
|
21
|
+
* username: 'default',
|
|
22
|
+
* password: 'password'
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* ClickHouseConnection.initialize({
|
|
26
|
+
* host: 'http://localhost:8123',
|
|
27
|
+
* database: 'my_database',
|
|
28
|
+
* client // Explicitly provide the client
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Method 2: Auto-detection (Node.js environments only)
|
|
32
|
+
* ClickHouseConnection.initialize({
|
|
33
|
+
* host: 'http://localhost:8123',
|
|
34
|
+
* username: 'default',
|
|
35
|
+
* password: 'password',
|
|
36
|
+
* database: 'my_database'
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* // Get the client to execute queries directly
|
|
40
|
+
* const client = ClickHouseConnection.getClient();
|
|
41
|
+
* const result = await client.query({
|
|
42
|
+
* query: 'SELECT * FROM my_table',
|
|
43
|
+
* format: 'JSONEachRow'
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @note This library requires one of the following peer dependencies:
|
|
48
|
+
* - @clickhouse/client (for Node.js environments)
|
|
49
|
+
* - @clickhouse/client-web (for browser environments)
|
|
50
|
+
*
|
|
51
|
+
* **Important**: Browser environments require manual injection because `require()` calls don't work in browsers.
|
|
52
|
+
*/
|
|
53
|
+
export declare class ClickHouseConnection {
|
|
54
|
+
private static instance;
|
|
55
|
+
private static clientModule;
|
|
56
|
+
/**
|
|
57
|
+
* Initializes the ClickHouse connection with the provided configuration.
|
|
58
|
+
* This method must be called before any queries can be executed.
|
|
59
|
+
*
|
|
60
|
+
* **Priority order:**
|
|
61
|
+
* 1. If `config.client` is provided, use it directly (manual injection)
|
|
62
|
+
* 2. Otherwise, auto-detect @clickhouse/client for Node.js environments
|
|
63
|
+
*
|
|
64
|
+
* **Note**: Browser environments require manual injection because `require()` calls don't work in browsers.
|
|
65
|
+
*
|
|
66
|
+
* @param config - The connection configuration options
|
|
67
|
+
* @returns The ClickHouseConnection class for method chaining
|
|
68
|
+
* @throws Will throw an error if no ClickHouse client is available
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* // Manual injection (required for browser environments)
|
|
73
|
+
* import { createClient } from '@clickhouse/client-web';
|
|
74
|
+
* const client = createClient({ host: 'http://localhost:8123' });
|
|
75
|
+
* ClickHouseConnection.initialize({ host: 'http://localhost:8123', client });
|
|
76
|
+
*
|
|
77
|
+
* // Auto-detection (Node.js environments only)
|
|
78
|
+
* ClickHouseConnection.initialize({
|
|
79
|
+
* host: 'http://localhost:8123',
|
|
80
|
+
* username: 'default',
|
|
81
|
+
* password: 'password',
|
|
82
|
+
* database: 'my_database'
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
static initialize(config: ClickHouseConfig): typeof ClickHouseConnection;
|
|
87
|
+
/**
|
|
88
|
+
* Retrieves the ClickHouse client instance for direct query execution.
|
|
89
|
+
*
|
|
90
|
+
* @returns The ClickHouse client instance
|
|
91
|
+
* @throws Will throw an error if the connection has not been initialized
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const client = ClickHouseConnection.getClient();
|
|
96
|
+
* const result = await client.query({
|
|
97
|
+
* query: 'SELECT * FROM my_table',
|
|
98
|
+
* format: 'JSONEachRow'
|
|
99
|
+
* });
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
static getClient(): ClickHouseClient;
|
|
103
|
+
/**
|
|
104
|
+
* Gets the ClickHouseSettings type from the loaded client module.
|
|
105
|
+
* Only available when using auto-detection (not manual injection).
|
|
106
|
+
*
|
|
107
|
+
* @returns The ClickHouseSettings type or an empty object if not available
|
|
108
|
+
*/
|
|
109
|
+
static getClickHouseSettings(): ClickHouseSettings;
|
|
110
|
+
}
|
|
111
|
+
export {};
|
|
112
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAIxD,KAAK,gBAAgB,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AA+CnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAiC;IACxD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAuC;IAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,oBAAoB;IAaxE;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,SAAS,IAAI,gBAAgB;IAOpC;;;;;OAKG;IACH,MAAM,CAAC,qBAAqB,IAAI,kBAAkB;CAGnD"}
|