@hypequery/clickhouse 2.0.2 → 2.1.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 (86) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/generate-types.d.ts +35 -1
  3. package/dist/cli/generate-types.js +32 -11
  4. package/dist/cli/index.d.ts +7 -1
  5. package/dist/cli/index.js +1 -1
  6. package/dist/cli/type-parsing.js +22 -4
  7. package/dist/core/dialects/clickhouse-dialect.d.ts.map +1 -1
  8. package/dist/core/dialects/clickhouse-dialect.js +2 -1
  9. package/dist/core/tests/integration/setup.d.ts.map +1 -1
  10. package/dist/core/tests/integration/setup.js +1 -3
  11. package/dist/core/utils/sql-expressions.d.ts.map +1 -1
  12. package/dist/core/utils/sql-expressions.js +6 -4
  13. package/dist/core/utils/sql-literals.d.ts +3 -0
  14. package/dist/core/utils/sql-literals.d.ts.map +1 -0
  15. package/dist/core/utils/sql-literals.js +39 -0
  16. package/dist/datasets.d.ts +20 -8
  17. package/dist/datasets.d.ts.map +1 -1
  18. package/dist/datasets.js +25 -11
  19. package/package.json +13 -3
  20. package/dist/core/tests/integration/test-data.json +0 -190
  21. package/dist/migrations/config/index.d.ts +0 -3
  22. package/dist/migrations/config/index.d.ts.map +0 -1
  23. package/dist/migrations/config/index.js +0 -1
  24. package/dist/migrations/config/types.d.ts +0 -45
  25. package/dist/migrations/config/types.d.ts.map +0 -1
  26. package/dist/migrations/config/types.js +0 -28
  27. package/dist/migrations/diff/diff.d.ts +0 -11
  28. package/dist/migrations/diff/diff.d.ts.map +0 -1
  29. package/dist/migrations/diff/diff.js +0 -240
  30. package/dist/migrations/diff/index.d.ts +0 -3
  31. package/dist/migrations/diff/index.d.ts.map +0 -1
  32. package/dist/migrations/diff/index.js +0 -1
  33. package/dist/migrations/diff/types.d.ts +0 -74
  34. package/dist/migrations/diff/types.d.ts.map +0 -1
  35. package/dist/migrations/diff/types.js +0 -1
  36. package/dist/migrations/introspect/index.d.ts +0 -3
  37. package/dist/migrations/introspect/index.d.ts.map +0 -1
  38. package/dist/migrations/introspect/index.js +0 -1
  39. package/dist/migrations/introspect/pull-schema.d.ts +0 -23
  40. package/dist/migrations/introspect/pull-schema.d.ts.map +0 -1
  41. package/dist/migrations/introspect/pull-schema.js +0 -135
  42. package/dist/migrations/plan/index.d.ts +0 -3
  43. package/dist/migrations/plan/index.d.ts.map +0 -1
  44. package/dist/migrations/plan/index.js +0 -1
  45. package/dist/migrations/plan/plan.d.ts +0 -12
  46. package/dist/migrations/plan/plan.d.ts.map +0 -1
  47. package/dist/migrations/plan/plan.js +0 -416
  48. package/dist/migrations/plan/types.d.ts +0 -93
  49. package/dist/migrations/plan/types.d.ts.map +0 -1
  50. package/dist/migrations/plan/types.js +0 -1
  51. package/dist/migrations/schema/column.d.ts +0 -71
  52. package/dist/migrations/schema/column.d.ts.map +0 -1
  53. package/dist/migrations/schema/column.js +0 -123
  54. package/dist/migrations/schema/define.d.ts +0 -24
  55. package/dist/migrations/schema/define.d.ts.map +0 -1
  56. package/dist/migrations/schema/define.js +0 -47
  57. package/dist/migrations/schema/index.d.ts +0 -4
  58. package/dist/migrations/schema/index.d.ts.map +0 -1
  59. package/dist/migrations/schema/index.js +0 -2
  60. package/dist/migrations/schema/types.d.ts +0 -74
  61. package/dist/migrations/schema/types.d.ts.map +0 -1
  62. package/dist/migrations/schema/types.js +0 -1
  63. package/dist/migrations/snapshot/index.d.ts +0 -3
  64. package/dist/migrations/snapshot/index.d.ts.map +0 -1
  65. package/dist/migrations/snapshot/index.js +0 -1
  66. package/dist/migrations/snapshot/serialize.d.ts +0 -21
  67. package/dist/migrations/snapshot/serialize.d.ts.map +0 -1
  68. package/dist/migrations/snapshot/serialize.js +0 -127
  69. package/dist/migrations/snapshot/types.d.ts +0 -47
  70. package/dist/migrations/snapshot/types.d.ts.map +0 -1
  71. package/dist/migrations/snapshot/types.js +0 -1
  72. package/dist/migrations/sql/index.d.ts +0 -4
  73. package/dist/migrations/sql/index.d.ts.map +0 -1
  74. package/dist/migrations/sql/index.js +0 -2
  75. package/dist/migrations/sql/render.d.ts +0 -10
  76. package/dist/migrations/sql/render.d.ts.map +0 -1
  77. package/dist/migrations/sql/render.js +0 -347
  78. package/dist/migrations/sql/types.d.ts +0 -53
  79. package/dist/migrations/sql/types.d.ts.map +0 -1
  80. package/dist/migrations/sql/types.js +0 -1
  81. package/dist/migrations/sql/write.d.ts +0 -10
  82. package/dist/migrations/sql/write.d.ts.map +0 -1
  83. package/dist/migrations/sql/write.js +0 -35
  84. package/dist/semantic-backend.d.ts +0 -7
  85. package/dist/semantic-backend.d.ts.map +0 -1
  86. package/dist/semantic-backend.js +0 -208
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hypequery/clickhouse
2
2
 
