@hypequery/clickhouse 1.6.1 → 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/cli/generate-types.js +3 -81
  5. package/dist/cli/type-parsing.js +124 -0
  6. package/dist/core/adapters/clickhouse-adapter.d.ts.map +1 -1
  7. package/dist/core/adapters/clickhouse-adapter.js +3 -2
  8. package/dist/core/cache/cache-manager.d.ts.map +1 -1
  9. package/dist/core/cache/cache-manager.js +5 -3
  10. package/dist/core/connection.d.ts +6 -6
  11. package/dist/core/connection.js +9 -9
  12. package/dist/core/cross-filter.js +1 -1
  13. package/dist/core/dialects/clickhouse-dialect.d.ts +2 -2
  14. package/dist/core/dialects/clickhouse-dialect.d.ts.map +1 -1
  15. package/dist/core/dialects/clickhouse-dialect.js +39 -22
  16. package/dist/core/dialects/sql-dialect.d.ts +2 -2
  17. package/dist/core/dialects/sql-dialect.d.ts.map +1 -1
  18. package/dist/core/env/auto-client.d.ts.map +1 -1
  19. package/dist/core/env/auto-client.js +1 -1
  20. package/dist/core/features/aggregations.d.ts +7 -90
  21. package/dist/core/features/aggregations.d.ts.map +1 -1
  22. package/dist/core/features/aggregations.js +19 -7
  23. package/dist/core/features/analytics.d.ts +5 -870
  24. package/dist/core/features/analytics.d.ts.map +1 -1
  25. package/dist/core/features/analytics.js +15 -13
  26. package/dist/core/features/cross-filtering.d.ts +1 -1
  27. package/dist/core/features/cross-filtering.d.ts.map +1 -1
  28. package/dist/core/features/cross-filtering.js +28 -73
  29. package/dist/core/features/executor.d.ts +1 -1
  30. package/dist/core/features/executor.d.ts.map +1 -1
  31. package/dist/core/features/executor.js +9 -11
  32. package/dist/core/features/filtering.d.ts +5 -91
  33. package/dist/core/features/filtering.d.ts.map +1 -1
  34. package/dist/core/features/filtering.js +63 -77
  35. package/dist/core/features/joins.d.ts +2 -19
  36. package/dist/core/features/joins.d.ts.map +1 -1
  37. package/dist/core/features/joins.js +16 -5
  38. package/dist/core/features/query-modifiers.d.ts +10 -109
  39. package/dist/core/features/query-modifiers.d.ts.map +1 -1
  40. package/dist/core/features/query-modifiers.js +64 -18
  41. package/dist/core/formatters/sql-formatter.d.ts +16 -5
  42. package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
  43. package/dist/core/formatters/sql-formatter.js +197 -93
  44. package/dist/core/join-relationships.d.ts +22 -5
  45. package/dist/core/join-relationships.d.ts.map +1 -1
  46. package/dist/core/join-relationships.js +1 -1
  47. package/dist/core/query-builder.d.ts +63 -12
  48. package/dist/core/query-builder.d.ts.map +1 -1
  49. package/dist/core/query-builder.js +210 -153
  50. package/dist/core/query-node.d.ts +7 -0
  51. package/dist/core/query-node.d.ts.map +1 -0
  52. package/dist/core/query-node.js +80 -0
  53. package/dist/core/tests/integration/setup.d.ts +1 -0
  54. package/dist/core/tests/integration/setup.d.ts.map +1 -1
  55. package/dist/core/tests/integration/setup.js +4 -2
  56. package/dist/core/types/select-types.d.ts +3 -0
  57. package/dist/core/types/select-types.d.ts.map +1 -1
  58. package/dist/core/utils/connection-endpoint.d.ts +3 -0
  59. package/dist/core/utils/connection-endpoint.d.ts.map +1 -0
  60. package/dist/core/utils/connection-endpoint.js +9 -0
  61. package/dist/core/utils/filter-application.d.ts +15 -0
  62. package/dist/core/utils/filter-application.d.ts.map +1 -0
  63. package/dist/core/utils/filter-application.js +32 -0
  64. package/dist/core/utils/query-config-compat.d.ts +48 -0
  65. package/dist/core/utils/query-config-compat.d.ts.map +1 -0
  66. package/dist/core/utils/query-config-compat.js +137 -0
  67. package/dist/core/utils/relation-application.d.ts +9 -0
  68. package/dist/core/utils/relation-application.d.ts.map +1 -0
  69. package/dist/core/utils/relation-application.js +19 -0
  70. package/dist/core/utils/relation-validation.d.ts +6 -0
  71. package/dist/core/utils/relation-validation.d.ts.map +1 -0
  72. package/dist/core/utils/relation-validation.js +29 -0
  73. package/dist/core/utils/sql-expressions.d.ts +14 -0
  74. package/dist/core/utils/sql-expressions.d.ts.map +1 -1
  75. package/dist/core/utils/sql-expressions.js +40 -0
  76. package/dist/core/utils/tuple-filter-validation.d.ts +3 -0
  77. package/dist/core/utils/tuple-filter-validation.d.ts.map +1 -0
  78. package/dist/core/utils/tuple-filter-validation.js +16 -0
  79. package/dist/index.d.ts +2 -11
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +3 -7
  82. package/dist/types/base.d.ts +88 -22
  83. package/dist/types/base.d.ts.map +1 -1
  84. package/dist/types/clickhouse-types.d.ts +5 -2
  85. package/dist/types/clickhouse-types.d.ts.map +1 -1
  86. package/dist/types/filters.d.ts +9 -5
  87. package/dist/types/filters.d.ts.map +1 -1
  88. package/dist/types/index.d.ts +1 -0
  89. package/dist/types/index.d.ts.map +1 -1
  90. package/dist/types/index.js +1 -0
  91. package/dist/types/type-helpers.d.ts +7 -0
  92. package/dist/types/type-helpers.d.ts.map +1 -0
  93. package/package.json +5 -5
  94. package/dist/migrations/config/index.d.ts +0 -3
  95. package/dist/migrations/config/index.d.ts.map +0 -1
  96. package/dist/migrations/config/index.js +0 -1
  97. package/dist/migrations/config/types.d.ts +0 -45
  98. package/dist/migrations/config/types.d.ts.map +0 -1
  99. package/dist/migrations/config/types.js +0 -28
  100. package/dist/migrations/diff/diff.d.ts +0 -11
  101. package/dist/migrations/diff/diff.d.ts.map +0 -1
  102. package/dist/migrations/diff/diff.js +0 -240
  103. package/dist/migrations/diff/index.d.ts +0 -3
  104. package/dist/migrations/diff/index.d.ts.map +0 -1
  105. package/dist/migrations/diff/index.js +0 -1
  106. package/dist/migrations/diff/types.d.ts +0 -74
  107. package/dist/migrations/diff/types.d.ts.map +0 -1
  108. package/dist/migrations/schema/column.d.ts +0 -71
  109. package/dist/migrations/schema/column.d.ts.map +0 -1
  110. package/dist/migrations/schema/column.js +0 -123
  111. package/dist/migrations/schema/define.d.ts +0 -24
  112. package/dist/migrations/schema/define.d.ts.map +0 -1
  113. package/dist/migrations/schema/define.js +0 -47
  114. package/dist/migrations/schema/index.d.ts +0 -4
  115. package/dist/migrations/schema/index.d.ts.map +0 -1
  116. package/dist/migrations/schema/index.js +0 -2
  117. package/dist/migrations/schema/types.d.ts +0 -74
  118. package/dist/migrations/schema/types.d.ts.map +0 -1
  119. package/dist/migrations/schema/types.js +0 -1
  120. package/dist/migrations/snapshot/index.d.ts +0 -3
  121. package/dist/migrations/snapshot/index.d.ts.map +0 -1
  122. package/dist/migrations/snapshot/index.js +0 -1
  123. package/dist/migrations/snapshot/serialize.d.ts +0 -21
  124. package/dist/migrations/snapshot/serialize.d.ts.map +0 -1
  125. package/dist/migrations/snapshot/serialize.js +0 -127
  126. package/dist/migrations/snapshot/types.d.ts +0 -47
  127. package/dist/migrations/snapshot/types.d.ts.map +0 -1
  128. package/dist/migrations/snapshot/types.js +0 -1
  129. package/dist/migrations/sql/index.d.ts +0 -4
  130. package/dist/migrations/sql/index.d.ts.map +0 -1
  131. package/dist/migrations/sql/index.js +0 -2
  132. package/dist/migrations/sql/render.d.ts +0 -11
  133. package/dist/migrations/sql/render.d.ts.map +0 -1
  134. package/dist/migrations/sql/render.js +0 -334
  135. package/dist/migrations/sql/types.d.ts +0 -48
  136. package/dist/migrations/sql/types.d.ts.map +0 -1
  137. package/dist/migrations/sql/types.js +0 -1
  138. package/dist/migrations/sql/write.d.ts +0 -9
  139. package/dist/migrations/sql/write.d.ts.map +0 -1
  140. package/dist/migrations/sql/write.js +0 -31
  141. /package/dist/{migrations/diff/types.js → types/type-helpers.js} +0 -0
