@hypequery/clickhouse 1.6.2 → 2.0.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.
Files changed (141) hide show
  1. package/README-CLI.md +43 -88
  2. package/README.md +84 -253
  3. package/dist/cli/bin.js +16 -8
  4. package/dist/core/adapters/clickhouse-adapter.d.ts.map +1 -1
  5. package/dist/core/adapters/clickhouse-adapter.js +3 -2
  6. package/dist/core/cache/cache-manager.d.ts.map +1 -1
  7. package/dist/core/cache/cache-manager.js +5 -3
  8. package/dist/core/connection.d.ts +6 -6
  9. package/dist/core/connection.js +9 -9
  10. package/dist/core/cross-filter.js +1 -1
  11. package/dist/core/dialects/clickhouse-dialect.d.ts +2 -2
  12. package/dist/core/dialects/clickhouse-dialect.d.ts.map +1 -1
  13. package/dist/core/dialects/clickhouse-dialect.js +39 -22
  14. package/dist/core/dialects/sql-dialect.d.ts +2 -2
  15. package/dist/core/dialects/sql-dialect.d.ts.map +1 -1
  16. package/dist/core/env/auto-client.d.ts.map +1 -1
  17. package/dist/core/env/auto-client.js +1 -1
  18. package/dist/core/features/aggregations.d.ts +7 -90
  19. package/dist/core/features/aggregations.d.ts.map +1 -1
  20. package/dist/core/features/aggregations.js +19 -7
  21. package/dist/core/features/analytics.d.ts +5 -870
  22. package/dist/core/features/analytics.d.ts.map +1 -1
  23. package/dist/core/features/analytics.js +15 -13
  24. package/dist/core/features/cross-filtering.d.ts +1 -1
  25. package/dist/core/features/cross-filtering.d.ts.map +1 -1
  26. package/dist/core/features/cross-filtering.js +28 -73
  27. package/dist/core/features/executor.d.ts +1 -1
  28. package/dist/core/features/executor.d.ts.map +1 -1
  29. package/dist/core/features/executor.js +9 -11
  30. package/dist/core/features/filtering.d.ts +5 -91
  31. package/dist/core/features/filtering.d.ts.map +1 -1
  32. package/dist/core/features/filtering.js +63 -77
  33. package/dist/core/features/joins.d.ts +2 -19
  34. package/dist/core/features/joins.d.ts.map +1 -1
  35. package/dist/core/features/joins.js +16 -5
  36. package/dist/core/features/query-modifiers.d.ts +10 -109
  37. package/dist/core/features/query-modifiers.d.ts.map +1 -1
  38. package/dist/core/features/query-modifiers.js +64 -18
  39. package/dist/core/formatters/sql-formatter.d.ts +16 -5
  40. package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
  41. package/dist/core/formatters/sql-formatter.js +197 -93
  42. package/dist/core/join-relationships.d.ts +22 -5
  43. package/dist/core/join-relationships.d.ts.map +1 -1
  44. package/dist/core/join-relationships.js +1 -1
  45. package/dist/core/query-builder.d.ts +63 -12
  46. package/dist/core/query-builder.d.ts.map +1 -1
  47. package/dist/core/query-builder.js +210 -153
  48. package/dist/core/query-node.d.ts +7 -0
  49. package/dist/core/query-node.d.ts.map +1 -0
  50. package/dist/core/query-node.js +80 -0
  51. package/dist/core/tests/integration/setup.d.ts +1 -0
  52. package/dist/core/tests/integration/setup.d.ts.map +1 -1
  53. package/dist/core/tests/integration/setup.js +4 -2
  54. package/dist/core/types/select-types.d.ts +3 -0
  55. package/dist/core/types/select-types.d.ts.map +1 -1
  56. package/dist/core/utils/connection-endpoint.d.ts +3 -0
  57. package/dist/core/utils/connection-endpoint.d.ts.map +1 -0
  58. package/dist/core/utils/connection-endpoint.js +9 -0
  59. package/dist/core/utils/filter-application.d.ts +15 -0
  60. package/dist/core/utils/filter-application.d.ts.map +1 -0
  61. package/dist/core/utils/filter-application.js +32 -0
  62. package/dist/core/utils/query-config-compat.d.ts +48 -0
  63. package/dist/core/utils/query-config-compat.d.ts.map +1 -0
  64. package/dist/core/utils/query-config-compat.js +137 -0
  65. package/dist/core/utils/relation-application.d.ts +9 -0
  66. package/dist/core/utils/relation-application.d.ts.map +1 -0
  67. package/dist/core/utils/relation-application.js +19 -0
  68. package/dist/core/utils/relation-validation.d.ts +6 -0
  69. package/dist/core/utils/relation-validation.d.ts.map +1 -0
  70. package/dist/core/utils/relation-validation.js +29 -0
  71. package/dist/core/utils/sql-expressions.d.ts +14 -0
  72. package/dist/core/utils/sql-expressions.d.ts.map +1 -1
  73. package/dist/core/utils/sql-expressions.js +40 -0
  74. package/dist/core/utils/tuple-filter-validation.d.ts +3 -0
  75. package/dist/core/utils/tuple-filter-validation.d.ts.map +1 -0
  76. package/dist/core/utils/tuple-filter-validation.js +16 -0
  77. package/dist/index.d.ts +2 -13
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +3 -8
  80. package/dist/types/base.d.ts +88 -22
  81. package/dist/types/base.d.ts.map +1 -1
  82. package/dist/types/filters.d.ts +9 -5
  83. package/dist/types/filters.d.ts.map +1 -1
  84. package/package.json +5 -5
  85. package/dist/migrations/config/index.d.ts +0 -3
  86. package/dist/migrations/config/index.d.ts.map +0 -1
  87. package/dist/migrations/config/index.js +0 -1
  88. package/dist/migrations/config/types.d.ts +0 -45
  89. package/dist/migrations/config/types.d.ts.map +0 -1
  90. package/dist/migrations/config/types.js +0 -28
  91. package/dist/migrations/diff/diff.d.ts +0 -11
  92. package/dist/migrations/diff/diff.d.ts.map +0 -1
  93. package/dist/migrations/diff/diff.js +0 -240
  94. package/dist/migrations/diff/index.d.ts +0 -3
  95. package/dist/migrations/diff/index.d.ts.map +0 -1
  96. package/dist/migrations/diff/index.js +0 -1
  97. package/dist/migrations/diff/types.d.ts +0 -74
  98. package/dist/migrations/diff/types.d.ts.map +0 -1
  99. package/dist/migrations/diff/types.js +0 -1
  100. package/dist/migrations/plan/index.d.ts +0 -3
  101. package/dist/migrations/plan/index.d.ts.map +0 -1
  102. package/dist/migrations/plan/index.js +0 -1
  103. package/dist/migrations/plan/plan.d.ts +0 -12
  104. package/dist/migrations/plan/plan.d.ts.map +0 -1
  105. package/dist/migrations/plan/plan.js +0 -416
  106. package/dist/migrations/plan/types.d.ts +0 -93
  107. package/dist/migrations/plan/types.d.ts.map +0 -1
  108. package/dist/migrations/plan/types.js +0 -1
  109. package/dist/migrations/schema/column.d.ts +0 -71
  110. package/dist/migrations/schema/column.d.ts.map +0 -1
  111. package/dist/migrations/schema/column.js +0 -123
  112. package/dist/migrations/schema/define.d.ts +0 -24
  113. package/dist/migrations/schema/define.d.ts.map +0 -1
  114. package/dist/migrations/schema/define.js +0 -47
  115. package/dist/migrations/schema/index.d.ts +0 -4
  116. package/dist/migrations/schema/index.d.ts.map +0 -1
  117. package/dist/migrations/schema/index.js +0 -2
  118. package/dist/migrations/schema/types.d.ts +0 -74
  119. package/dist/migrations/schema/types.d.ts.map +0 -1
  120. package/dist/migrations/schema/types.js +0 -1
  121. package/dist/migrations/snapshot/index.d.ts +0 -3
  122. package/dist/migrations/snapshot/index.d.ts.map +0 -1
  123. package/dist/migrations/snapshot/index.js +0 -1
  124. package/dist/migrations/snapshot/serialize.d.ts +0 -21
  125. package/dist/migrations/snapshot/serialize.d.ts.map +0 -1
  126. package/dist/migrations/snapshot/serialize.js +0 -127
  127. package/dist/migrations/snapshot/types.d.ts +0 -47
  128. package/dist/migrations/snapshot/types.d.ts.map +0 -1
  129. package/dist/migrations/snapshot/types.js +0 -1
  130. package/dist/migrations/sql/index.d.ts +0 -4
  131. package/dist/migrations/sql/index.d.ts.map +0 -1
  132. package/dist/migrations/sql/index.js +0 -2
  133. package/dist/migrations/sql/render.d.ts +0 -10
  134. package/dist/migrations/sql/render.d.ts.map +0 -1
  135. package/dist/migrations/sql/render.js +0 -347
  136. package/dist/migrations/sql/types.d.ts +0 -53
  137. package/dist/migrations/sql/types.d.ts.map +0 -1
  138. package/dist/migrations/sql/types.js +0 -1
  139. package/dist/migrations/sql/write.d.ts +0 -10
  140. package/dist/migrations/sql/write.d.ts.map +0 -1
  141. package/dist/migrations/sql/write.js +0 -35