3
- Typed ClickHouse query builder for hypequery.
3
+ Typed query builder for ClickHouse.
4
4
 
5
5
  Use it when you want schema-aware queries, typed results, and a fluent API that stays close to how ClickHouse actually works.
6
6
 
@@ -1,5 +1,39 @@
1
+ /**
2
+ * Minimal ClickHouse client surface needed by the type generator.
3
+ */
4
+ export interface TypeGenerationClickHouseClient {
5
+ query(options: { query: string; format: 'JSONEachRow' }): Promise<{
6
+ json(): Promise<Array<Record<string, string>>>;
7
+ }>;
8
+ }
9
+
10
+ /**
11
+ * Options for generating TypeScript type definitions from ClickHouse.
12
+ */
13
+ export interface GenerateTypesOptions {
14
+ includeTables?: string[];
15
+ excludeTables?: string[];
16
+ client?: TypeGenerationClickHouseClient;
17
+ generatedBy?: string;
18
+ includeUsageExample?: boolean;
19
+ }
20
+
21
+ /**
22
+ * Converts a ClickHouse type string to a TypeScript type string.
23
+ */
24
+ export declare function clickhouseToTsType(type: string): string;
25
+
1
26
  /**
2
27
  * Generates TypeScript type definitions from the ClickHouse database schema
3
28
  * @param outputPath - The file path where the type definitions will be written
29
+ * @param options - Options for type generation
30
+ */
31
+ export declare function generateTypes(outputPath: string, options?: GenerateTypesOptions): Promise<void>;
32
+
33
+ /**
34
+ * Generates TypeScript type definition contents from a ClickHouse client.
4
35
  */
5
- export declare function generateTypes(outputPath: string): Promise<void>;
36
+ export declare function generateTypeDefinitions(
37
+ client: TypeGenerationClickHouseClient,
38
+ options?: GenerateTypesOptions,
39
+ ): Promise<string>;
@@ -19,6 +19,9 @@ dotenv.config();
19
19
  * @typedef {Object} GenerateTypesOptions
20
20
  * @property {string[]} [includeTables] - List of tables to include
21
21
  * @property {string[]} [excludeTables] - List of tables to exclude
22
+ * @property {object} [client] - ClickHouse client to use instead of ClickHouseConnection
23
+ * @property {string} [generatedBy] - Package name to include in the generated file header
24
+ * @property {boolean} [includeUsageExample] - Whether to append the historical usage example
22
25
  */
23
26
 
24
27
  /**
@@ -28,8 +31,30 @@ dotenv.config();
28
31
  * @returns {Promise<void>}
29
32
  */
