@hypequery/clickhouse 0.2.1 → 0.2.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-CLI.md +1 -1
- package/dist/cli/bin.js +129 -37
- package/dist/cli/generate-types.js +104 -15
- package/dist/core/connection.d.ts +112 -0
- package/dist/core/connection.d.ts.map +1 -1
- package/dist/core/connection.js +148 -25
- package/dist/core/cross-filter.d.ts +69 -0
- package/dist/core/cross-filter.d.ts.map +1 -1
- package/dist/core/cross-filter.js +1 -83
- package/dist/core/features/aggregations.d.ts +102 -0
- package/dist/core/features/analytics.d.ts +66 -0
- package/dist/core/features/analytics.d.ts.map +1 -1
- package/dist/core/features/cross-filtering.d.ts +31 -0
- package/dist/core/features/cross-filtering.d.ts.map +1 -0
- package/dist/core/features/cross-filtering.js +123 -0
- package/dist/core/features/executor.d.ts +19 -0
- package/dist/core/features/executor.js +3 -3
- package/dist/core/features/filtering.d.ts +95 -0
- package/dist/core/features/filtering.d.ts.map +1 -1
- package/dist/core/features/filtering.js +89 -3
- package/dist/core/features/joins.d.ts +29 -0
- package/dist/core/features/pagination.d.ts +23 -0
- package/dist/core/features/query-modifiers.d.ts +119 -0
- package/dist/core/formatters/sql-formatter.d.ts +9 -0
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.js +61 -5
- package/dist/core/join-relationships.d.ts +50 -0
- package/dist/core/join-relationships.d.ts.map +1 -1
- package/dist/core/query-builder.d.ts +258 -0
- package/dist/core/query-builder.d.ts.map +1 -1
- package/dist/core/query-builder.js +88 -27
- package/dist/core/tests/index.d.ts +2 -0
- package/dist/core/tests/integration/pagination-test-tbc.d.ts +2 -0
- package/dist/core/tests/integration/pagination-test-tbc.d.ts.map +1 -0
- package/dist/core/tests/integration/pagination-test-tbc.js +189 -0
- package/dist/core/tests/integration/setup.d.ts +40 -0
- package/dist/core/tests/integration/setup.d.ts.map +1 -1
- package/dist/core/tests/integration/setup.js +279 -238
- package/dist/core/tests/integration/test-config.d.ts +15 -0
- package/dist/core/tests/integration/test-config.d.ts.map +1 -0
- package/dist/core/tests/integration/test-config.js +15 -0
- package/dist/core/tests/integration/test-initializer.d.ts +7 -0
- package/dist/core/tests/integration/test-initializer.d.ts.map +1 -0
- package/dist/core/tests/integration/test-initializer.js +32 -0
- package/dist/core/tests/test-utils.d.ts +29 -0
- package/dist/core/tests/test-utils.d.ts.map +1 -1
- package/dist/core/tests/test-utils.js +6 -2
- package/dist/core/utils/logger.d.ts +37 -0
- package/dist/core/utils/logger.js +6 -6
- package/dist/core/utils/sql-expressions.d.ts +63 -0
- package/dist/core/utils/sql-expressions.d.ts.map +1 -1
- package/dist/core/utils/sql-expressions.js +9 -5
- package/dist/core/utils.d.ts +3 -0
- package/dist/core/validators/filter-validator.d.ts +8 -0
- package/dist/core/validators/filter-validator.js +1 -1
- package/dist/core/validators/value-validator.d.ts +6 -0
- package/dist/formatters/index.d.ts +1 -0
- package/dist/index.d.ts +12 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/types/base.d.ts +77 -0
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/clickhouse-types.d.ts +13 -0
- package/dist/types/clickhouse-types.d.ts.map +1 -1
- package/dist/types/filters.d.ts +53 -0
- package/dist/types/filters.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/package.json +36 -13
- package/README.md +0 -276
package/dist/core/connection.js
CHANGED
|
@@ -1,34 +1,157 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isClientConfig } from './query-builder.js';
|
|
2
|
+
// Function to synchronously get the appropriate client
|
|
3
|
+
function getClickHouseClientSync() {
|
|
4
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
5
|
+
const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
|
|
6
|
+
// In Node.js environment, use Node.js client only
|
|
7
|
+
if (isNode) {
|
|
8
|
+
try {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
10
|
+
const clientNode = require('@clickhouse/client');
|
|
11
|
+
if (isDev) {
|
|
12
|
+
console.log('hypequery: Using @clickhouse/client for Node.js environment');
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
createClient: clientNode.createClient,
|
|
16
|
+
ClickHouseSettings: clientNode.ClickHouseSettings || {}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw new Error('@clickhouse/client is required for Node.js environments.\n\n' +
|
|
21
|
+
'Install with: npm install @clickhouse/client\n\n' +
|
|
22
|
+
'Alternatively, you can provide a client instance directly in the config.client option.');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// For browser environments, require() doesn't work, so we can't auto-detect
|
|
26
|
+
// Users must use manual injection in browser environments
|
|
27
|
+
throw new Error('Unable to auto-detect ClickHouse client in browser environment. ' +
|
|
28
|
+
'Please use manual injection by providing a client instance:\n\n' +
|
|
29
|
+
'```typescript\n' +
|
|
30
|
+
'import { createClient } from \'@clickhouse/client-web\';\n' +
|
|
31
|
+
'const client = createClient({ host: \'http://localhost:8123\' });\n' +
|
|
32
|
+
'ClickHouseConnection.initialize({ host: \'http://localhost:8123\', client });\n' +
|
|
33
|
+
'```\n\n' +
|
|
34
|
+
'This is required because browser environments cannot use require() to load modules.');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The main entry point for connecting to a ClickHouse database.
|
|
38
|
+
* Provides static methods to initialize the connection and retrieve the client.
|
|
39
|
+
*
|
|
40
|
+
* Supports two modes of operation:
|
|
41
|
+
* 1. **Manual injection**: Provide a client instance via `config.client` (required for browser environments)
|
|
42
|
+
* 2. **Auto-detection**: Automatically uses @clickhouse/client for Node.js environments
|
|
43
|
+
*
|
|
44
|
+
* @category Core
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* // Method 1: Manual injection (required for browser environments)
|
|
48
|
+
* import { createClient } from '@clickhouse/client-web';
|
|
49
|
+
* const client = createClient({
|
|
50
|
+
* host: 'http://localhost:8123',
|
|
51
|
+
* username: 'default',
|
|
52
|
+
* password: 'password'
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* ClickHouseConnection.initialize({
|
|
56
|
+
* host: 'http://localhost:8123',
|
|
57
|
+
* database: 'my_database',
|
|
58
|
+
* client // Explicitly provide the client
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* // Method 2: Auto-detection (Node.js environments only)
|
|
62
|
+
* ClickHouseConnection.initialize({
|
|
63
|
+
* host: 'http://localhost:8123',
|
|
64
|
+
* username: 'default',
|
|
65
|
+
* password: 'password',
|
|
66
|
+
* database: 'my_database'
|
|
67
|
+
* });
|
|
68
|
+
*
|
|
69
|
+
* // Get the client to execute queries directly
|
|
70
|
+
* const client = ClickHouseConnection.getClient();
|
|
71
|
+
* const result = await client.query({
|
|
72
|
+
* query: 'SELECT * FROM my_table',
|
|
73
|
+
* format: 'JSONEachRow'
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @note This library requires one of the following peer dependencies:
|
|
78
|
+
* - @clickhouse/client (for Node.js environments)
|
|
79
|
+
* - @clickhouse/client-web (for browser environments)
|
|
80
|
+
*
|
|
81
|
+
* **Important**: Browser environments require manual injection because `require()` calls don't work in browsers.
|
|
82
|
+
*/
|
|
2
83
|
export class ClickHouseConnection {
|
|
84
|
+
/**
|
|
85
|
+
* Initializes the ClickHouse connection with the provided configuration.
|
|
86
|
+
* This method must be called before any queries can be executed.
|
|
87
|
+
*
|
|
88
|
+
* **Priority order:**
|
|
89
|
+
* 1. If `config.client` is provided, use it directly (manual injection)
|
|
90
|
+
* 2. Otherwise, auto-detect @clickhouse/client for Node.js environments
|
|
91
|
+
*
|
|
92
|
+
* **Note**: Browser environments require manual injection because `require()` calls don't work in browsers.
|
|
93
|
+
*
|
|
94
|
+
* @param config - The connection configuration options
|
|
95
|
+
* @returns The ClickHouseConnection class for method chaining
|
|
96
|
+
* @throws Will throw an error if no ClickHouse client is available
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* // Manual injection (required for browser environments)
|
|
101
|
+
* import { createClient } from '@clickhouse/client-web';
|
|
102
|
+
* const client = createClient({ host: 'http://localhost:8123' });
|
|
103
|
+
* ClickHouseConnection.initialize({ host: 'http://localhost:8123', client });
|
|
104
|
+
*
|
|
105
|
+
* // Auto-detection (Node.js environments only)
|
|
106
|
+
* ClickHouseConnection.initialize({
|
|
107
|
+
* host: 'http://localhost:8123',
|
|
108
|
+
* username: 'default',
|
|
109
|
+
* password: 'password',
|
|
110
|
+
* database: 'my_database'
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
3
114
|
static initialize(config) {
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
clientConfig.http_headers = config.http_headers;
|
|
14
|
-
if (config.request_timeout)
|
|
15
|
-
clientConfig.request_timeout = config.request_timeout;
|
|
16
|
-
if (config.compression)
|
|
17
|
-
clientConfig.compression = config.compression;
|
|
18
|
-
if (config.application)
|
|
19
|
-
clientConfig.application = config.application;
|
|
20
|
-
if (config.keep_alive)
|
|
21
|
-
clientConfig.keep_alive = config.keep_alive;
|
|
22
|
-
if (config.log)
|
|
23
|
-
clientConfig.log = config.log;
|
|
24
|
-
if (config.clickhouse_settings)
|
|
25
|
-
clientConfig.clickhouse_settings = config.clickhouse_settings;
|
|
26
|
-
this.instance = createClient(clientConfig);
|
|
115
|
+
// If a client is explicitly provided, use it directly
|
|
116
|
+
if (isClientConfig(config)) {
|
|
117
|
+
this.instance = config.client;
|
|
118
|
+
return ClickHouseConnection;
|
|
119
|
+
}
|
|
120
|
+
// Otherwise, auto-detect the client (we know we have a host-based config)
|
|
121
|
+
this.clientModule = getClickHouseClientSync();
|
|
122
|
+
this.instance = this.clientModule.createClient(config);
|
|
123
|
+
return ClickHouseConnection;
|
|
27
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Retrieves the ClickHouse client instance for direct query execution.
|
|
127
|
+
*
|
|
128
|
+
* @returns The ClickHouse client instance
|
|
129
|
+
* @throws Will throw an error if the connection has not been initialized
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* const client = ClickHouseConnection.getClient();
|
|
134
|
+
* const result = await client.query({
|
|
135
|
+
* query: 'SELECT * FROM my_table',
|
|
136
|
+
* format: 'JSONEachRow'
|
|
137
|
+
* });
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
28
140
|
static getClient() {
|
|
29
141
|
if (!this.instance) {
|
|
30
|
-
throw new Error('ClickHouse connection not initialized');
|
|
142
|
+
throw new Error('ClickHouse connection not initialized. Call ClickHouseConnection.initialize() first.');
|
|
31
143
|
}
|
|
32
144
|
return this.instance;
|
|
33
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Gets the ClickHouseSettings type from the loaded client module.
|
|
148
|
+
* Only available when using auto-detection (not manual injection).
|
|
149
|
+
*
|
|
150
|
+
* @returns The ClickHouseSettings type or an empty object if not available
|
|
151
|
+
*/
|
|
152
|
+
static getClickHouseSettings() {
|
|
153
|
+
return this.clientModule?.ClickHouseSettings || {};
|
|
154
|
+
}
|
|
34
155
|
}
|
|
156
|
+
ClickHouseConnection.instance = null;
|
|
157
|
+
ClickHouseConnection.clientModule = null;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ColumnType, FilterOperator, InferColumnType, OperatorValueMap, FilterConditionInput } from '../types';
|
|
2
|
+
export interface FilterGroup<Schema extends Record<string, Record<string, any>> = any, OriginalT extends Record<string, any> = any> {
|
|
3
|
+
operator: 'AND' | 'OR';
|
|
4
|
+
conditions: Array<FilterConditionInput<any, Schema, OriginalT> | FilterGroup<Schema, OriginalT>>;
|
|
5
|
+
limit?: number;
|
|
6
|
+
orderBy?: {
|
|
7
|
+
column: keyof OriginalT;
|
|
8
|
+
direction: 'ASC' | 'DESC';
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A type-safe filter builder supporting both simple conditions and complex nested groups.
|
|
13
|
+
* @template Schema - The full database schema type
|
|
14
|
+
* @template TableName - The specific table being filtered
|
|
15
|
+
*/
|
|
16
|
+
export declare class CrossFilter<Schema extends {
|
|
17
|
+
[tableName: string]: {
|
|
18
|
+
[columnName: string]: ColumnType;
|
|
19
|
+
};
|
|
20
|
+
} = any, TableName extends keyof Schema = Extract<keyof Schema, string>> {
|
|
21
|
+
private schema?;
|
|
22
|
+
private rootGroup;
|
|
23
|
+
constructor(schema?: Schema | undefined);
|
|
24
|
+
/**
|
|
25
|
+
* Adds a single filter condition to the root group with an implicit AND conjunction.
|
|
26
|
+
* Performs type-safe validation if a schema is provided.
|
|
27
|
+
*/
|
|
28
|
+
add<ColumnName extends Extract<keyof Schema[TableName], string>, Op extends FilterOperator>(condition: FilterConditionInput<OperatorValueMap<InferColumnType<Schema[TableName][ColumnName]>>[Op], Schema, Schema[TableName]>): this;
|
|
29
|
+
/**
|
|
30
|
+
* Adds multiple filter conditions to the root group.
|
|
31
|
+
*/
|
|
32
|
+
addMultiple(conditions: Array<FilterConditionInput<any, Schema, Schema[TableName]>>): this;
|
|
33
|
+
/**
|
|
34
|
+
* Adds a nested group of filter conditions to the root group using the specified logical operator.
|
|
35
|
+
* @param groupConditions - Array of filter conditions or nested groups to be grouped together.
|
|
36
|
+
* @param operator - Logical operator ('AND' or 'OR') to combine the conditions in the group.
|
|
37
|
+
*/
|
|
38
|
+
addGroup(groupConditions: Array<FilterConditionInput<any, Schema, Schema[TableName]> | FilterGroup<Schema, Schema[TableName]>>, operator: 'AND' | 'OR'): this;
|
|
39
|
+
/**
|
|
40
|
+
* Returns the current filter tree representing all conditions and groups.
|
|
41
|
+
*/
|
|
42
|
+
getConditions(): FilterGroup<Schema, Schema[TableName]>;
|
|
43
|
+
/**
|
|
44
|
+
* Looks up a column's type from the schema.
|
|
45
|
+
* Defaults to 'String' if no schema is provided.
|
|
46
|
+
* @param column - The column name as a string.
|
|
47
|
+
*/
|
|
48
|
+
private getColumnType;
|
|
49
|
+
/**
|
|
50
|
+
* Validates the value of a filter condition against its expected column type.
|
|
51
|
+
*/
|
|
52
|
+
private validateValueType;
|
|
53
|
+
/**
|
|
54
|
+
* Recursively validates an array of filter conditions and nested groups.
|
|
55
|
+
*/
|
|
56
|
+
private validateGroup;
|
|
57
|
+
/**
|
|
58
|
+
* Type guard to check if an item is a FilterGroup.
|
|
59
|
+
*/
|
|
60
|
+
private isGroup;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a filter for top N records by a value column
|
|
63
|
+
* @param valueColumn - The column to filter and order by
|
|
64
|
+
* @param n - Number of records to return
|
|
65
|
+
* @param orderBy - Sort direction, defaults to 'desc'
|
|
66
|
+
*/
|
|
67
|
+
topN<K extends keyof Schema[TableName]>(valueColumn: K, n: number, orderBy?: 'desc' | 'asc'): this;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=cross-filter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-filter.d.ts","sourceRoot":"","sources":["../../src/core/cross-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAIlB,MAAM,WAAW,WAAW,CAC1B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,EACxD,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG;IAE3C,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,KAAK,CACf,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAC9E,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,SAAS,CAAC;QACxB,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;KAC3B,CAAC;CACH;AAED
|
|
1
|
+
{"version":3,"file":"cross-filter.d.ts","sourceRoot":"","sources":["../../src/core/cross-filter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAIlB,MAAM,WAAW,WAAW,CAC1B,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,EACxD,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG;IAE3C,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,KAAK,CACf,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAC9E,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,SAAS,CAAC;QACxB,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;KAC3B,CAAC;CACH;AAED;;;;GAIG;AACH,qBAAa,WAAW,CACtB,MAAM,SAAS;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAA;CAAE,GAAG,GAAG,EAClF,SAAS,SAAS,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,MAAM,EAAE,MAAM,CAAC;IAMlD,OAAO,CAAC,MAAM,CAAC;IAH3B,OAAO,CAAC,SAAS,CAAyC;gBAGtC,MAAM,CAAC,EAAE,MAAM,YAAA;IAInC;;;OAGG;IACH,GAAG,CACD,UAAU,SAAS,OAAO,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,EAC3D,EAAE,SAAS,cAAc,EAEzB,SAAS,EAAE,oBAAoB,CAC7B,gBAAgB,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACpE,MAAM,EACN,MAAM,CAAC,SAAS,CAAC,CAClB,GACA,IAAI;IA0BP;;OAEG;IACH,WAAW,CACT,UAAU,EAAE,KAAK,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GACtE,IAAI;IAQP;;;;OAIG;IACH,QAAQ,CACN,eAAe,EAAE,KAAK,CACpB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAC9F,EACD,QAAQ,EAAE,KAAK,GAAG,IAAI,GACrB,IAAI;IAYP;;OAEG;IACH,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAIvD;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;IACH,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,OAAO,CAAC,OAAO;IAMf;;;;;OAKG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,CAAC,SAAS,CAAC,EACpC,WAAW,EAAE,CAAC,EACd,CAAC,EAAE,MAAM,EACT,OAAO,GAAE,MAAM,GAAG,KAAc,GAC/B,IAAI;CAmBR"}
|
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
import { FilterValidator } from './validators/filter-validator';
|
|
2
|
-
export const DateRange = {
|
|
3
|
-
TODAY: 'today',
|
|
4
|
-
YESTERDAY: 'yesterday',
|
|
5
|
-
LAST_7_DAYS: 'last_7_days',
|
|
6
|
-
LAST_30_DAYS: 'last_30_days',
|
|
7
|
-
THIS_MONTH: 'this_month',
|
|
8
|
-
LAST_MONTH: 'last_month',
|
|
9
|
-
THIS_QUARTER: 'this_quarter',
|
|
10
|
-
YEAR_TO_DATE: 'year_to_date'
|
|
11
|
-
};
|
|
1
|
+
import { FilterValidator } from './validators/filter-validator.js';
|
|
12
2
|
/**
|
|
13
3
|
* A type-safe filter builder supporting both simple conditions and complex nested groups.
|
|
14
4
|
* @template Schema - The full database schema type
|
|
@@ -120,78 +110,6 @@ export class CrossFilter {
|
|
|
120
110
|
isGroup(item) {
|
|
121
111
|
return typeof item.conditions !== 'undefined';
|
|
122
112
|
}
|
|
123
|
-
addDateCondition(column, value) {
|
|
124
|
-
this.rootGroup.conditions.push({
|
|
125
|
-
column,
|
|
126
|
-
operator: 'between',
|
|
127
|
-
value: [value[0].toISOString(), value[1].toISOString()]
|
|
128
|
-
});
|
|
129
|
-
return this;
|
|
130
|
-
}
|
|
131
|
-
addDateRange(column, range) {
|
|
132
|
-
const now = new Date();
|
|
133
|
-
let start;
|
|
134
|
-
let end;
|
|
135
|
-
switch (range) {
|
|
136
|
-
case 'today':
|
|
137
|
-
start = new Date(now.setHours(0, 0, 0, 0));
|
|
138
|
-
end = new Date(now.setHours(23, 59, 59, 999));
|
|
139
|
-
break;
|
|
140
|
-
case 'yesterday':
|
|
141
|
-
start = new Date(now.setDate(now.getDate() - 1));
|
|
142
|
-
start.setHours(0, 0, 0, 0);
|
|
143
|
-
end = new Date(start);
|
|
144
|
-
end.setHours(23, 59, 59, 999);
|
|
145
|
-
break;
|
|
146
|
-
case 'last_7_days':
|
|
147
|
-
end = new Date(now);
|
|
148
|
-
start = new Date(now.setDate(now.getDate() - 7));
|
|
149
|
-
break;
|
|
150
|
-
case 'last_30_days':
|
|
151
|
-
end = new Date(now);
|
|
152
|
-
start = new Date(now.setDate(now.getDate() - 30));
|
|
153
|
-
break;
|
|
154
|
-
case 'this_month':
|
|
155
|
-
start = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
156
|
-
end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
|
157
|
-
break;
|
|
158
|
-
case 'last_month':
|
|
159
|
-
start = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
|
160
|
-
end = new Date(now.getFullYear(), now.getMonth(), 0);
|
|
161
|
-
break;
|
|
162
|
-
case 'this_quarter':
|
|
163
|
-
const quarter = Math.floor(now.getMonth() / 3);
|
|
164
|
-
start = new Date(now.getFullYear(), quarter * 3, 1);
|
|
165
|
-
end = new Date(now.getFullYear(), (quarter + 1) * 3, 0);
|
|
166
|
-
break;
|
|
167
|
-
case 'year_to_date':
|
|
168
|
-
start = new Date(now.getFullYear(), 0, 1);
|
|
169
|
-
end = new Date(now);
|
|
170
|
-
break;
|
|
171
|
-
default:
|
|
172
|
-
throw new Error(`Unsupported date range: ${range}`);
|
|
173
|
-
}
|
|
174
|
-
return this.addDateCondition(column, [start, end]);
|
|
175
|
-
}
|
|
176
|
-
lastNDays(column, days) {
|
|
177
|
-
const end = new Date();
|
|
178
|
-
const start = new Date();
|
|
179
|
-
start.setDate(start.getDate() - days);
|
|
180
|
-
return this.addDateCondition(column, [start, end]);
|
|
181
|
-
}
|
|
182
|
-
addComparisonPeriod(column, currentRange) {
|
|
183
|
-
const periodLength = currentRange[1].getTime() - currentRange[0].getTime();
|
|
184
|
-
const previousStart = new Date(currentRange[0].getTime() - periodLength);
|
|
185
|
-
const previousEnd = new Date(currentRange[1].getTime() - periodLength);
|
|
186
|
-
return this.addDateCondition(column, [previousStart, previousEnd]);
|
|
187
|
-
}
|
|
188
|
-
addYearOverYear(column, currentRange) {
|
|
189
|
-
const previousStart = new Date(currentRange[0]);
|
|
190
|
-
previousStart.setFullYear(previousStart.getFullYear() - 1);
|
|
191
|
-
const previousEnd = new Date(currentRange[1]);
|
|
192
|
-
previousEnd.setFullYear(previousEnd.getFullYear() - 1);
|
|
193
|
-
return this.addDateCondition(column, [previousStart, previousEnd]);
|
|
194
|
-
}
|
|
195
113
|
/**
|
|
196
114
|
* Creates a filter for top N records by a value column
|
|
197
115
|
* @param valueColumn - The column to filter and order by
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { QueryBuilder } from '../query-builder';
|
|
2
|
+
import { ColumnType } from '../../types';
|
|
3
|
+
export declare class AggregationFeature<Schema extends {
|
|
4
|
+
[tableName: string]: {
|
|
5
|
+
[columnName: string]: ColumnType;
|
|
6
|
+
};
|
|
7
|
+
}, T, HasSelect extends boolean = false, Aggregations = {}, OriginalT = T> {
|
|
8
|
+
private builder;
|
|
9
|
+
constructor(builder: QueryBuilder<Schema, T, HasSelect, Aggregations, OriginalT>);
|
|
10
|
+
private createAggregation;
|
|
11
|
+
sum<Column extends keyof OriginalT, Alias extends string = `${Column & string}_sum`>(column: Column, alias?: Alias): {
|
|
12
|
+
select: string[];
|
|
13
|
+
where?: import("../../types").WhereCondition[];
|
|
14
|
+
groupBy?: string[];
|
|
15
|
+
having?: string[];
|
|
16
|
+
limit?: number;
|
|
17
|
+
offset?: number;
|
|
18
|
+
distinct?: boolean;
|
|
19
|
+
orderBy?: {
|
|
20
|
+
column: keyof T | import("../../types").TableColumn<Schema>;
|
|
21
|
+
direction: import("../../types").OrderDirection;
|
|
22
|
+
}[] | undefined;
|
|
23
|
+
joins?: import("../../types").JoinClause[];
|
|
24
|
+
parameters?: any[];
|
|
25
|
+
ctes?: string[];
|
|
26
|
+
unionQueries?: string[];
|
|
27
|
+
settings?: string;
|
|
28
|
+
};
|
|
29
|
+
count<Column extends keyof OriginalT, Alias extends string = `${Column & string}_count`>(column: Column, alias?: Alias): {
|
|
30
|
+
select: string[];
|
|
31
|
+
where?: import("../../types").WhereCondition[];
|
|
32
|
+
groupBy?: string[];
|
|
33
|
+
having?: string[];
|
|
34
|
+
limit?: number;
|
|
35
|
+
offset?: number;
|
|
36
|
+
distinct?: boolean;
|
|
37
|
+
orderBy?: {
|
|
38
|
+
column: keyof T | import("../../types").TableColumn<Schema>;
|
|
39
|
+
direction: import("../../types").OrderDirection;
|
|
40
|
+
}[] | undefined;
|
|
41
|
+
joins?: import("../../types").JoinClause[];
|
|
42
|
+
parameters?: any[];
|
|
43
|
+
ctes?: string[];
|
|
44
|
+
unionQueries?: string[];
|
|
45
|
+
settings?: string;
|
|
46
|
+
};
|
|
47
|
+
avg<Column extends keyof OriginalT, Alias extends string = `${Column & string}_avg`>(column: Column, alias?: Alias): {
|
|
48
|
+
select: string[];
|
|
49
|
+
where?: import("../../types").WhereCondition[];
|
|
50
|
+
groupBy?: string[];
|
|
51
|
+
having?: string[];
|
|
52
|
+
limit?: number;
|
|
53
|
+
offset?: number;
|
|
54
|
+
distinct?: boolean;
|
|
55
|
+
orderBy?: {
|
|
56
|
+
column: keyof T | import("../../types").TableColumn<Schema>;
|
|
57
|
+
direction: import("../../types").OrderDirection;
|
|
58
|
+
}[] | undefined;
|
|
59
|
+
joins?: import("../../types").JoinClause[];
|
|
60
|
+
parameters?: any[];
|
|
61
|
+
ctes?: string[];
|
|
62
|
+
unionQueries?: string[];
|
|
63
|
+
settings?: string;
|
|
64
|
+
};
|
|
65
|
+
min<Column extends keyof OriginalT, Alias extends string = `${Column & string}_min`>(column: Column, alias?: Alias): {
|
|
66
|
+
select: string[];
|
|
67
|
+
where?: import("../../types").WhereCondition[];
|
|
68
|
+
groupBy?: string[];
|
|
69
|
+
having?: string[];
|
|
70
|
+
limit?: number;
|
|
71
|
+
offset?: number;
|
|
72
|
+
distinct?: boolean;
|
|
73
|
+
orderBy?: {
|
|
74
|
+
column: keyof T | import("../../types").TableColumn<Schema>;
|
|
75
|
+
direction: import("../../types").OrderDirection;
|
|
76
|
+
}[] | undefined;
|
|
77
|
+
joins?: import("../../types").JoinClause[];
|
|
78
|
+
parameters?: any[];
|
|
79
|
+
ctes?: string[];
|
|
80
|
+
unionQueries?: string[];
|
|
81
|
+
settings?: string;
|
|
82
|
+
};
|
|
83
|
+
max<Column extends keyof OriginalT, Alias extends string = `${Column & string}_max`>(column: Column, alias?: Alias): {
|
|
84
|
+
select: string[];
|
|
85
|
+
where?: import("../../types").WhereCondition[];
|
|
86
|
+
groupBy?: string[];
|
|
87
|
+
having?: string[];
|
|
88
|
+
limit?: number;
|
|
89
|
+
offset?: number;
|
|
90
|
+
distinct?: boolean;
|
|
91
|
+
orderBy?: {
|
|
92
|
+
column: keyof T | import("../../types").TableColumn<Schema>;
|
|
93
|
+
direction: import("../../types").OrderDirection;
|
|
94
|
+
}[] | undefined;
|
|
95
|
+
joins?: import("../../types").JoinClause[];
|
|
96
|
+
parameters?: any[];
|
|
97
|
+
ctes?: string[];
|
|
98
|
+
unionQueries?: string[];
|
|
99
|
+
settings?: string;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=aggregations.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { QueryBuilder } from '../query-builder';
|
|
2
|
+
import { ColumnType, TableColumn } from '../../types';
|
|
3
|
+
import { ClickHouseSettings } from '@clickhouse/client-common';
|
|
4
|
+
export declare class AnalyticsFeature<Schema extends {
|
|
5
|
+
[tableName: string]: {
|
|
6
|
+
[columnName: string]: ColumnType;
|
|
7
|
+
};
|
|
8
|
+
}, T, HasSelect extends boolean = false, Aggregations = {}, OriginalT = T> {
|
|
9
|
+
private builder;
|
|
10
|
+
constructor(builder: QueryBuilder<Schema, T, HasSelect, Aggregations, OriginalT>);
|
|
11
|
+
addCTE(alias: string, subquery: QueryBuilder<any, any> | string): {
|
|
12
|
+
ctes: string[];
|
|
13
|
+
select?: (string | keyof T)[] | undefined;
|
|
14
|
+
where?: import("../../types").WhereCondition[];
|
|
15
|
+
groupBy?: string[];
|
|
16
|
+
having?: string[];
|
|
17
|
+
limit?: number;
|
|
18
|
+
offset?: number;
|
|
19
|
+
distinct?: boolean;
|
|
20
|
+
orderBy?: {
|
|
21
|
+
column: keyof T | TableColumn<Schema>;
|
|
22
|
+
direction: import("../../types").OrderDirection;
|
|
23
|
+
}[] | undefined;
|
|
24
|
+
joins?: import("../../types").JoinClause[];
|
|
25
|
+
parameters?: any[];
|
|
26
|
+
unionQueries?: string[];
|
|
27
|
+
settings?: string;
|
|
28
|
+
};
|
|
29
|
+
addTimeInterval(column: keyof T | TableColumn<Schema>, interval: string, method: 'toStartOfInterval' | 'toStartOfMinute' | 'toStartOfHour' | 'toStartOfDay' | 'toStartOfWeek' | 'toStartOfMonth' | 'toStartOfQuarter' | 'toStartOfYear'): {
|
|
30
|
+
groupBy: string[];
|
|
31
|
+
select?: (string | keyof T)[] | undefined;
|
|
32
|
+
where?: import("../../types").WhereCondition[];
|
|
33
|
+
having?: string[];
|
|
34
|
+
limit?: number;
|
|
35
|
+
offset?: number;
|
|
36
|
+
distinct?: boolean;
|
|
37
|
+
orderBy?: {
|
|
38
|
+
column: keyof T | TableColumn<Schema>;
|
|
39
|
+
direction: import("../../types").OrderDirection;
|
|
40
|
+
}[] | undefined;
|
|
41
|
+
joins?: import("../../types").JoinClause[];
|
|
42
|
+
parameters?: any[];
|
|
43
|
+
ctes?: string[];
|
|
44
|
+
unionQueries?: string[];
|
|
45
|
+
settings?: string;
|
|
46
|
+
};
|
|
47
|
+
addSettings(opts: ClickHouseSettings): {
|
|
48
|
+
settings: string;
|
|
49
|
+
select?: (string | keyof T)[] | undefined;
|
|
50
|
+
where?: import("../../types").WhereCondition[];
|
|
51
|
+
groupBy?: string[];
|
|
52
|
+
having?: string[];
|
|
53
|
+
limit?: number;
|
|
54
|
+
offset?: number;
|
|
55
|
+
distinct?: boolean;
|
|
56
|
+
orderBy?: {
|
|
57
|
+
column: keyof T | TableColumn<Schema>;
|
|
58
|
+
direction: import("../../types").OrderDirection;
|
|
59
|
+
}[] | undefined;
|
|
60
|
+
joins?: import("../../types").JoinClause[];
|
|
61
|
+
parameters?: any[];
|
|
62
|
+
ctes?: string[];
|
|
63
|
+
unionQueries?: string[];
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../src/core/features/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../src/core/features/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAE9D,qBAAa,gBAAgB,CAC3B,MAAM,SAAS;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAA;CAAE,EAC5E,CAAC,EACD,SAAS,SAAS,OAAO,GAAG,KAAK,EACjC,YAAY,GAAG,EAAE,EACjB,SAAS,GAAG,CAAC;IAED,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC;IAExF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;;;IAS/D,eAAe,CACb,MAAM,EAAE,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,EACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,mBAAmB,GAAG,iBAAiB,GAAG,eAAe,GAAG,cAAc,GAAG,eAAe,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,eAAe;;;;;;;;;;;;;;;;;;IAiBhK,WAAW,CAAC,IAAI,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;CAQrC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { QueryBuilder } from '../query-builder';
|
|
2
|
+
import { CrossFilter } from '../cross-filter';
|
|
3
|
+
import { ColumnType } from '../../types';
|
|
4
|
+
/**
|
|
5
|
+
* Feature for handling cross-filter operations on queries
|
|
6
|
+
*/
|
|
7
|
+
export declare class CrossFilteringFeature<Schema extends {
|
|
8
|
+
[tableName: string]: {
|
|
9
|
+
[columnName: string]: ColumnType;
|
|
10
|
+
};
|
|
11
|
+
}, T, HasSelect extends boolean = false, Aggregations = {}, OriginalT = T> {
|
|
12
|
+
private builder;
|
|
13
|
+
constructor(builder: QueryBuilder<Schema, T, HasSelect, Aggregations, OriginalT>);
|
|
14
|
+
/**
|
|
15
|
+
* Applies a set of cross filters to the query
|
|
16
|
+
* @param crossFilter - An instance of CrossFilter containing shared filter conditions
|
|
17
|
+
* @returns Updated query config
|
|
18
|
+
*/
|
|
19
|
+
applyCrossFilters(crossFilter: CrossFilter<Schema, keyof Schema>): import("../../types").QueryConfig<T, Schema>;
|
|
20
|
+
/**
|
|
21
|
+
* Apply AND conditions - each condition is applied with WHERE
|
|
22
|
+
*/
|
|
23
|
+
private applyAndConditions;
|
|
24
|
+
/**
|
|
25
|
+
* Apply direct OR conditions without adding extra conjunctions
|
|
26
|
+
* @param conditions The conditions to apply
|
|
27
|
+
* @param builder The builder to apply conditions to, defaults to this.builder
|
|
28
|
+
*/
|
|
29
|
+
private applyOrConditions;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=cross-filtering.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-filtering.d.ts","sourceRoot":"","sources":["../../../src/core/features/cross-filtering.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAe,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAwB,UAAU,EAAe,MAAM,aAAa,CAAC;AAgB5E;;GAEG;AACH,qBAAa,qBAAqB,CAChC,MAAM,SAAS;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAAA;KAAE,CAAA;CAAE,EAC5E,CAAC,EACD,SAAS,SAAS,OAAO,GAAG,KAAK,EACjC,YAAY,GAAG,EAAE,EACjB,SAAS,GAAG,CAAC;IAED,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,CAAC;IAExF;;;;OAIG;IACH,iBAAiB,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;IAsBhE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA4B1B;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CAqD1B"}
|