package/README-CLI.md CHANGED
@@ -1,123 +1,78 @@
1
- # hypequery TypeScript Generator
1
+ # hypequery Type Generator
2
2
 
3
- This tool automatically generates TypeScript type definitions from your ClickHouse database schema.
3
+ `hypequery-generate-types` introspects your ClickHouse schema and writes a TypeScript interface you can use with `createQueryBuilder()`.
4
4
 
5
- ## Installation
5
+ Most users should prefer:
6
6
 
7
- The TypeScript generator is included with the `@hypequery/clickhouse` package:
7
+ ```bash
8
+ npx hypequery generate
9
+ ```
10
+
11
+ This file documents the lower-level binary that ships with `@hypequery/clickhouse`.
12
+
13
+ ## Install
8
14
 
9
15
  ```bash
10
16
  npm install @hypequery/clickhouse
11
17
  ```
12
18
 
13
- ## Quick Start
14
-
15
- Generate TypeScript types for your ClickHouse database:
19
+ ## Usage
16
20
 
17
21
  ```bash
18
22
  npx hypequery-generate-types
19
23
  ```
20
24
 
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
+ By default it:
25
26
 
26
- ## Example Usage
27
+ - reads ClickHouse connection details from environment variables
28
+ - introspects tables in the target database
29
+ - writes `generated-schema.ts` in the current working directory
27
30
 
