feat(core): introduce typed ClickHouse table API, query builder, and result handling; enhance HTTP client and add schema evolution, batch inserts and mutations; update docs/tests and bump deps

This commit is contained in:
2026-02-27 10:17:32 +00:00
parent 26449e9171
commit aace102868
17 changed files with 7000 additions and 1886 deletions

View File

@@ -1,6 +1,8 @@
import * as plugins from './smartclickhouse.plugins.js';
import { ClickhouseTable } from './smartclickhouse.classes.clickhousetable.js';
import { TimeDataTable } from './smartclickhouse.classes.timedatatable.js';
import { ClickhouseHttpClient } from './smartclickhouse.classes.httpclient.js';
import type { IClickhouseTableOptions } from './smartclickhouse.types.js';
export interface IClickhouseConstructorOptions {
url: string;
@@ -8,8 +10,8 @@ export interface IClickhouseConstructorOptions {
username?: string;
password?: string;
/**
* allow services to exit when waiting for clickhouse startup
* this allows to leave the lifecycle flow to other processes
* Allow services to exit when waiting for clickhouse startup.
* This allows to leave the lifecycle flow to other processes
* like a listening server.
*/
unref?: boolean;
@@ -24,11 +26,10 @@ export class SmartClickHouseDb {
}
/**
* starts the connection to the Clickhouse db
* Starts the connection to the Clickhouse db
*/
public async start(dropOld = false) {
console.log(`Connecting to default database first.`);
// lets connect
this.clickhouseHttpClient = await ClickhouseHttpClient.createAndStart(this.options);
await this.pingDatabaseUntilAvailable();
console.log(`Create database ${this.options.database}, if it does not exist...`);
@@ -47,9 +48,7 @@ export class SmartClickHouseDb {
public async pingDatabaseUntilAvailable() {
let available = false;
while (!available) {
available = await this.clickhouseHttpClient.ping().catch((err) => {
return false;
});
available = await this.clickhouseHttpClient.ping().catch(() => false);
if (!available) {
console.log(`NOT OK: tried pinging ${this.options.url}... Trying again in 5 seconds.`);
await plugins.smartdelay.delayFor(5000, null, this.options.unref);
@@ -57,11 +56,35 @@ export class SmartClickHouseDb {
}
}
// ---- NEW: Generic typed table factory ----
/**
* gets a table
* Create a typed ClickHouse table with full configuration
*/
public async getTable(tableName: string) {
const newTable = TimeDataTable.getTable(this, tableName);
return newTable;
public async createTable<T extends Record<string, any>>(
options: IClickhouseTableOptions<T>,
): Promise<ClickhouseTable<T>> {
return ClickhouseTable.create<T>(this, {
...options,
database: options.database || this.options.database,
});
}
// ---- BACKWARD COMPAT: TimeDataTable factory ----
/**
* Get a TimeDataTable (backward compatible)
*/
public async getTable(tableName: string): Promise<TimeDataTable> {
return TimeDataTable.getTable(this, tableName);
}
// ---- RAW QUERY ----
/**
* Execute a raw SQL query and return typed results
*/
public async query<T = any>(sql: string): Promise<T[]> {
return this.clickhouseHttpClient.queryTyped<T>(sql);
}
}