@hypequery/clickhouse 0.2.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.
Files changed (61) hide show
  1. package/README-CLI.md +123 -0
  2. package/README.md +276 -0
  3. package/dist/cli/bin.js +151 -0
  4. package/dist/cli/generate-types.d.ts +5 -0
  5. package/dist/cli/generate-types.js +91 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.js +2 -0
  8. package/dist/core/connection.d.ts.map +1 -0
  9. package/dist/core/connection.js +34 -0
  10. package/dist/core/cross-filter.d.ts.map +1 -0
  11. package/dist/core/cross-filter.js +218 -0
  12. package/dist/core/features/aggregations.d.ts.map +1 -0
  13. package/dist/core/features/aggregations.js +35 -0
  14. package/dist/core/features/analytics.d.ts.map +1 -0
  15. package/dist/core/features/analytics.js +35 -0
  16. package/dist/core/features/executor.d.ts.map +1 -0
  17. package/dist/core/features/executor.js +136 -0
  18. package/dist/core/features/filtering.d.ts.map +1 -0
  19. package/dist/core/features/filtering.js +30 -0
  20. package/dist/core/features/joins.d.ts.map +1 -0
  21. package/dist/core/features/joins.js +16 -0
  22. package/dist/core/features/pagination.d.ts.map +1 -0
  23. package/dist/core/features/pagination.js +190 -0
  24. package/dist/core/features/query-modifiers.d.ts.map +1 -0
  25. package/dist/core/features/query-modifiers.js +50 -0
  26. package/dist/core/formatters/sql-formatter.d.ts.map +1 -0
  27. package/dist/core/formatters/sql-formatter.js +69 -0
  28. package/dist/core/join-relationships.d.ts.map +1 -0
  29. package/dist/core/join-relationships.js +56 -0
  30. package/dist/core/query-builder.d.ts.map +1 -0
  31. package/dist/core/query-builder.js +372 -0
  32. package/dist/core/tests/index.d.ts.map +1 -0
  33. package/dist/core/tests/index.js +1 -0
  34. package/dist/core/tests/integration/setup.d.ts.map +1 -0
  35. package/dist/core/tests/integration/setup.js +274 -0
  36. package/dist/core/tests/test-utils.d.ts.map +1 -0
  37. package/dist/core/tests/test-utils.js +32 -0
  38. package/dist/core/utils/logger.d.ts.map +1 -0
  39. package/dist/core/utils/logger.js +98 -0
  40. package/dist/core/utils/sql-expressions.d.ts.map +1 -0
  41. package/dist/core/utils/sql-expressions.js +73 -0
  42. package/dist/core/utils.d.ts.map +1 -0
  43. package/dist/core/utils.js +29 -0
  44. package/dist/core/validators/filter-validator.d.ts.map +1 -0
  45. package/dist/core/validators/filter-validator.js +19 -0
  46. package/dist/core/validators/value-validator.d.ts.map +1 -0
  47. package/dist/core/validators/value-validator.js +47 -0
  48. package/dist/formatters/index.d.ts.map +1 -0
  49. package/dist/formatters/index.js +1 -0
  50. package/dist/index.d.ts +33 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +5 -0
  53. package/dist/types/base.d.ts.map +1 -0
  54. package/dist/types/base.js +1 -0
  55. package/dist/types/clickhouse-types.d.ts.map +1 -0
  56. package/dist/types/clickhouse-types.js +1 -0
  57. package/dist/types/filters.d.ts.map +1 -0
  58. package/dist/types/filters.js +1 -0
  59. package/dist/types/index.d.ts.map +1 -0
  60. package/dist/types/index.js +2 -0
  61. package/package.json +67 -0