28
- **Generate types with a custom output path:**
31
+ Custom output path:
29
32
 
30
33
  ```bash
31
34
  npx hypequery-generate-types ./src/types/db-schema.ts
32
35
  ```
33
36
 
34
- **Specify database connection directly:**
37
+ ## Environment Variables
38
+
39
+ | Variable | Description |
40
+ | --- | --- |
41
+ | `CLICKHOUSE_URL` | Preferred ClickHouse URL |
42
+ | `CLICKHOUSE_HOST` | Deprecated alias for `CLICKHOUSE_URL` |
43
+ | `CLICKHOUSE_USER` | ClickHouse username |
44
+ | `CLICKHOUSE_PASSWORD` | ClickHouse password |
45
+ | `CLICKHOUSE_DATABASE` | ClickHouse database |
46
+
47
+ Example:
35
48
 
36
49
  ```bash
37
- CLICKHOUSE_HOST=http://clickhouse.example.com:8123 \
38
- CLICKHOUSE_USER=myuser \
39
- CLICKHOUSE_PASSWORD=mypassword \
50
+ CLICKHOUSE_URL=http://localhost:8123 \
51
+ CLICKHOUSE_USER=default \
52
+ CLICKHOUSE_PASSWORD=secret \
40
53
  CLICKHOUSE_DATABASE=analytics \
41
- npx hypequery-generate-types
54
+ npx hypequery-generate-types ./analytics/schema.ts
42
55
  ```
43
56
 
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
57
+ ## Using The Generated Types
61
58
 
62
- Import the generated types in your code:
63
-
64
- ```typescript
59
+ ```ts
65
60
  import { createQueryBuilder } from '@hypequery/clickhouse';
66
- import { IntrospectedSchema } from './generated-schema';
61
+ import type { IntrospectedSchema } from './analytics/schema.js';
67
62
 
68
- // Create a type-safe query builder
69
63
  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
64
+ url: process.env.CLICKHOUSE_URL!,
65
+ username: process.env.CLICKHOUSE_USER!,
66
+ password: process.env.CLICKHOUSE_PASSWORD ?? '',
67
+ database: process.env.CLICKHOUSE_DATABASE!,
86
68
  });