30
33
  export async function generateTypes(outputPath, options = {}) {
31
- const client = ClickHouseConnection.getClient();
32
- const { includeTables = [], excludeTables = [] } = options;
34
+ const client = options.client || ClickHouseConnection.getClient();
35
+ const typeDefinitions = await generateTypeDefinitions(client, options);
36
+
37
+ // Ensure the output directory exists
38
+ const outputDir = path.dirname(path.resolve(outputPath));
39
+ await fs.mkdir(outputDir, { recursive: true });
40
+
41
+ // Write the file
42
+ await fs.writeFile(path.resolve(outputPath), typeDefinitions);
43
+ }
44
+
45
+ /**
46
+ * Generates TypeScript type definition contents from a ClickHouse client.
47
+ * @param {object} client - ClickHouse client with a query method
48
+ * @param {GenerateTypesOptions} [options] - Options for type generation
49
+ * @returns {Promise<string>}
50
+ */
51
+ export async function generateTypeDefinitions(client, options = {}) {
52
+ const {
53
+ includeTables = [],
54
+ excludeTables = [],
55
+ generatedBy = '@hypequery/clickhouse',
56
+ includeUsageExample = true,
57
+ } = options;
33
58
 
34
59
  // Get all tables
35
60
  const tablesQuery = await client.query({
@@ -52,7 +77,7 @@ export async function generateTypes(outputPath, options = {}) {
52
77
  console.warn('Warning: No tables match the filter criteria. Check your include/exclude options.');
53
78
  }
54
79
 
55
- let typeDefinitions = `// Generated by @hypequery/clickhouse
80
+ let typeDefinitions = `// Generated by ${generatedBy}
56
81
  // This file defines TypeScript types based on your ClickHouse database schema
57
82
 
58
83
  /**
@@ -95,8 +120,8 @@ export interface IntrospectedSchema {`;
95
120
  typeDefinitions += '\n}\n\n';
96
121
  }
97
122
 
98
- // Add a usage example
99
- typeDefinitions += `
123
+ if (includeUsageExample) {
124
+ typeDefinitions += `
100
125
  /**
101
126
  * Usage example:
102
127
  *
@@ -114,13 +139,9 @@ export interface IntrospectedSchema {`;
114
139
  * .execute();
115
140
  */
116
141
  `;
142
+ }
117
143
 
118
- // Ensure the output directory exists
119
- const outputDir = path.dirname(path.resolve(outputPath));
120
- await fs.mkdir(outputDir, { recursive: true });
121
-
122
- // Write the file
123
- await fs.writeFile(path.resolve(outputPath), typeDefinitions);
144
+ return typeDefinitions;
124
145
  }
125
146
 
126
147
  /**
@@ -1,2 +1,8 @@
1
1
  // CLI module type declarations
2
- export { generateTypes } from './generate-types';
2
+ export {
3
+ clickhouseToTsType,
4
+ generateTypeDefinitions,
5
+ generateTypes,
6
+ type GenerateTypesOptions,
7
+ type TypeGenerationClickHouseClient,
8
+ } from './generate-types';
package/dist/cli/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // CLI module exports
2
- export { generateTypes } from './generate-types.js';
2
+ export { clickhouseToTsType, generateTypeDefinitions, generateTypes } from './generate-types.js';
@@ -33,10 +33,20 @@ function splitTopLevelArgs(value) {
33
33
  }
34
34
 
35
35
  function unwrapType(type, wrapperName) {
36
- const prefix = `${wrapperName}(`;
37
- return type.startsWith(prefix) && type.endsWith(')')
38
- ? type.slice(prefix.length, -1)
39
- : null;
36
+ // Trim whitespace and handle case-insensitive matching
37
+ const trimmedType = type.trim();
38
+ const lowerType = trimmedType.toLowerCase();
39
+ const lowerWrapper = wrapperName.toLowerCase();
40
+ const prefix = `${lowerWrapper}(`;
41
+
42
+ if (lowerType.startsWith(prefix) && trimmedType.endsWith(')')) {
43
+ // Extract inner type, preserving original case
44
+ const innerStart = trimmedType.indexOf('(') + 1;
45
+ const innerEnd = trimmedType.lastIndexOf(')');
46
+ return trimmedType.slice(innerStart, innerEnd).trim();
47
+ }
48
+
49
+ return null;
40
50
  }
41
51
 
42
52
  function getPrimitiveTsType(type) {
@@ -45,6 +55,8 @@ function getPrimitiveTsType(type) {
45
55
  switch (lowerType) {
46
56
  case 'string':
47
57
  case 'uuid':
58
+ case 'ipv4':
59
+ case 'ipv6':
48
60
  return 'string';
49
61
  case 'int8':
50
62
  case 'int16':
@@ -72,9 +84,15 @@ function getPrimitiveTsType(type) {
72
84
  case 'bool':
73
85
  case 'boolean':
74
86
  return 'boolean';
87
+ case 'json':
88
+ return 'unknown';
75
89
  default:
76
90
  if (type.startsWith('FixedString(')) return 'string';
77
91
  if (type.startsWith('Decimal(')) return 'number';
92
+ if (type.startsWith('Decimal32(')) return 'number';
93
+ if (type.startsWith('Decimal64(')) return 'number';
94
+ if (type.startsWith('Decimal128(')) return 'number';
95
+ if (type.startsWith('Decimal256(')) return 'number';
78
96
  if (type.startsWith('DateTime64(')) return 'string';
79
97
  if (type.startsWith('DateTime(')) return 'string';
80
98
  if (type.startsWith('Enum8(')) return 'string';
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/clickhouse-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAExE,qBAAa,iBAAkB,YAAW,UAAU;IAClD,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,SAAS,CAAsB;IAEvC,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa;IA6D3F,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ5E,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;CAK1D"}
1
+ {"version":3,"file":"clickhouse-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/clickhouse-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAExE,qBAAa,iBAAkB,YAAW,UAAU;IAClD,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,SAAS,CAAsB;IAEvC,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa;IA6D3F,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ5E,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;CAK1D"}
@@ -1,4 +1,5 @@
1
1
  import { SQLFormatter } from '../formatters/sql-formatter.js';
2
+ import { formatIntervalLiteral } from '../utils/sql-literals.js';
2
3
  export class ClickHouseDialect {
3
4
  name = 'clickhouse';
4
5
  formatter = new SQLFormatter();
@@ -52,7 +53,7 @@ export class ClickHouseDialect {
52
53
  }
53
54
  formatTimeInterval(column, interval, method) {
54
55
  if (method === 'toStartOfInterval') {
55
- return `${method}(${column}, INTERVAL ${interval})`;
56
+ return `${method}(${column}, INTERVAL ${formatIntervalLiteral(interval)})`;
56
57
  }
57
58
  return `${method}(${column})`;
58
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../../src/core/tests/integration/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,SAAS,EASV,MAAM,kDAAkD,CAAC;AA4B1D,eAAO,MAAM,wBAAwB;;;;;;EAyBpC,CAAC;AAGF,eAAO,MAAM,2BAA2B,yGAevC,CAAC;AAGF,eAAO,MAAM,kBAAkB,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,OAAO,CAE/E,CAAC;AAGF,eAAO,MAAM,wBAAwB,QAAa,OAAO,CAAC,IAAI,CAO7D,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAC5B,oBAAgB,EAChB,sBAAoB,KACnB,OAAO,CAAC,IAAI,CAOd,CAAC;AAGF,eAAO,MAAM,uBAAuB,QAAa,OAAO,CAAC,IAAI,CAU5D,CAAC;AAGF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;QACnB,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,SAAS,EAAE,CAAC;AAKxE,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,IAAI,CAuBtD,CAAC"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../../src/core/tests/integration/setup.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,SAAS,EAQV,MAAM,kDAAkD,CAAC;AA4B1D,eAAO,MAAM,wBAAwB;;;;;;EAyBpC,CAAC;AAGF,eAAO,MAAM,2BAA2B,yGAevC,CAAC;AAGF,eAAO,MAAM,kBAAkB,GAAU,eAAe,MAAM,KAAG,OAAO,CAAC,OAAO,CAE/E,CAAC;AAGF,eAAO,MAAM,wBAAwB,QAAa,OAAO,CAAC,IAAI,CAO7D,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAC5B,oBAAgB,EAChB,sBAAoB,KACnB,OAAO,CAAC,IAAI,CAOd,CAAC;AAGF,eAAO,MAAM,uBAAuB,QAAa,OAAO,CAAC,IAAI,CAU5D,CAAC;AAGF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,KAAK,CAAC;QAChB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;QACnB,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QACX,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AAED,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,SAAS,EAAE,CAAC;AAKxE,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,IAAI,CAuBtD,CAAC"}
@@ -1,8 +1,6 @@
1
1
  import { ClickHouseConnection } from '../../connection.js';
2
2
  import { logger as hypeQueryLogger } from '../../utils/logger.js';
3
- import { CLICKHOUSE_CONTAINER_NAME, TEST_CONNECTION_CONFIG, TEST_DATA, detectComposeCommand, ensureDockerDaemon, isContainerRunning as sharedIsContainerRunning, seedClickHouseDatabase, startClickHouseContainer as sharedStartClickHouseContainer, stopClickHouseContainer as sharedStopClickHouseContainer, waitForClickHouse as sharedWaitForClickHouse,
4
- // @ts-expect-error: shared test harness is plain JS
5
- } from '../../../../../../testing/clickhouse/harness.mjs';
3
+ import { CLICKHOUSE_CONTAINER_NAME, TEST_CONNECTION_CONFIG, TEST_DATA, detectComposeCommand, ensureDockerDaemon, isContainerRunning as sharedIsContainerRunning, seedClickHouseDatabase, startClickHouseContainer as sharedStartClickHouseContainer, stopClickHouseContainer as sharedStopClickHouseContainer, waitForClickHouse as sharedWaitForClickHouse, } from '../../../../../../testing/clickhouse/harness.mjs';
6
4
  // Disable the hypequery logger to prevent "logs after tests" errors
7
5
  // This must be done early in the setup, before any queries run
8
6
  hypeQueryLogger.configure({ enabled: false });
@@ -1 +1 @@
1
- {"version":3,"file":"sql-expressions.d.ts","sourceRoot":"","sources":["../../../src/core/utils/sql-expressions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sql-expressions.d.ts","sourceRoot":"","sources":["../../../src/core/utils/sql-expressions.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { formatIntervalLiteral, quoteStringLiteral } from './sql-literals.js';
1
2
  /**
2
3
  * Creates a raw SQL expression
3
4
  * @param sql The SQL expression string
@@ -34,17 +35,18 @@ export function toDateTime(field, alias) {
34
35
  }
35
36
  export function formatDateTime(field, format, options = {}) {
36
37
  const { timezone, alias } = options;
37
- let sql = `formatDateTime(${field}, '${format}'`;
38
+ let sql = `formatDateTime(${field}, ${quoteStringLiteral(format)}`;
38
39
  if (timezone) {
39
- sql += `, '${timezone}'`;
40
+ sql += `, ${quoteStringLiteral(timezone)}`;
40
41
  }
41
42
  sql += ')';
42
43
  return alias ? rawAs(sql, alias) : raw(sql);
43
44
  }
44
45
  export function toStartOfInterval(field, interval, alias) {
46
+ const sql = `toStartOfInterval(${field}, INTERVAL ${formatIntervalLiteral(interval)})`;
45
47
  return alias
46
- ? rawAs(`toStartOfInterval(${field}, INTERVAL ${interval})`, alias)
47
- : raw(`toStartOfInterval(${field}, INTERVAL ${interval})`);
48
+ ? rawAs(sql, alias)
49
+ : raw(sql);
48
50
  }
49
51
  function toStartOfUnit(functionName, field, alias) {
50
52
  return alias
@@ -0,0 +1,3 @@
1
+ export declare function formatIntervalLiteral(interval: string): string;
2
+ export declare function quoteStringLiteral(value: string): string;
3
+ //# sourceMappingURL=sql-literals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-literals.d.ts","sourceRoot":"","sources":["../../../src/core/utils/sql-literals.ts"],"names":[],"mappings":"AA2BA,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAc9D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD"}
@@ -0,0 +1,39 @@
1
+ const INTERVAL_UNITS = {
2
+ second: 'SECOND',
3
+ seconds: 'SECOND',
4
+ minute: 'MINUTE',
5
+ minutes: 'MINUTE',
6
+ hour: 'HOUR',
7
+ hours: 'HOUR',
8
+ day: 'DAY',
9
+ days: 'DAY',
10
+ week: 'WEEK',
11
+ weeks: 'WEEK',
12
+ month: 'MONTH',
13
+ months: 'MONTH',
14
+ quarter: 'QUARTER',
15
+ quarters: 'QUARTER',
16
+ year: 'YEAR',
17
+ years: 'YEAR',
18
+ millisecond: 'MILLISECOND',
19
+ milliseconds: 'MILLISECOND',
20
+ microsecond: 'MICROSECOND',
21
+ microseconds: 'MICROSECOND',
22
+ nanosecond: 'NANOSECOND',
23
+ nanoseconds: 'NANOSECOND',
24
+ };
25
+ const INTERVAL_PATTERN = /^(\d+)\s+([a-z]+)$/i;
26
+ export function formatIntervalLiteral(interval) {
27
+ const normalized = interval.trim();
28
+ const match = normalized.match(INTERVAL_PATTERN);
29
+ const unit = match ? INTERVAL_UNITS[match[2].toLowerCase()] : undefined;
30
+ if (!match || !unit) {
31
+ throw new Error(`Invalid time interval: "${interval}". Expected "<number> <unit>" where unit is ` +
32
+ 'one of second, minute, hour, day, week, month, quarter, year, millisecond, microsecond, nanosecond ' +
33
+ '(e.g. "1 day", "15 minute").');
34
+ }
35
+ return `${match[1]} ${unit}`;
36
+ }
37
+ export function quoteStringLiteral(value) {
38
+ return `'${value.replace(/\\/g, '\\\\').replace(/'/g, "''")}'`;
39
+ }
@@ -9,18 +9,30 @@
9
9
  * - @hypequery/datasets: Owns semantic planning, validation, and execution protocol
10
10
  * - @hypequery/clickhouse: Implements SQL translation and execution for ClickHouse
11
11
  *
12
- * Usage:
12
+ * Usage (recommended): pass the query builder you already use for
13
+ * hand-written queries, so semantic and ad hoc queries share one connection.
13
14
  * ```ts
14
15
  * import { createDatasetClient } from '@hypequery/datasets';
15
- * import { createBackend } from '@hypequery/clickhouse';
16
+ * import { createQueryBuilder } from '@hypequery/clickhouse';
17
+ *
18
+ * const db = createQueryBuilder({
19
+ * url: process.env.CLICKHOUSE_URL,
20
+ * username: process.env.CLICKHOUSE_USER,
21
+ * password: process.env.CLICKHOUSE_PASSWORD,
22
+ * database: process.env.CLICKHOUSE_DATABASE,
23
+ * });
24
+ *
25
+ * const analytics = createDatasetClient({ queryBuilder: db });
26
+ * ```
27
+ *
28
+ * Advanced: `createBackend` exposes the database-agnostic SemanticBackend
29
+ * protocol directly. Reach for it when you want a standalone backend instance
30
+ * rather than sharing a query builder.
31
+ * ```ts
32
+ * import { createBackend } from '@hypequery/clickhouse/datasets';
16
33
  *
17
34
  * const analytics = createDatasetClient({
18
- * backend: createBackend({
19
- * url: process.env.CLICKHOUSE_URL,
20
- * username: process.env.CLICKHOUSE_USER,
21
- * password: process.env.CLICKHOUSE_PASSWORD,
22
- * database: process.env.CLICKHOUSE_DATABASE,
23
- * })
35
+ * backend: createBackend({ url, username, password, database }),
24
36
  * });
25
37
  * ```
26
38
  */
@@ -1 +1 @@
1
- {"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../src/datasets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,CAAC;AAuW3D;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACnE,MAAM,EAAE,mBAAmB,GAC1B,eAAe,CAmDjB"}
1
+ {"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../src/datasets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,CAAC;AAuW3D;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACnE,MAAM,EAAE,mBAAmB,GAC1B,eAAe,CAqDjB"}
package/dist/datasets.js CHANGED
@@ -9,18 +9,30 @@
9
9
  * - @hypequery/datasets: Owns semantic planning, validation, and execution protocol
10
10
  * - @hypequery/clickhouse: Implements SQL translation and execution for ClickHouse
11
11
  *
12
- * Usage:
12
+ * Usage (recommended): pass the query builder you already use for
13
+ * hand-written queries, so semantic and ad hoc queries share one connection.
13
14
  * ```ts
14
15
  * import { createDatasetClient } from '@hypequery/datasets';
15
- * import { createBackend } from '@hypequery/clickhouse';
16
+ * import { createQueryBuilder } from '@hypequery/clickhouse';
17
+ *
18
+ * const db = createQueryBuilder({
19
+ * url: process.env.CLICKHOUSE_URL,
20
+ * username: process.env.CLICKHOUSE_USER,
21
+ * password: process.env.CLICKHOUSE_PASSWORD,
22
+ * database: process.env.CLICKHOUSE_DATABASE,
23
+ * });
24
+ *
25
+ * const analytics = createDatasetClient({ queryBuilder: db });
26
+ * ```
27
+ *
28
+ * Advanced: `createBackend` exposes the database-agnostic SemanticBackend
29
+ * protocol directly. Reach for it when you want a standalone backend instance
30
+ * rather than sharing a query builder.
31
+ * ```ts
32
+ * import { createBackend } from '@hypequery/clickhouse/datasets';
16
33
  *
17
34
  * const analytics = createDatasetClient({
18
- * backend: createBackend({
19
- * url: process.env.CLICKHOUSE_URL,
20
- * username: process.env.CLICKHOUSE_USER,
21
- * password: process.env.CLICKHOUSE_PASSWORD,
22
- * database: process.env.CLICKHOUSE_DATABASE,
23
- * })
35
+ * backend: createBackend({ url, username, password, database }),
24
36
  * });
25
37
  * ```
26
38
  */
@@ -282,7 +294,7 @@ function buildAggregateQuery(queryBuilder, plan) {
282
294
  }
283
295
  // Apply tenant filter (auto-injected)
284
296
  if (plan.tenant) {
285
- qb = qb.where(plan.tenant.field, 'eq', plan.tenant.value);
297
+ qb = qb.where(plan.tenant.field, plan.tenant.operator, plan.tenant.value);
286
298
  }
287
299
  // Apply user filters
288
300
  qb = applyFilters(qb, plan.filters);
@@ -357,14 +369,16 @@ export function createBackend(config) {
357
369
  meta: {
358
370
  sql,
359
371
  timingMs: Date.now() - start,
360
- tenant: plan.tenant?.value,
372
+ tenant: plan.tenant?.operator === 'eq' ? plan.tenant.value : undefined,
361
373
  },
362
374
  };
363
375
  }
364
376
  // Derived metrics: CTE query with formulas
365
377
  const { sql, parameters } = buildDerivedSQL(queryBuilder, plan);
366
378
  const data = await queryBuilder.rawQuery(sql, parameters);
367
- const tenant = plan.input.kind === 'aggregate' ? plan.input.tenant?.value : undefined;
379
+ const tenant = plan.input.kind === 'aggregate' && plan.input.tenant?.operator === 'eq'
380
+ ? plan.input.tenant.value
381
+ : undefined;
368
382
  return {
369
383
  data,
370
384
  meta: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/clickhouse",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "ClickHouse typescript query builder",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,6 +14,11 @@
14
14
  "import": "./dist/index.js",
15
15
  "require": "./dist/index.js"
16
16
  },
17
+ "./datasets": {
18
+ "types": "./dist/datasets.d.ts",
19
+ "import": "./dist/datasets.js",
20
+ "require": "./dist/datasets.js"
21
+ },
17
22
  "./cli": {
18
23
  "types": "./dist/cli/index.d.ts",
19
24
  "import": "./dist/cli/index.js",
@@ -33,11 +38,15 @@
33
38
  "dotenv": "^16.0.0"
34
39
  },
35
40
  "peerDependencies": {
36
- "@clickhouse/client-web": "^0.2.0 || ^1.0.0"
41
+ "@clickhouse/client-web": "^0.2.0 || ^1.0.0",
42
+ "@hypequery/datasets": "^0.1.0 || ^0.2.0"
37
43
  },
38
44
  "peerDependenciesMeta": {
39
45
  "@clickhouse/client-web": {
40
46
  "optional": true
47
+ },
48
+ "@hypequery/datasets": {
49
+ "optional": true
41
50
  }
42
51
  },
43
52
  "devDependencies": {
@@ -51,7 +60,8 @@
51
60
  "typedoc-plugin-markdown": "^4.6.0",
52
61
  "typescript": "^5.7.3",
53
62
  "@vitest/coverage-v8": "^2.1.6",
54
- "vitest": "^2.1.6"
63
+ "vitest": "^2.1.6",
64
+ "@hypequery/datasets": "0.2.0"
55
65
  },
56
66
  "ts-node": {
57
67
  "esm": true,