@@ -2,6 +2,9 @@ import { ClickHouseConnection } from '../core/connection.js';
2
2
  import fs from 'fs/promises';
3
3
  import path from 'path';
4
4
  import dotenv from 'dotenv';
5
+ import { clickhouseToTsType } from './type-parsing.js';
6
+
7
+ export { clickhouseToTsType } from './type-parsing.js';
5
8
 
6
9
  // Load environment variables from the current directory
7
10
  dotenv.config();
@@ -18,87 +21,6 @@ dotenv.config();
18
21
  * @property {string[]} [excludeTables] - List of tables to exclude
19
22
  */
20
23
 
21
- /**
22
- * Converts ClickHouse types to TypeScript types
23
- * @param {string} type - The ClickHouse type to convert
24
- * @returns {string} - The corresponding TypeScript type
25
- */
26
- export const clickhouseToTsType = (type) => {
27
- if (type.startsWith('Array(')) {
28
- const innerType = type.slice(6, -1);
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`;
36
- }
37
-
38
- // Handle Map types
39
- if (type.startsWith('Map(')) {
40
- // Extract key and value types from Map(KeyType, ValueType)
41
- const mapContent = type.slice(4, -1); // Remove 'Map(' and ')'
42
- const commaIndex = mapContent.lastIndexOf(',');
43
- if (commaIndex !== -1) {
44
- const keyType = mapContent.substring(0, commaIndex).trim();
45
- const valueType = mapContent.substring(commaIndex + 1).trim();
46
-
47
- // Handle different value types
48
- let valueTsType = 'unknown';
49
- if (valueType.startsWith('Array(')) {
50
- const innerType = valueType.slice(6, -1);
51
- valueTsType = `Array<${clickhouseToTsType(innerType)}>`;
52
- } else if (valueType.startsWith('Nullable(')) {
53
- const innerType = valueType.slice(9, -1);
54
- valueTsType = `${clickhouseToTsType(innerType)} | null`;
55
- } else {
56
- valueTsType = clickhouseToTsType(valueType);
57
- }
58
-
59
- // JSON object keys are strings even when ClickHouse map keys are numeric.
60
- return `Record<string, ${valueTsType}>`;
61
- }
62
- return 'Record<string, unknown>';
63
- }
64
-
65
- switch (type.toLowerCase()) {
66
- case 'string':
67
- case 'fixedstring':
68
- return 'string';
69
- case 'int8':
70
- case 'int16':
71
- case 'int32':
72
- case 'uint8':
73
- case 'uint16':
74
- case 'uint32':
75
- return 'number';
76
- case 'int64':
77
- case 'uint64':
78
- case 'uint128':
79
- case 'uint256':
80
- case 'int128':
81
- case 'int256':
82
- return 'string';
83
- case 'float32':
84
- case 'float64':
85
- case 'decimal':
86
- return 'number';
87
- case 'datetime':
88
- case 'datetime64':
89
- return 'string'; // Use string for datetime
90
- case 'date':
91
- case 'date32':
92
- return 'string'; // Use string for date
93
- case 'bool':
94
- case 'boolean':
95
- return 'boolean';
96
- default:
97
- // For complex types or unknown types, return string as a safe default
98
- return 'string';
99
- }
100
- };
101
-
102
24
  /**
103
25
  * Generates TypeScript type definitions from the ClickHouse database schema
104
26
  * @param {string} outputPath - The file path where the type definitions will be written
@@ -0,0 +1,124 @@
1
+ function splitTopLevelArgs(value) {
2
+ const parts = [];
3
+ let current = '';
4
+ let depth = 0;
5
+
6
+ for (const char of value) {
7
+ if (char === '(') {
8
+ depth += 1;
9
+ current += char;
10
+ continue;
11
+ }
12
+
13
+ if (char === ')') {
14
+ depth -= 1;
15
+ current += char;
16
+ continue;
17
+ }
18
+
19
+ if (char === ',' && depth === 0) {
20
+ parts.push(current.trim());
21
+ current = '';
22
+ continue;
23
+ }
24
+
25
+ current += char;
26
+ }
27
+
28
+ if (current.trim()) {
29
+ parts.push(current.trim());
30
+ }
31
+
32
+ return parts;
33
+ }
34
+
35
+ function unwrapType(type, wrapperName) {
36
+ const prefix = `${wrapperName}(`;
37
+ return type.startsWith(prefix) && type.endsWith(')')
38
+ ? type.slice(prefix.length, -1)
39
+ : null;
40
+ }
41
+
42
+ function getPrimitiveTsType(type) {
43
+ const lowerType = type.toLowerCase();
44
+
45
+ switch (lowerType) {
46
+ case 'string':
47
+ case 'uuid':
48
+ return 'string';
49
+ case 'int8':
50
+ case 'int16':
51
+ case 'int32':
52
+ case 'uint8':
53
+ case 'uint16':
54
+ case 'uint32':
55
+ return 'number';
56
+ case 'int64':
57
+ case 'uint64':
58
+ case 'uint128':
59
+ case 'uint256':
60
+ case 'int128':
61
+ case 'int256':
62
+ return 'string';
63
+ case 'float32':
64
+ case 'float64':
65
+ case 'decimal':
66
+ return 'number';
67
+ case 'datetime':
68
+ case 'datetime64':
69
+ case 'date':
70
+ case 'date32':
71
+ return 'string';
72
+ case 'bool':
73
+ case 'boolean':
74
+ return 'boolean';
75
+ default:
76
+ if (type.startsWith('FixedString(')) return 'string';
77
+ if (type.startsWith('Decimal(')) return 'number';
78
+ if (type.startsWith('DateTime64(')) return 'string';
79
+ if (type.startsWith('DateTime(')) return 'string';
80
+ if (type.startsWith('Enum8(')) return 'string';
81
+ if (type.startsWith('Enum16(')) return 'string';
82
+ return null;
83
+ }
84
+ }
85
+
86
+ export const clickhouseToTsType = (type) => {
87
+ const wrappedArrayType = unwrapType(type, 'Array');
88
+ if (wrappedArrayType) {
89
+ return `Array<${clickhouseToTsType(wrappedArrayType)}>`;
90
+ }
91
+
92
+ const wrappedNullableType = unwrapType(type, 'Nullable');
93
+ if (wrappedNullableType) {
94
+ return `${clickhouseToTsType(wrappedNullableType)} | null`;
95
+ }
96
+
97
+ const wrappedLowCardinalityType = unwrapType(type, 'LowCardinality');
98
+ if (wrappedLowCardinalityType) {
99
+ return clickhouseToTsType(wrappedLowCardinalityType);
100
+ }
101
+
102
+ const wrappedTupleType = unwrapType(type, 'Tuple');
103
+ if (wrappedTupleType) {
104
+ const tupleParts = splitTopLevelArgs(wrappedTupleType);
105
+ return `[${tupleParts.map(clickhouseToTsType).join(', ')}]`;
106
+ }
107
+
108
+ const wrappedMapType = unwrapType(type, 'Map');
109
+ if (wrappedMapType) {
110
+ const mapParts = splitTopLevelArgs(wrappedMapType);
111
+ if (mapParts.length === 2) {
112
+ const [, valueType] = mapParts;
113
+ // JSON object keys are strings even when ClickHouse map keys are numeric.
114
+ return `Record<string, ${clickhouseToTsType(valueType)}>`;
115
+ }
116
+ return 'Record<string, unknown>';
117
+ }
118
+
119
+ const primitiveType = getPrimitiveTsType(type);
120
+ if (primitiveType) return primitiveType;
121
+
122
+ // Unsupported or more complex ClickHouse types currently preserve the historical fallback.
123
+ return 'string';
124
+ };
@@ -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;
@@ -1 +1 @@
1
- {"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../../src/core/cache/cache-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AA4DnF,wBAAsB,gBAAgB,CACpC,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACvC,KAAK,SAAS,eAAe,EAE7B,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EACpC,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CA4J5B"}
1
+ {"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../../src/core/cache/cache-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AA6DnF,wBAAsB,gBAAgB,CACpC,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACvC,KAAK,SAAS,eAAe,EAE7B,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EACpC,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CA6J5B"}
@@ -8,9 +8,10 @@ function isCacheable(options) {
8
8
  return ttl > 0 || stale > 0;
9
9
  }
10
10
  function deriveTags(builder) {
11
+ const queryNode = builder.toQueryNode();
11
12
  const tags = new Set();
12
- tags.add(builder.getTableName());
13
- const joins = builder.getConfig().joins || [];
13
+ tags.add(queryNode.from?.kind === 'table' ? queryNode.from.name : builder.getTableName());
14
+ const joins = queryNode.joins || [];
14
15
  joins.forEach(join => tags.add(join.table));
15
16
  return Array.from(tags);
16
17
  }
@@ -49,11 +50,12 @@ export async function executeWithCache(builder, options) {
49
50
  const renderSql = adapter.render ? adapter.render(sql, parameters) : substituteParameters(sql, parameters);
50
51
  const tableName = builder.getTableName();
51
52
  const namespace = mergedOptions.namespace || runtime.namespace;
53
+ const queryNode = builder.toQueryNode();
52
54
  const key = mergedOptions.key || computeCacheKey({
53
55
  namespace,
54
56
  sql,
55
57
  parameters,
56
- settings: builder.getConfig().settings,
58
+ settings: queryNode.settings,
57
59
  version: runtime.versionTag,
58
60
  tableName
59
61
  });
@@ -17,20 +17,20 @@ type ClickHouseClient = NodeClickHouseClient | WebClickHouseClient;
17
17
  * // Method 1: Manual injection (required for browser environments)
18
18
  * import { createClient } from '@clickhouse/client-web';
19
19
  * const client = createClient({
20
- * host: 'http://localhost:8123',
20
+ * url: 'http://localhost:8123',
21
21
  * username: 'default',
22
22
  * password: 'password'
23
23
  * });
24
24
  *
25
25
  * ClickHouseConnection.initialize({
26
- * host: 'http://localhost:8123',
26
+ * url: 'http://localhost:8123',
27
27
  * database: 'my_database',
28
28
  * client // Explicitly provide the client
29
29
  * });
30
30
  *
31
31
  * // Method 2: Auto-detection (Node.js environments only)
32
32
  * ClickHouseConnection.initialize({
33
- * host: 'http://localhost:8123',
33
+ * url: 'http://localhost:8123',
34
34
  * username: 'default',
35
35
  * password: 'password',
36
36
  * database: 'my_database'
@@ -71,12 +71,12 @@ export declare class ClickHouseConnection {
71
71
  * ```typescript
72
72
  * // Manual injection (required for browser environments)
73
73
  * import { createClient } from '@clickhouse/client-web';
74
- * const client = createClient({ host: 'http://localhost:8123' });
75
- * ClickHouseConnection.initialize({ host: 'http://localhost:8123', client });
74
+ * const client = createClient({ url: 'http://localhost:8123' });
75
+ * ClickHouseConnection.initialize({ url: 'http://localhost:8123', client });
76
76
  *
77
77
  * // Auto-detection (Node.js environments only)
78
78
  * ClickHouseConnection.initialize({
79
- * host: 'http://localhost:8123',
79
+ * url: 'http://localhost:8123',
80
80
  * username: 'default',
81
81
  * password: 'password',
82
82
  * database: 'my_database'
@@ -21,8 +21,8 @@ function getClickHouseClientSync() {
21
21
  'Please use manual injection by providing a client instance:\n\n' +
22
22
  '```typescript\n' +
23
23
  'import { createClient } from \'@clickhouse/client-web\';\n' +
24
- 'const client = createClient({ host: \'http://localhost:8123\' });\n' +
25
- 'ClickHouseConnection.initialize({ host: \'http://localhost:8123\', client });\n' +
24
+ 'const client = createClient({ url: \'http://localhost:8123\' });\n' +
25
+ 'ClickHouseConnection.initialize({ url: \'http://localhost:8123\', client });\n' +
26
26
  '```\n\n' +
27
27
  'This is required because browser environments cannot use require() to load modules.');
28
28
  }
@@ -40,20 +40,20 @@ function getClickHouseClientSync() {
40
40
  * // Method 1: Manual injection (required for browser environments)
41
41
  * import { createClient } from '@clickhouse/client-web';
42
42
  * const client = createClient({
43
- * host: 'http://localhost:8123',
43
+ * url: 'http://localhost:8123',
44
44
  * username: 'default',
45
45
  * password: 'password'
46
46
  * });
47
47
  *
48
48
  * ClickHouseConnection.initialize({
49
- * host: 'http://localhost:8123',
49
+ * url: 'http://localhost:8123',
50
50
  * database: 'my_database',
51
51
  * client // Explicitly provide the client
52
52
  * });
53
53
  *
54
54
  * // Method 2: Auto-detection (Node.js environments only)
55
55
  * ClickHouseConnection.initialize({
56
- * host: 'http://localhost:8123',
56
+ * url: 'http://localhost:8123',
57
57
  * username: 'default',
58
58
  * password: 'password',
59
59
  * database: 'my_database'
@@ -94,12 +94,12 @@ export class ClickHouseConnection {
94
94
  * ```typescript
95
95
  * // Manual injection (required for browser environments)
96
96
  * import { createClient } from '@clickhouse/client-web';
97
- * const client = createClient({ host: 'http://localhost:8123' });
98
- * ClickHouseConnection.initialize({ host: 'http://localhost:8123', client });
97
+ * const client = createClient({ url: 'http://localhost:8123' });
98
+ * ClickHouseConnection.initialize({ url: 'http://localhost:8123', client });
99
99
  *
100
100
  * // Auto-detection (Node.js environments only)
101
101
  * ClickHouseConnection.initialize({
102
- * host: 'http://localhost:8123',
102
+ * url: 'http://localhost:8123',
103
103
  * username: 'default',
104
104
  * password: 'password',
105
105
  * database: 'my_database'
@@ -112,7 +112,7 @@ export class ClickHouseConnection {
112
112
  this.instance = config.client;
113
113
  return ClickHouseConnection;
114
114
  }
115
- // Otherwise, auto-detect the client (we know we have a host-based config)
115
+ // Otherwise, auto-detect the client using the provided ClickHouse connection config.
116
116
  this.clientModule = getClickHouseClientSync();
117
117
  this.instance = this.clientModule.createClient(config);
118
118
  return ClickHouseConnection;
@@ -114,7 +114,7 @@ export class CrossFilter {
114
114
  * Type guard to check if an item is a FilterGroup.
115
115
  */
116
116
  isGroup(item) {
117
- return typeof item.conditions !== 'undefined';
117
+ return 'conditions' in item;
118
118
  }
119
119
  /**
120
120
  * Creates a filter for top N records by a value column
@@ -1,9 +1,9 @@
1
- import type { QueryConfig } from '../../types/index.js';
1
+ import type { CompiledQuery, SelectQueryNode } from '../../types/index.js';
2
2
  import type { CompileQueryContext, SqlDialect } from './sql-dialect.js';
3
3
  export declare class ClickHouseDialect implements SqlDialect {
4
4
  readonly name = "clickhouse";
5
5
  private formatter;
6
- compileQuery(config: QueryConfig<any, any>, context: CompileQueryContext): string;
6
+ compileQuery(query: SelectQueryNode<any, any>, context: CompileQueryContext): CompiledQuery;
7
7
  formatTimeInterval(column: string, interval: string, method: string): string;
8
8
  formatSettings(settings: Record<string, unknown>): string;
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/clickhouse-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,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,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,MAAM;IAyCjF,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;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"}
@@ -2,36 +2,53 @@ import { SQLFormatter } from '../formatters/sql-formatter.js';
2
2
  export class ClickHouseDialect {
3
3
  name = 'clickhouse';
4
4
  formatter = new SQLFormatter();
5
- compileQuery(config, context) {
5
+ compileQuery(query, context) {
6
6
  const parts = [];
7
- if (config.ctes?.length) {
8
- parts.push(`WITH ${config.ctes.join(', ')}`);
7
+ const parameters = [];
8
+ if (query.ctes?.length) {
9
+ parts.push(`WITH ${this.formatter.formatCtes(query)}`);
9
10
  }
10
- parts.push(`SELECT ${this.formatter.formatSelect(config)}`);
11
- parts.push(`FROM ${context.tableName}`);
12
- if (config.joins?.length) {
13
- parts.push(this.formatter.formatJoins(config));
11
+ parts.push(`SELECT ${this.formatter.formatSelect(query)}`);
12
+ parts.push(`FROM ${this.formatter.formatFrom(query.from ?? { kind: 'table', name: context.tableName })}`);
13
+ if (query.arrayJoins?.length) {
14
+ parts.push(this.formatter.formatArrayJoins(query));
14
15
  }
15
- if (config.where?.length) {
16
- parts.push(`WHERE ${this.formatter.formatWhere(config)}`);
16
+ if (query.joins?.length) {
17
+ parts.push(this.formatter.formatJoins(query));
17
18
  }
18
- if (config.groupBy?.length) {
19
- parts.push(`GROUP BY ${this.formatter.formatGroupBy(config)}`);
19
+ if (query.prewhere) {
20
+ const compiled = this.formatter.compileExpr(query.prewhere);
21
+ parts.push(`PREWHERE ${compiled.query}`);
22
+ parameters.push(...compiled.parameters);
20
23
  }
21
- if (config.having?.length) {
22
- parts.push(`HAVING ${config.having.join(' AND ')}`);
24
+ if (query.where) {
25
+ const compiled = this.formatter.compileExpr(query.where);
26
+ parts.push(`WHERE ${compiled.query}`);
27
+ parameters.push(...compiled.parameters);
23
28
  }
24
- if (config.orderBy?.length) {
25
- const orderBy = config.orderBy
26
- .map(({ column, direction }) => `${String(column)} ${direction}`.trim())
27
- .join(', ');
28
- parts.push(`ORDER BY ${orderBy}`);
29
+ if (query.groupBy?.length) {
30
+ const groupByClause = `GROUP BY ${this.formatter.formatGroupBy(query)}`;
31
+ parts.push(query.withTotals ? `${groupByClause} WITH TOTALS` : groupByClause);
29
32
  }
30
- if (config.limit) {
31
- const offsetClause = config.offset ? `OFFSET ${config.offset}` : '';
32
- parts.push(`LIMIT ${config.limit} ${offsetClause}`);
33
+ if (query.having?.length) {
34
+ const compiled = this.formatter.compileHaving(query);
35
+ parts.push(`HAVING ${compiled.query}`);
36
+ parameters.push(...compiled.parameters);
33
37
  }
34
- return parts.join(' ').trim();
38
+ if (query.orderBy?.length) {
39
+ parts.push(`ORDER BY ${this.formatter.formatOrderBy(query)}`);
40
+ }
41
+ if (query.limitBy) {
42
+ parts.push(`LIMIT ${this.formatter.formatLimitBy(query)}`);
43
+ }
44
+ if (query.limit) {
45
+ const offsetClause = query.offset ? `OFFSET ${query.offset}` : '';
46
+ parts.push(`LIMIT ${query.limit} ${offsetClause}`);
47
+ }
48
+ return {
49
+ query: parts.join(' ').trim(),
50
+ parameters,
51
+ };
35
52
  }
36
53
  formatTimeInterval(column, interval, method) {
37
54
  if (method === 'toStartOfInterval') {
@@ -1,10 +1,10 @@
1
- import type { QueryConfig } from '../../types/index.js';
1
+ import type { CompiledQuery, SelectQueryNode } from '../../types/index.js';
2
2
  export interface CompileQueryContext {
3
3
  tableName: string;
4
4
  }
5
5
  export interface SqlDialect {
6
6
  readonly name: string;
7
- compileQuery(config: QueryConfig<any, any>, context: CompileQueryContext): string;
7
+ compileQuery(query: SelectQueryNode<any, any>, context: CompileQueryContext): CompiledQuery;
8
8
  formatTimeInterval(column: string, interval: string, method: string): string;
9
9
  formatSettings(settings: Record<string, unknown>): string;
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sql-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/sql-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAAC;IAClF,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAAC;IACV,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CAC3D"}
1
+ {"version":3,"file":"sql-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/sql-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa,CAAC;IAC5F,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAAC;IACV,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CAC3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"auto-client.d.ts","sourceRoot":"","sources":["../../../src/core/env/auto-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,KAAK,gBAAgB,GAAG,cAAc,oBAAoB,CAAC,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAID,wBAAgB,mBAAmB,IAAI,gBAAgB,CAqBtD"}
1
+ {"version":3,"file":"auto-client.d.ts","sourceRoot":"","sources":["../../../src/core/env/auto-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,KAAK,gBAAgB,GAAG,cAAc,oBAAoB,CAAC,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAKD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAoBtD"}
@@ -1,9 +1,9 @@
1
1
  import { createRequire } from 'module';
2
2
  let cachedModule;
3
+ const nodeRequire = createRequire(import.meta.url);
3
4
  export function getAutoClientModule() {
4
5
  if (!cachedModule) {
5
6
  try {
6
- const nodeRequire = createRequire(`${process.cwd()}/noop.js`);
7
7
  const clientModule = nodeRequire('@clickhouse/client');
8
8
  const settings = clientModule.ClickHouseSettings;
9
9
  cachedModule = {
@@ -1,98 +1,15 @@
1
1
  import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
2
2
  import { QueryBuilder } from '../query-builder.js';
3
+ import type { SelectQueryNode } from '../../types/index.js';
3
4
  export declare class AggregationFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
4
5
  private builder;
5
6
  constructor(builder: QueryBuilder<Schema, State>);
7
+ private inferGroupBySelections;
6
8
  private createAggregation;
7
- sum(column: string, alias: string): {
8
- select: string[];
9
- where?: import("../../types/base.js").WhereCondition[];
10
- groupBy?: string[];
11
- having?: string[];
12
- limit?: number;
13
- offset?: number;
14
- distinct?: boolean;
15
- orderBy?: {
16
- column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
17
- direction: import("../../index.js").OrderDirection;
18
- }[] | undefined;
19
- joins?: import("../../types/base.js").JoinClause[];
20
- parameters?: any[];
21
- ctes?: string[];
22
- unionQueries?: string[];
23
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
24
- };
25
- count(column: string, alias: string): {
26
- select: string[];
27
- where?: import("../../types/base.js").WhereCondition[];
28
- groupBy?: string[];
29
- having?: string[];
30
- limit?: number;
31
- offset?: number;
32
- distinct?: boolean;
33
- orderBy?: {
34
- column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
35
- direction: import("../../index.js").OrderDirection;
36
- }[] | undefined;
37
- joins?: import("../../types/base.js").JoinClause[];
38
- parameters?: any[];
39
- ctes?: string[];
40
- unionQueries?: string[];
41
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
42
- };
43
- avg(column: string, alias: string): {
44
- select: string[];
45
- where?: import("../../types/base.js").WhereCondition[];
46
- groupBy?: string[];
47
- having?: string[];
48
- limit?: number;
49
- offset?: number;
50
- distinct?: boolean;
51
- orderBy?: {
52
- column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
53
- direction: import("../../index.js").OrderDirection;
54
- }[] | undefined;
55
- joins?: import("../../types/base.js").JoinClause[];
56
- parameters?: any[];
57
- ctes?: string[];
58
- unionQueries?: string[];
59
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
60
- };
61
- min(column: string, alias: string): {
62
- select: string[];
63
- where?: import("../../types/base.js").WhereCondition[];
64
- groupBy?: string[];
65
- having?: string[];
66
- limit?: number;
67
- offset?: number;
68
- distinct?: boolean;
69
- orderBy?: {
70
- column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
71
- direction: import("../../index.js").OrderDirection;
72
- }[] | undefined;
73
- joins?: import("../../types/base.js").JoinClause[];
74
- parameters?: any[];
75
- ctes?: string[];
76
- unionQueries?: string[];
77
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
78
- };
79
- max(column: string, alias: string): {
80
- select: string[];
81
- where?: import("../../types/base.js").WhereCondition[];
82
- groupBy?: string[];
83
- having?: string[];
84
- limit?: number;
85
- offset?: number;
86
- distinct?: boolean;
87
- orderBy?: {
88
- column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
89
- direction: import("../../index.js").OrderDirection;
90
- }[] | undefined;
91
- joins?: import("../../types/base.js").JoinClause[];
92
- parameters?: any[];
93
- ctes?: string[];
94
- unionQueries?: string[];
95
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
96
- };
9
+ sum(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
10
+ count(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
11
+ avg(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
12
+ min(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
13
+ max(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
97
14
  }
98
15
  //# sourceMappingURL=aggregations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aggregations.d.ts","sourceRoot":"","sources":["../../../src/core/features/aggregations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,qBAAa,kBAAkB,CAC7B,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACvC,KAAK,SAAS,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,CAAC,CAAC;IAExF,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,OAAO,CAAC,iBAAiB;IAsBzB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;IAIjC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;IAInC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;IAIjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;IAIjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;CAGlC"}
1
+ {"version":3,"file":"aggregations.d.ts","sourceRoot":"","sources":["../../../src/core/features/aggregations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,qBAAa,kBAAkB,CAC7B,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACvC,KAAK,SAAS,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,CAAC,CAAC;IAExF,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,iBAAiB;IAsBzB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAInC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAGlC"}