87
69
  ```
88
70
 
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:
71
+ ## Docs
106
72
 
107
- 1. **Connection problems**
108
- - Make sure ClickHouse is running and accessible
109
- - Check your firewall settings
73
+ - [Quick start](https://hypequery.com/docs/quick-start)
74
+ - [CLI reference](https://hypequery.com/docs/reference/api/cli)
110
75
 
111
- 2. **Authentication failures**
112
- - Verify your username and password
113
- - Ensure the user has sufficient permissions
76
+ ## License
114
77
 
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
- ```
78
+ Apache-2.0.
package/README.md CHANGED
@@ -1,321 +1,152 @@
1
- <div align="center">
2
- <h1>@hypequery/clickhouse</h1>
3
- <p>A TypeScript-first query builder for ClickHouse and the foundation of the hypequery path.</p>
4
-
5
- [![GitHub license](https://img.shields.io/github/license/hypequery/hypequery)](https://github.com/hypequery/hypequery/blob/main/LICENSE)
6
- [![npm version](https://badge.fury.io/js/@hypequery%2Fclickhouse.svg)](https://badge.fury.io/js/@hypequery%2Fclickhouse)
7
- [![GitHub stars](https://img.shields.io/github/stars/hypequery/hypequery)](https://github.com/hypequery/hypequery/stargazers)
8
- </div>
1
+ # @hypequery/clickhouse
9
2
 
3
+ Typed ClickHouse query builder for hypequery.
10
4
 
11
- ## Overview
5
+ Use it when you want schema-aware queries, typed results, and a fluent API that stays close to how ClickHouse actually works.
12
6
 
13
- `@hypequery/clickhouse` is the first step in the main hypequery flow. Generate types from your ClickHouse schema, build typed queries locally, then promote important queries into `query({ ... })` and `serve({ queries })` when they need to be reused across your app.
7
+ ## Install
14
8
 
15
- ## Features
9
+ Node:
16
10
 
17
- - 🎯 **Type-Safe**: Full TypeScript support with types from your ClickHouse schema
18
- - 🚀 **Performant**: Built for real-time analytics with optimized query generation
19
- - 🔍 **Cross Filtering**: Powerful cross-filtering capabilities for interactive dashboards
20
- - 🛠️ **Developer Friendly**: Fluent API design for an intuitive development experience
21
- - 📱 **Platform Agnostic**: Works in both Node.js and browser environments
22
- - 🔄 **Schema Generation**: CLI tool to generate TypeScript types from your ClickHouse schema
23
-
24
- ## Installation
25
-
26
- This library requires one of the following ClickHouse clients as a peer dependency:
27
-
28
- ### For Node.js environments
29
11
  ```bash
30
12
  npm install @hypequery/clickhouse
31
13
  ```
32
14
 
33
- ### For browser/universal environments
15
+ Browser or shared client setup:
16
+
34
17
  ```bash
35
18
  npm install @hypequery/clickhouse @clickhouse/client-web
36
19
  ```
37
20
 
38
- **Note**: The library supports multiple client selection strategies:
39
- - **Manual injection**: Explicitly provide a client instance (required for browser environments)
40
- - **Auto-detection**: Automatically selects the client for Node.js environments
21
+ `url` is the preferred connection field. `host` is still supported as a deprecated alias.
41
22
 
42
23
  ## Quick Start
43
24
 
44
- Main path:
45
-
46
- 1. Generate schema types
47
- 2. Create a typed `db` with `createQueryBuilder(...)`
48
- 3. Build and execute queries locally
49
- 4. Add `@hypequery/serve` later if a query needs a reusable contract or HTTP surface
50
-
51
- ### Node.js Environments
52
-
53
- ```typescript
25
+ ```ts
54
26
  import { createQueryBuilder } from '@hypequery/clickhouse';
55
- import type { IntrospectedSchema } from './generated-schema';
27
+ import type { IntrospectedSchema } from './analytics/schema.js';
56
28
 
57
- // Initialize the query builder
58
29
  const db = createQueryBuilder<IntrospectedSchema>({
59
- host: 'your-clickhouse-host',
60
- username: 'default',
61
- password: 'your-password',
62
- database: 'default'
30
+ url: process.env.CLICKHOUSE_URL!,
31
+ username: process.env.CLICKHOUSE_USERNAME!,
32
+ password: process.env.CLICKHOUSE_PASSWORD ?? '',
33
+ database: process.env.CLICKHOUSE_DATABASE!,
63
34
  });
64
35
 
65
- // Build and execute a query
66
- const results = await db
67
- .table('trips')
68
- .select(['pickup_datetime', 'dropoff_datetime', 'total_amount'])
69
- .where('total_amount', '>', 50)
70
- .orderBy('pickup_datetime', 'DESC')
71
- .limit(10)
36
+ const recentOrders = await db
37
+ .table('orders')
38
+ .select(['id', 'user_id', 'total', 'created_at'])
39
+ .where('created_at', 'gte', '2026-01-01')
40
+ .orderBy('created_at', 'DESC')
41
+ .limit(20)
72
42
  .execute();
73
43
  ```
74
44
 
75
- ### Browser Environments
45
+ ## Main Path
76
46
 
77
- ```typescript
78
- import { createQueryBuilder } from '@hypequery/clickhouse';
79
- import { createClient } from '@clickhouse/client-web';
80
- import type { IntrospectedSchema } from './generated-schema';
47
+ 1. Generate schema types with the CLI
48
+ 2. Create a typed `db`
49
+ 3. Write and execute queries locally
50
+ 4. Promote important queries into `@hypequery/serve` when they need a shared contract or HTTP surface
81
51
 
82
- // Create the ClickHouse client explicitly
83
- const client = createClient({
84
- host: 'your-clickhouse-host',
85
- username: 'default',
86
- password: '',
87
- database: 'default'
88
- });
52
+ ## Common Patterns
89
53
 
90
- // Initialize the query builder with the client
91
- const db = createQueryBuilder<IntrospectedSchema>({
92
- client // Explicitly provide the client
93
- });
54
+ ### Aggregation
94
55
 
95
- // Build and execute a query
96
- const results = await db
97
- .table('trips')
98
- .select(['pickup_datetime', 'dropoff_datetime', 'total_amount'])
99
- .where('total_amount', '>', 50)
100
- .orderBy('pickup_datetime', 'DESC')
101
- .limit(10)
56
+ ```ts
57
+ const revenueByRegion = await db
58
+ .table('orders')
59
+ .select(['region'])
60
+ .sum('total', 'revenue')
61
+ .groupBy('region')
62
+ .orderBy('revenue', 'DESC')
102
63
  .execute();
103
64
  ```
104
65
 
105
- ## Caching (Experimental)
106
-
107
- The query builder can cache results with deterministic keys, stale-while-revalidate behavior, and pluggable providers.
108
-
109
- ```typescript
110
- import { createQueryBuilder, MemoryCacheProvider } from '@hypequery/clickhouse';
111
-
112
- const db = createQueryBuilder<IntrospectedSchema>({
113
- host: 'your-clickhouse-host',
114
- username: 'default',
115
- password: '',
116
- database: 'default',
117
- cache: {
118
- mode: 'stale-while-revalidate',
119
- ttlMs: 2_000,
120
- staleTtlMs: 30_000,
121
- provider: new MemoryCacheProvider({ maxEntries: 5_000 })
122
- }
123
- });
66
+ ### Joins
124
67
 
125
- const rows = await db
126
- .table('users')
127
- .select(['id', 'email'])
128
- .where('active', '=', true)
129
- .cache({ tags: ['users'] })
68
+ ```ts
69
+ const ordersWithUsers = await db
70
+ .table('orders')
71
+ .innerJoin('users', 'user_id', 'users.id')
72
+ .select(['orders.id', 'users.email', 'orders.total'])
73
+ .where('users.status', 'eq', 'active')
130
74
  .execute();
131
-
132
- // Programmatic invalidation
133
- await db.cache.invalidateTags(['users']);
134
- ```
135
-
136
- Use `.cache()` to attach defaults to a fluent chain, pass `execute({ cache: { ... } })` for one-off overrides, or call `db.cache.*` for manual invalidation. For a deep dive on cache modes, invalidation, advanced serialization, and bring-your-own-provider recipes (Redis/Upstash, compression, etc.), see the [Caching guide](https://hypequery.com/docs/caching).
137
-
138
- ## Schema Generation
139
-
140
- Use the hypequery CLI to generate TypeScript types from your ClickHouse schema:
141
-
142
- ```bash
143
- npm install -D @hypequery/cli
144
- npx hypequery generate
145
- ```
146
-
147
- This creates a `generated-schema.ts` file that you can import in your application:
148
-
149
- ```typescript
150
- import { createQueryBuilder } from '@hypequery/clickhouse';
151
- import type { IntrospectedSchema } from './generated-schema';
152
-
153
- const db = createQueryBuilder<IntrospectedSchema>({
154
- // connection details
155
- });
156
75
  ```
157
76
 
158
- ## Core Features
159
-
160
- ### Type-Safe Queries
161
-
162
- hypequery provides full TypeScript support, ensuring your queries are type-safe:
77
+ ### ClickHouse-specific features
163
78
 
164
- ```typescript
165
- // Column names are type-checked
166
- const query = db.table('trips')
167
- .select(['pickup_datetime', 'total_amount'])
168
- .where('total_amount', 'gt', 50)
79
+ ```ts
80
+ const topProductsPerCategory = await db
81
+ .table('products')
82
+ .select(['category', 'id', 'score'])
83
+ .orderBy('score', 'DESC')
84
+ .limitBy(3, 'category')
169
85
  .execute();
170
-
171
- // Type error if column doesn't exist
172
- db.table('trips').select(['non_existent_column']); // TypeScript error
173
86
  ```
174
87
 
175
- ### Cross Filtering
176
-
177
- Implement interactive dashboards with cross-filtering support:
178
-
179
- ```typescript
180
- import { CrossFilter } from '@hypequery/clickhouse';
181
-
182
- // Create a filter
183
- const filter = new CrossFilter()
184
- .add({
185
- column: 'pickup_datetime',
186
- operator: 'gte',
187
- value: '2024-01-01'
188
- })
189
- .add({
190
- column: 'total_amount',
191
- operator: 'gt',
192
- value: 20
193
- });
194
-
195
- // Apply to multiple queries
196
- const query1 = db.table('trips')
197
- .applyCrossFilters(filter)
198
- .execute();
199
-
200
- const query2 = db.table('drivers')
201
- .applyCrossFilters(filter)
88
+ ```ts
89
+ const explodedTags = await db
90
+ .table('products')
91
+ .select(['id', 'tags'])
92
+ .arrayJoin('tags')
202
93
  .execute();
203
94
  ```
204
95
 
205
- ### Advanced Queries
206
-
207
- hypequery supports complex queries including joins, aggregations, and subqueries:
96
+ `arrayJoin()` and `leftArrayJoin()` only accept array-typed columns.
208
97
 
209
- ```typescript
210
- // Aggregations
211
- const stats = await db.table('trips')
212
- .avg('total_amount')
213
- .max('trip_distance')
214
- .count('trip_id')
215
- .where('pickup_datetime', 'gte', '2024-01-01')
216
- .execute();
98
+ ## Browser Use
217
99
 
218
- // Joins
219
- const tripsWithDrivers = await db.table('trips')
220
- .select(['trips.trip_id', 'trips.total_amount', 'drivers.name'])
221
- .join('drivers', 'trips.driver_id', 'drivers.id')
222
- .execute();
100
+ In browser environments, create the ClickHouse client explicitly and inject it:
223
101
 
224
- // After joining, TypeScript understands the expanded scope
225
- const tripsWithUsers = await db.table('trips')
226
- .innerJoin('users', 'trips.user_id', 'users.id')
227
- .select(['users.email', 'trips.trip_id'])
228
- .where('users.email', 'like', '%@example.com')
229
- .execute();
230
-
231
- // Keep literal column inference with selectConst and reuse joined columns in ORDER BY / HAVING
232
- const sortedTrips = await db.table('trips')
233
- .innerJoin('users', 'trips.user_id', 'users.id')
234
- .selectConst('users.email', 'trips.trip_id')
235
- .groupBy(['users.email', 'trips.trip_id'])
236
- .having('COUNT(*) > 1')
237
- .orderBy('users.email', 'DESC')
238
- .execute();
239
-
240
- ```
241
-
242
- `selectConst()` preserves literal column names (including aliases like `users.email`), which means TypeScript keeps those identifiers available for downstream `orderBy`, `groupBy`, and `having` calls.
243
-
244
- **Benefits:**
245
- - ✅ Works in all environments (Node.js, browser, bundlers)
246
- - ✅ Explicit control over client configuration
247
- - ✅ Required for browser environments (require() doesn't work in browsers)
248
- - ✅ Synchronous API throughout
102
+ ```ts
103
+ import { createClient } from '@clickhouse/client-web';
104
+ import { createQueryBuilder } from '@hypequery/clickhouse';
105
+ import type { IntrospectedSchema } from './analytics/schema.js';
249
106
 
250
- #### 2. Auto-Detection with Fallback (Node.js Environments Only)
107
+ const client = createClient({
108
+ url: process.env.NEXT_PUBLIC_CLICKHOUSE_URL!,
109
+ username: process.env.NEXT_PUBLIC_CLICKHOUSE_USERNAME!,
110
+ password: process.env.NEXT_PUBLIC_CLICKHOUSE_PASSWORD ?? '',
111
+ database: process.env.NEXT_PUBLIC_CLICKHOUSE_DATABASE!,
112
+ });
251
113
 
252
- ```typescript
253
114
  const db = createQueryBuilder<IntrospectedSchema>({
254
- host: 'your-clickhouse-host',
255
- username: 'default',
256
- password: '',
257
- database: 'default'
115
+ client,
258
116
  });
259
117
  ```
260
118
 
119
+ ## Schema Generation
261
120
 
262
- ## Testing
263
-
264
- Run the fast feedback loop with:
121
+ The usual path is through the CLI:
265
122
 
266
123
  ```bash
267
- npm run test
124
+ npm install -D @hypequery/cli
125
+ npx hypequery generate
268
126
  ```
269
127
 
270
- This command runs type checks + unit tests only. To exercise the ClickHouse-backed integration suite, copy `.env.test.example` to `.env.test`, point it at a ClickHouse instance, and run:
128
+ The package also ships the lower-level generator binary:
271
129
 
272
130
  ```bash
273
- npm run test:integration
131
+ npx hypequery-generate-types
274
132
  ```
275
133
 
276
- ## Versioning and Release Channels
134
+ More details: [README-CLI.md](./README-CLI.md)
277
135
 
278
- hypequery follows semantic versioning and provides multiple release channels:
136
+ ## Useful Exports
279
137
 
280
- - **Latest**: Stable releases (`npm install @hypequery/clickhouse`)
281
- - **Beta**: Pre-release versions (`npm install @hypequery/clickhouse@beta`)
138
+ - SQL helpers like `raw`, `rawAs`, `selectExpr`, and `toDateTime`
139
+ - exported time helpers like `toStartOfMinute`, `toStartOfHour`, `toStartOfDay`, `toStartOfWeek`, `toStartOfMonth`, `toStartOfQuarter`, and `toStartOfYear`
140
+ - cache primitives like `MemoryCacheProvider`
282
141
 
283
- ## Documentation
142
+ ## Docs
284
143
 
285
- For detailed documentation and examples, visit the main docs flow.
286
-
287
- - [Quick Start](https://hypequery.com/docs/quick-start)
288
- - [Core Concepts](https://hypequery.com/docs/core-concepts)
289
- - [Query Building](https://hypequery.com/docs/query-building/basics)
144
+ - [Query builder basics](https://hypequery.com/docs/query-building/basics)
290
145
  - [Filtering](https://hypequery.com/docs/query-building/where)
291
- - [API Reference](https://hypequery.com/docs/reference/query-builder)
292
-
293
-
294
- ## Troubleshooting
295
-
296
- ### Common Issues
297
-
298
- - **Connection Errors**: Ensure your ClickHouse server is running and accessible
299
- - **CORS Issues**: Use a proxy server for browser environments
300
- - **Type Errors**: Make sure to regenerate your schema types after schema changes
301
- - **Client Not Found**: Make sure you have installed at least one of the required peer dependencies:
302
- - `@clickhouse/client` (for Node.js environments)
303
- - `@clickhouse/client-web` (for browser/universal environments)
304
- - **Browser Auto-Detection**: Auto-detection doesn't work in browsers because `require()` calls don't work. Use manual injection instead.
305
-
146
+ - [Joins](https://hypequery.com/docs/query-building/joins)
147
+ - [Aggregation](https://hypequery.com/docs/query-building/aggregation)
148
+ - [Connection reference](https://hypequery.com/docs/reference/connection)
306
149
 
307
150
  ## License
308
151
 
309
- This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENSE) file for details.
310
-
311
- ## Support
312
-
313
- - 📚 [Documentation](https://hypequery.com/docs)
314
- - 🐛 [Issue Tracker](https://github.com/hypequery/hypequery/issues)
315
- - 💬 [Discussions](https://github.com/hypequery/hypequery/discussions)
316
-
317
- ---
318
-
319
- <div align="center">
320
- <sub>Built with ❤️ by the hypequery team</sub>
321
- </div>
152
+ Apache-2.0.
package/dist/cli/bin.js CHANGED
@@ -41,7 +41,8 @@ ${colors.bright}Usage:${colors.reset}
41
41
 
42
42
  ${colors.bright}Options:${colors.reset}
43
43
  --output=<path> Path where TypeScript definitions will be saved (default: "./generated-schema.ts")
44
- --host=<url> ClickHouse server URL (default: http://localhost:8123)
44
+ --url=<url> ClickHouse server URL (default: http://localhost:8123)
45
+ --host=<url> Deprecated alias for --url
45
46
  --username=<user> ClickHouse username (default: default)
46
47
  --password=<password> ClickHouse password
47
48
  --database=<db> ClickHouse database name (default: default)
@@ -53,9 +54,12 @@ ${colors.bright}Options:${colors.reset}
53
54
  ${colors.dim}Note: All options support both formats: --option=value or --option value${colors.reset}
54
55
 
55
56
  ${colors.bright}Environment variables:${colors.reset}
56
- CLICKHOUSE_HOST ClickHouse server URL
57
- VITE_CLICKHOUSE_HOST Alternative variable for Vite projects
58
- NEXT_PUBLIC_CLICKHOUSE_HOST Alternative variable for Next.js projects
57
+ CLICKHOUSE_URL ClickHouse server URL
58
+ VITE_CLICKHOUSE_URL Alternative variable for Vite projects
59
+ NEXT_PUBLIC_CLICKHOUSE_URL Alternative variable for Next.js projects
60
+ CLICKHOUSE_HOST Deprecated alternative
61
+ VITE_CLICKHOUSE_HOST Deprecated alternative for Vite projects
62
+ NEXT_PUBLIC_CLICKHOUSE_HOST Deprecated alternative for Next.js projects
59
63
 
60
64
  CLICKHOUSE_USER ClickHouse username
61
65
  VITE_CLICKHOUSE_USER Alternative variable for Vite projects
@@ -73,8 +77,8 @@ ${colors.bright}Examples:${colors.reset}
73
77
  npx hypequery-generate-types
74
78
  npx hypequery-generate-types --output=./src/types/db-schema.ts
75
79
  npx hypequery-generate-types --output ./src/types/db-schema.ts
76
- npx hypequery-generate-types --host=https://your-instance.clickhouse.cloud:8443 --secure
77
- npx hypequery-generate-types --host http://localhost:8123 --username default --password password --database my_db
80
+ npx hypequery-generate-types --url=https://your-instance.clickhouse.cloud:8443 --secure
81
+ npx hypequery-generate-types --url http://localhost:8123 --username default --password password --database my_db
78
82
  npx hypequery-generate-types --include-tables=users,orders,products
79
83
  npx hypequery-generate-types --include-tables users,orders,products
80
84
  `);
@@ -107,6 +111,7 @@ function parseArguments(args) {
107
111
  // Parameter handlers map
108
112
  const paramHandlers = {
109
113
  '--output': (value) => config.output = value,
114
+ '--url': (value) => config.host = value,
110
115
  '--host': (value) => config.host = value,
111
116
  '--username': (value) => config.username = value,
112
117
  '--password': (value) => config.password = value,
@@ -176,6 +181,9 @@ async function main() {
176
181
  try {
177
182
  // Get connection parameters from args and environment variables
178
183
  const host = config.host ||
184
+ process.env.CLICKHOUSE_URL ||
185
+ process.env.VITE_CLICKHOUSE_URL ||
186
+ process.env.NEXT_PUBLIC_CLICKHOUSE_URL ||
179
187
  process.env.CLICKHOUSE_HOST ||
180
188
  process.env.VITE_CLICKHOUSE_HOST ||
181
189
  process.env.NEXT_PUBLIC_CLICKHOUSE_HOST ||
@@ -237,7 +245,7 @@ import { createQueryBuilder } from '@hypequery/clickhouse';
237
245
  import { IntrospectedSchema } from '${config.output.replace(/\.ts$/, '')}';
238
246
 
239
247
  const db = createQueryBuilder<IntrospectedSchema>({
240
- host: '${host}',
248
+ url: '${host}',
241
249
  username: '${username}',
242
250
  password: '********',
243
251
  database: '${database}'
@@ -282,4 +290,4 @@ ${colors.yellow}SSL/TLS certificate issue.${colors.reset} For secure connections
282
290
  }
283
291
 
284
292
  // Execute the main function
285
- main();
293
+ main();
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse-adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/clickhouse-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AA2B5D,qBAAa,iBAAkB,YAAW,eAAe;IAK3C,OAAO,CAAC,MAAM;IAJ1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,MAAM,CAAmB;gBAEb,MAAM,EAAE,gBAAgB;IAKtC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAW5F,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAYnH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,MAAM;CAGpD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,CAEjF"}
1
+ {"version":3,"file":"clickhouse-adapter.d.ts","sourceRoot":"","sources":["../../../src/core/adapters/clickhouse-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AA4B5D,qBAAa,iBAAkB,YAAW,eAAe;IAK3C,OAAO,CAAC,MAAM;IAJ1B,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,MAAM,CAAmB;gBAEb,MAAM,EAAE,gBAAgB;IAKtC,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAW5F,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAYnH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,OAAO,EAAO,GAAG,MAAM;CAGpD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,CAEjF"}
@@ -1,5 +1,6 @@
1
1
  import { isClientConfig } from '../query-builder.js';
2
2
  import { substituteParameters } from '../utils.js';
3
+ import { getConnectionEndpoint } from '../utils/connection-endpoint.js';
3
4
  import { createJsonEachRowStream } from '../utils/streaming-helpers.js';
4
5
  import { getAutoClientModule } from '../env/auto-client.js';
5
6
  function createClickHouseClient(config) {
@@ -13,10 +14,10 @@ function deriveNamespace(config) {
13
14
  if ('client' in config && config.client) {
14
15
  return 'client';
15
16
  }
16
- const host = 'host' in config ? config.host : 'unknown-host';
17
+ const endpoint = getConnectionEndpoint(config);
17
18
  const database = 'database' in config ? config.database : 'default';
18
19
  const username = 'username' in config ? config.username : 'default';
19
- return `${host || 'unknown-host'}|${database || 'default'}|${username || 'default'}`;
20
+ return `${endpoint || 'unknown-host'}|${database || 'default'}|${username || 'default'}`;
20
21
  }
21
22
  export class ClickHouseAdapter {
22
23
  config;