package/README-CLI.md ADDED
@@ -0,0 +1,123 @@
1
+ # HypeQuery TypeScript Generator
2
+
3
+ This tool automatically generates TypeScript type definitions from your ClickHouse database schema.
4
+
5
+ ## Installation
6
+
7
+ The TypeScript generator is included with the `@hypequery/clickhouse` package:
8
+
9
+ ```bash
10
+ npm install @hypequery/clickhouse
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ Generate TypeScript types for your ClickHouse database:
16
+
17
+ ```bash
18
+ npx hypequery-generate-types
19
+ ```
20
+
21
+ This will:
22
+ 1. Connect to your ClickHouse database using environment variables
23
+ 2. Introspect all tables in your database
24
+ 3. Generate TypeScript definitions in `./generated-schema.ts`
25
+
26
+ ## Example Usage
27
+
28
+ **Generate types with a custom output path:**
29
+
30
+ ```bash
31
+ npx hypequery-generate-types ./src/types/db-schema.ts
32
+ ```
33
+
34
+ **Specify database connection directly:**
35
+
36
+ ```bash
37
+ CLICKHOUSE_HOST=http://clickhouse.example.com:8123 \
38
+ CLICKHOUSE_USER=myuser \
39
+ CLICKHOUSE_PASSWORD=mypassword \
40
+ CLICKHOUSE_DATABASE=analytics \
41
+ npx hypequery-generate-types
42
+ ```
43
+
44
+ ## Configuration
45
+
46
+ Configure the connection using environment variables:
47
+
48
+ | Variable | Description | Default |
49
+ |----------|-------------|---------|
50
+ | `CLICKHOUSE_HOST` | ClickHouse server URL | `http://localhost:8123` |
51
+ | `CLICKHOUSE_USER` | ClickHouse username | `default` |
52
+ | `CLICKHOUSE_PASSWORD` | ClickHouse password | _(empty)_ |
53
+ | `CLICKHOUSE_DATABASE` | ClickHouse database name | `default` |
54
+
55
+ You can set these in:
56
+ - A `.env` file in your project root
57
+ - Your system environment
58
+ - Directly when running the command
59
+
60
+ ## Using Generated Types
61
+
62
+ Import the generated types in your code:
63
+
64
+ ```typescript
65
+ import { createQueryBuilder } from '@hypequery/clickhouse';
66
+ import { IntrospectedSchema } from './generated-schema';
67
+
68
+ // Create a type-safe query builder
69
+ const db = createQueryBuilder<IntrospectedSchema>({
70
+ host: process.env.CLICKHOUSE_HOST,
71
+ username: process.env.CLICKHOUSE_USER,
72
+ password: process.env.CLICKHOUSE_PASSWORD,
73
+ database: process.env.CLICKHOUSE_DATABASE,
74
+ });
75
+
76
+ // Enjoy complete type safety!
77
+ const results = await db
78
+ .table('users') // TypeScript checks table exists
79
+ .select(['id', 'name']) // TypeScript checks columns exist
80
+ .where('id', 'gt', 10) // TypeScript validates types
81
+ .execute();
82
+
83
+ // Results are properly typed
84
+ results.forEach(user => {
85
+ console.log(user.name); // TypeScript knows this is a string
86
+ });
87
+ ```
88
+
89
+ ## Adding to Your Workflow
90
+
91
+ Add it to your npm scripts:
92
+
93
+ ```json
94
+ {
95
+ "scripts": {
96
+ "generate-types": "hypequery-generate-types ./src/types/db-schema.ts",
97
+ "prebuild": "npm run generate-types",
98
+ "build": "tsc"
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## Troubleshooting
104
+
105
+ If you encounter issues:
106
+
107
+ 1. **Connection problems**
108
+ - Make sure ClickHouse is running and accessible
109
+ - Check your firewall settings
110
+
111
+ 2. **Authentication failures**
112
+ - Verify your username and password
113
+ - Ensure the user has sufficient permissions
114
+
115
+ 3. **Missing tables**
116
+ - Confirm you're connecting to the correct database
117
+ - Verify the tables exist in your ClickHouse instance
118
+
119
+ For more help, run:
120
+
121
+ ```bash
122
+ npx hypequery-generate-types --help
123
+ ```
package/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # HypeQuery
2
+
3
+ <div align="center">
4
+ <img src="https://hypequery.dev/img/logo.svg" alt="HypeQuery Logo" width="200"/>
5
+ <h1>@hypequery/clickhouse</h1>
6
+ <p>A typescript-first library for building type-safe dashboards with ClickHouse</p>
7
+
8
+ [![GitHub license](https://img.shields.io/github/license/lukejreilly/hypequery)](https://github.com/lukejreilly/hypequery/blob/main/LICENSE)
9
+ [![npm version](https://badge.fury.io/js/@hypequery%2Fcore.svg)](https://badge.fury.io/js/@hypequery%2Fcore)
10
+ [![GitHub stars](https://img.shields.io/github/stars/lukejreilly/hypequery)](https://github.com/lukejreilly/hypequery/stargazers)
11
+ </div>
12
+
13
+ > **Note:** This package is published on npm as `@hypequery/core`. The unscoped package `hypequery-core` is unrelated and should not be used.
14
+
15
+ ## Overview
16
+
17
+ hypequery is a typescript-first query builder for ClickHouse designed specifically for building real-time, type-safe analytics dashboards. Unlike generic SQL query builders, HypeQuery understands your ClickHouse schema and provides full type checking throughout your codebase, making it ideal for data-intensive applications.
18
+
19
+ ## Features
20
+
21
+ - 🎯 **Type-Safe**: Full TypeScript support with inferred types from your ClickHouse schema
22
+ - 🚀 **Performant**: Built for real-time analytics with optimized query generation
23
+ - 🔍 **Cross Filtering**: Powerful cross-filtering capabilities for interactive dashboards
24
+ - 📊 **Dashboard Ready**: Built-in support for pagination, sorting, and filtering
25
+ - 🛠️ **Developer Friendly**: Fluent API design for an intuitive development experience
26
+ - 📱 **Platform Agnostic**: Works in both Node.js and browser environments
27
+ - 🔄 **Schema Generation**: CLI tool to generate TypeScript types from your ClickHouse schema
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ # npm
33
+ npm install @hypequery/core
34
+
35
+ # yarn
36
+ yarn add @hypequery/core
37
+
38
+ # pnpm
39
+ pnpm add @hypequery/core
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ```typescript
45
+ import { createQueryBuilder } from '@hypequery/core';
46
+ import type { Schema } from './generated-schema';
47
+
48
+ // Initialize the query builder
49
+ const db = createQueryBuilder<Schema>({
50
+ host: 'your-clickhouse-host',
51
+ username: 'default',
52
+ password: '',
53
+ database: 'default'
54
+ });
55
+
56
+ // Build and execute a query
57
+ const results = await db
58
+ .table('trips')
59
+ .select(['pickup_datetime', 'dropoff_datetime', 'total_amount'])
60
+ .where('total_amount', '>', 50)
61
+ .orderBy('pickup_datetime', 'DESC')
62
+ .limit(10)
63
+ .execute();
64
+ ```
65
+
66
+ ## Schema Generation
67
+
68
+ HypeQuery provides a CLI tool to generate TypeScript types from your ClickHouse schema:
69
+
70
+ ```bash
71
+ # Install globally (optional)
72
+ npm install -g @hypequery/core
73
+
74
+ # Generate schema types
75
+ npx hypequery-generate --host your-clickhouse-host --database your-database
76
+ ```
77
+
78
+ This creates a `generated-schema.ts` file that you can import in your application:
79
+
80
+ ```typescript
81
+ import { createQueryBuilder } from '@hypequery/core';
82
+ import type { IntrospectedSchema } from './generated-schema';
83
+
84
+ const db = createQueryBuilder<IntrospectedSchema>({
85
+ // connection details
86
+ });
87
+ ```
88
+
89
+ ## Core Features
90
+
91
+ ### Type-Safe Queries
92
+
93
+ HypeQuery provides full TypeScript support, ensuring your queries are type-safe:
94
+
95
+ ```typescript
96
+ // Column names are type-checked
97
+ const query = db.table('trips')
98
+ .select(['pickup_datetime', 'total_amount'])
99
+ .where('total_amount', '>', 50)
100
+ .execute();
101
+
102
+ // Type error if column doesn't exist
103
+ db.table('trips').select(['non_existent_column']); // TypeScript error
104
+ ```
105
+
106
+ ### Cross Filtering
107
+
108
+ Implement interactive dashboards with cross-filtering support:
109
+
110
+ ```typescript
111
+ import { CrossFilter } from '@hypequery/core';
112
+
113
+ // Create a filter
114
+ const filter = new CrossFilter()
115
+ .add({
116
+ column: 'pickup_datetime',
117
+ operator: 'gte',
118
+ value: '2024-01-01'
119
+ })
120
+ .add({
121
+ column: 'total_amount',
122
+ operator: 'gt',
123
+ value: 20
124
+ });
125
+
126
+ // Apply to multiple queries
127
+ const query1 = db.table('trips')
128
+ .applyCrossFilters(filter)
129
+ .execute();
130
+
131
+ const query2 = db.table('drivers')
132
+ .applyCrossFilters(filter)
133
+ .execute();
134
+ ```
135
+
136
+ ### Pagination
137
+
138
+ Built-in cursor-based pagination for efficient data loading:
139
+
140
+ ```typescript
141
+ // First page
142
+ const firstPage = await db.table('trips')
143
+ .select(['pickup_datetime', 'total_amount'])
144
+ .orderBy('pickup_datetime', 'DESC')
145
+ .paginate({
146
+ pageSize: 10
147
+ });
148
+
149
+ // Next page
150
+ const nextPage = await db.table('trips')
151
+ .select(['pickup_datetime', 'total_amount'])
152
+ .orderBy('pickup_datetime', 'DESC')
153
+ .paginate({
154
+ pageSize: 10,
155
+ after: firstPage.pageInfo.endCursor
156
+ });
157
+
158
+ // Previous page
159
+ const prevPage = await db.table('trips')
160
+ .select(['pickup_datetime', 'total_amount'])
161
+ .orderBy('pickup_datetime', 'DESC')
162
+ .paginate({
163
+ pageSize: 10,
164
+ before: nextPage.pageInfo.startCursor
165
+ });
166
+ ```
167
+
168
+ ### Advanced Queries
169
+
170
+ HypeQuery supports complex queries including joins, aggregations, and subqueries:
171
+
172
+ ```typescript
173
+ // Aggregations
174
+ const stats = await db.table('trips')
175
+ .avg('total_amount')
176
+ .max('trip_distance')
177
+ .count('trip_id')
178
+ .where('pickup_datetime', '>=', '2024-01-01')
179
+ .execute();
180
+
181
+ // Joins
182
+ const tripsWithDrivers = await db.table('trips')
183
+ .select(['trips.trip_id', 'trips.total_amount', 'drivers.name'])
184
+ .join('drivers', 'trips.driver_id', '=', 'drivers.id')
185
+ .execute();
186
+
187
+ // Raw SQL when needed
188
+ const customQuery = await db.table('trips')
189
+ .select([
190
+ db.raw('toStartOfDay(pickup_datetime) as day'),
191
+ 'count() as trip_count'
192
+ ])
193
+ .groupBy(db.raw('toStartOfDay(pickup_datetime)'))
194
+ .execute();
195
+ ```
196
+
197
+ ## Environment Support
198
+
199
+ ### Browser Environment
200
+
201
+ For browser usage, you'll typically need to set up a proxy server to avoid CORS issues:
202
+
203
+ ```typescript
204
+ const db = createQueryBuilder<Schema>({
205
+ host: '/api/clickhouse', // Proxy through your API route
206
+ username: 'default',
207
+ password: '',
208
+ database: 'default'
209
+ });
210
+ ```
211
+
212
+ ### Node.js Environment
213
+
214
+ For server-side applications, you can connect directly to ClickHouse:
215
+
216
+ ```typescript
217
+ const db = createQueryBuilder<Schema>({
218
+ host: 'http://your-clickhouse-server:8123',
219
+ username: 'default',
220
+ password: 'your-password',
221
+ database: 'default'
222
+ });
223
+ ```
224
+
225
+ ## Versioning and Release Channels
226
+
227
+ HypeQuery follows semantic versioning and provides multiple release channels:
228
+
229
+ - **Latest**: Stable releases (`npm install @hypequery/core`)
230
+ - **Beta**: Pre-release versions (`npm install @hypequery/core@beta`)
231
+
232
+ ## Documentation
233
+
234
+ For detailed documentation and examples, visit our [documentation site](https://hypequery.dev/docs).
235
+
236
+ - [Getting Started](https://hypequery.dev/docs/installation)
237
+ - [Query Building](https://hypequery.dev/docs/guides/query-building)
238
+ - [Filtering](https://hypequery.dev/docs/guides/filtering)
239
+ - [Pagination](https://hypequery.dev/docs/features/pagination)
240
+ - [API Reference](https://hypequery.dev/docs/reference/api)
241
+
242
+ ## Examples
243
+
244
+ Check out our example implementations:
245
+
246
+ - [Example Dashboard](https://github.com/lukejreilly/hypequery/tree/main/examples/example-dashboard): A complete Next.js dashboard with HypeQuery
247
+ - [React Query Integration](https://hypequery.dev/docs/guides/integrations/react-query): Using HypeQuery with React Query
248
+ - [Time Series Analysis](https://hypequery.dev/docs/guides/timeseries): Building time series analytics
249
+
250
+ ## Troubleshooting
251
+
252
+ ### Common Issues
253
+
254
+ - **Connection Errors**: Ensure your ClickHouse server is running and accessible
255
+ - **CORS Issues**: Use a proxy server for browser environments
256
+ - **Type Errors**: Make sure to regenerate your schema types after schema changes
257
+
258
+ ## Contributing
259
+
260
+ We welcome contributions! Please see our [contributing guide](CONTRIBUTING.md) for details.
261
+
262
+ ## License
263
+
264
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
265
+
266
+ ## Support
267
+
268
+ - 📚 [Documentation](https://hypequery.dev/docs)
269
+ - 🐛 [Issue Tracker](https://github.com/lukejreilly/hypequery/issues)
270
+ - 💬 [Discussions](https://github.com/lukejreilly/hypequery/discussions)
271
+
272
+ ---
273
+
274
+ <div align="center">
275
+ <sub>Built with ❤️ by the HypeQuery team</sub>
276
+ </div>
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { ClickHouseConnection } from '../core/connection.js';
4
+ import { generateTypes } from './generate-types.js';
5
+ import path from 'path';
6
+ import dotenv from 'dotenv';
7
+ import fs from 'fs/promises';
8
+
9
+ // Load environment variables from the current directory
10
+ dotenv.config();
11
+
12
+ // ANSI color codes for prettier output
13
+ const colors = {
14
+ reset: '\x1b[0m',
15
+ bright: '\x1b[1m',
16
+ dim: '\x1b[2m',
17
+ green: '\x1b[32m',
18
+ yellow: '\x1b[33m',
19
+ blue: '\x1b[34m',
20
+ red: '\x1b[31m',
21
+ cyan: '\x1b[36m'
22
+ };
23
+
24
+ /**
25
+ * Display a colorful banner with the tool name
26
+ */
27
+ function showBanner() {
28
+ console.log(`
29
+ ${colors.bright}${colors.cyan}HypeQuery TypeScript Generator${colors.reset}
30
+ ${colors.dim}Generate TypeScript types from your ClickHouse database schema${colors.reset}
31
+ `);
32
+ }
33
+
34
+ /**
35
+ * Show help information for the CLI
36
+ */
37
+ function showHelp() {
38
+ console.log(`
39
+ ${colors.bright}Usage:${colors.reset}
40
+ npx hypequery-generate-types [output-path] [options]
41
+
42
+ ${colors.bright}Arguments:${colors.reset}
43
+ output-path Path where TypeScript definitions will be saved (default: "./generated-schema.ts")
44
+
45
+ ${colors.bright}Environment variables:${colors.reset}
46
+ CLICKHOUSE_HOST ClickHouse server URL (default: http://localhost:8123)
47
+ CLICKHOUSE_USER ClickHouse username (default: default)
48
+ CLICKHOUSE_PASSWORD ClickHouse password
49
+ CLICKHOUSE_DATABASE ClickHouse database name (default: default)
50
+
51
+ ${colors.bright}Examples:${colors.reset}
52
+ npx hypequery-generate-types
53
+ npx hypequery-generate-types ./src/types/db-schema.ts
54
+ CLICKHOUSE_HOST=http://my-clickhouse:8123 npx hypequery-generate-types
55
+
56
+ ${colors.bright}Options:${colors.reset}
57
+ --help, -h Show this help text
58
+ `);
59
+ }
60
+
61
+ /**
62
+ * Main CLI function
63
+ */
64
+ async function main() {
65
+ showBanner();
66
+
67
+ // Process command line arguments
68
+ const args = process.argv.slice(2);
69
+
70
+ // Check for help flag
71
+ if (args.includes('--help') || args.includes('-h')) {
72
+ showHelp();
73
+ return;
74
+ }
75
+
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
+ try {
82
+ // Display connection info
83
+ const host = process.env.VITE_CLICKHOUSE_HOST || process.env.CLICKHOUSE_HOST || 'http://localhost:8123';
84
+ const database = process.env.VITE_CLICKHOUSE_DATABASE || process.env.CLICKHOUSE_DATABASE || 'default';
85
+
86
+ console.log(`${colors.dim}Connecting to ClickHouse at ${colors.reset}${colors.bright}${host}${colors.reset}`);
87
+ console.log(`${colors.dim}Database: ${colors.reset}${colors.bright}${database}${colors.reset}`);
88
+
89
+ // Initialize connection from env vars
90
+ ClickHouseConnection.initialize({
91
+ host,
92
+ username: process.env.VITE_CLICKHOUSE_USER || process.env.CLICKHOUSE_USER || 'default',
93
+ password: process.env.VITE_CLICKHOUSE_PASSWORD || process.env.CLICKHOUSE_PASSWORD,
94
+ database,
95
+ });
96
+
97
+ console.log(`${colors.dim}Generating TypeScript definitions...${colors.reset}`);
98
+
99
+ // Ensure directory exists
100
+ const dir = path.dirname(path.resolve(outputPath));
101
+ await fs.mkdir(dir, { recursive: true });
102
+
103
+ // Generate types
104
+ await generateTypes(outputPath);
105
+
106
+ console.log(`${colors.green}✓ Success! ${colors.reset}Types generated at ${colors.bright}${path.resolve(outputPath)}${colors.reset}`);
107
+ console.log(`
108
+ ${colors.dim}To use these types in your project:${colors.reset}
109
+
110
+ import { createQueryBuilder } from '@hypequery/clickhouse';
111
+ import { IntrospectedSchema } from '${outputPath.replace(/\.ts$/, '')}';
112
+
113
+ const db = createQueryBuilder<IntrospectedSchema>({
114
+ host: process.env.CLICKHOUSE_HOST,
115
+ username: process.env.CLICKHOUSE_USER,
116
+ password: process.env.CLICKHOUSE_PASSWORD,
117
+ database: process.env.CLICKHOUSE_DATABASE,
118
+ });
119
+ `);
120
+ } catch (error) {
121
+ console.error(`${colors.red}✗ Error generating types: ${colors.reset}${error.message}`);
122
+
123
+ // Provide more helpful error messages for common issues
124
+ if (error.message && error.message.includes('ECONNREFUSED')) {
125
+ console.error(`
126
+ ${colors.yellow}Connection refused.${colors.reset} Please check:
127
+ - Is ClickHouse running at ${process.env.CLICKHOUSE_HOST || 'http://localhost:8123'}?
128
+ - Do you need to provide authentication credentials?
129
+ - Are there any network/firewall restrictions?
130
+ `);
131
+ } else if (error.message && error.message.includes('Authentication failed')) {
132
+ console.error(`
133
+ ${colors.yellow}Authentication failed.${colors.reset} Please check:
134
+ - Are your CLICKHOUSE_USER and CLICKHOUSE_PASSWORD environment variables set correctly?
135
+ - Does the user have sufficient permissions?
136
+ `);
137
+ } else if (error.message && error.message.includes('database does not exist')) {
138
+ console.error(`
139
+ ${colors.yellow}Database not found.${colors.reset} Please check:
140
+ - Is the CLICKHOUSE_DATABASE environment variable set correctly?
141
+ - Does the database exist in your ClickHouse instance?
142
+ `);
143
+ }
144
+
145
+ console.error(`${colors.dim}For more information, use --help flag.${colors.reset}`);
146
+ process.exit(1);
147
+ }
148
+ }
149
+
150
+ // Execute the main function
151
+ main();
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generates TypeScript type definitions from the ClickHouse database schema
3
+ * @param outputPath - The file path where the type definitions will be written
4
+ */
5
+ export declare function generateTypes(outputPath: string): Promise<void>;
@@ -0,0 +1,91 @@
1
+ import { ClickHouseConnection } from '../core/connection.js';
2
+ import fs from 'fs/promises';
3
+ import path from 'path';
4
+ import dotenv from 'dotenv';
5
+
6
+ // Load environment variables from the current directory
7
+ dotenv.config();
8
+
9
+ /**
10
+ * @typedef {Object} ColumnInfo
11
+ * @property {string} name - The name of the column
12
+ * @property {string} type - The ClickHouse type of the column
13
+ */
14
+
15
+ /**
16
+ * Converts ClickHouse types to TypeScript types
17
+ * @param {string} type - The ClickHouse type to convert
18
+ * @returns {string} - The corresponding TypeScript type
19
+ */
20
+ const clickhouseToTsType = (type) => {
21
+ if (type.startsWith('Array(')) {
22
+ const innerType = type.slice(6, -1);
23
+ return `Array(${clickhouseToTsType(innerType)})`;
24
+ }
25
+
26
+ switch (type.toLowerCase()) {
27
+ case 'string':
28
+ case 'fixedstring':
29
+ return 'String';
30
+ case 'int8':
31
+ case 'int16':
32
+ case 'int32':
33
+ return 'Int32';
34
+ case 'int64':
35
+ return 'Int64';
36
+ case 'float32':
37
+ case 'float64':
38
+ return 'Float64';
39
+ case 'datetime':
40
+ return 'DateTime';
41
+ case 'date':
42
+ return 'Date';
43
+ default:
44
+ return 'String';
45
+ }
46
+ };
47
+
48
+ /**
49
+ * Generates TypeScript type definitions from the ClickHouse database schema
50
+ * @param {string} outputPath - The file path where the type definitions will be written
51
+ * @returns {Promise<void>}
52
+ */
53
+ export async function generateTypes(outputPath) {
54
+ const client = ClickHouseConnection.getClient();
55
+
56
+ // Get all tables
57
+ const tablesQuery = await client.query({
58
+ query: 'SHOW TABLES',
59
+ format: 'JSONEachRow'
60
+ });
61
+ const tables = await tablesQuery.json();
62
+
63
+ let typeDefinitions = `// Generated by @hypequery/clickhouse
64
+ import { ColumnType } from '@hypequery/clickhouse';
65
+
66
+ export interface IntrospectedSchema {`;
67
+
68
+ // Get columns for each table
69
+ for (const table of tables) {
70
+ const columnsQuery = await client.query({
71
+ query: `DESCRIBE ${table.name}`,
72
+ format: 'JSONEachRow'
73
+ });
74
+ const columns = await columnsQuery.json();
75
+
76
+ typeDefinitions += `\n ${table.name}: {`;
77
+ for (const column of columns) {
78
+ typeDefinitions += `\n ${column.name}: '${clickhouseToTsType(column.type)}';`;
79
+ }
80
+ typeDefinitions += '\n };';
81
+ }
82
+
83
+ typeDefinitions += '\n}\n';
84
+
85
+ // Ensure the output directory exists
86
+ const outputDir = path.dirname(path.resolve(outputPath));
87
+ await fs.mkdir(outputDir, { recursive: true });
88
+
89
+ // Write the file
90
+ await fs.writeFile(path.resolve(outputPath), typeDefinitions);
91
+ }
@@ -0,0 +1,2 @@
1
+ // CLI module type declarations
2
+ export { generateTypes } from './generate-types';
@@ -0,0 +1,2 @@
1
+ // CLI module exports
2
+ export { generateTypes } from './generate-types.js';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAWjE,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE;QACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE;QACX,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;IAEF,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,mBAAmB,CAAC,EAAE,kBAAkB,CAAC;CAC1C;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IAEzD,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,2BAA2B,GAAG,IAAI;IAqB5D,MAAM,CAAC,SAAS,IAAI,UAAU,CAAC,OAAO,YAAY,CAAC;CAMpD"}
@@ -0,0 +1,34 @@
1
+ import { createClient } from '@clickhouse/client-web';
2
+ export class ClickHouseConnection {
3
+ static initialize(config) {
4
+ // Create a client config object with only the standard options
5
+ const clientConfig = {
6
+ host: config.host,
7
+ username: config.username,
8
+ password: config.password,
9
+ database: config.database,
10
+ };
11
+ // Add the extended options if provided
12
+ if (config.http_headers)
13
+ clientConfig.http_headers = config.http_headers;
14
+ if (config.request_timeout)
15
+ clientConfig.request_timeout = config.request_timeout;
16
+ if (config.compression)
17
+ clientConfig.compression = config.compression;
18
+ if (config.application)
19
+ clientConfig.application = config.application;
20
+ if (config.keep_alive)
21
+ clientConfig.keep_alive = config.keep_alive;
22
+ if (config.log)
23
+ clientConfig.log = config.log;
24
+ if (config.clickhouse_settings)
25
+ clientConfig.clickhouse_settings = config.clickhouse_settings;
26
+ this.instance = createClient(clientConfig);
27
+ }
28
+ static getClient() {
29
+ if (!this.instance) {
30
+ throw new Error('ClickHouse connection not initialized');
31
+ }
32
+ return this.instance;
33
+ }
34
+ }