@querypanel/node-sdk 1.0.7 → 1.0.9
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.md +174 -0
- package/dist/cjs/adapters/clickhouse.d.ts +36 -0
- package/dist/cjs/adapters/clickhouse.d.ts.map +1 -0
- package/dist/cjs/adapters/clickhouse.js +256 -0
- package/dist/cjs/adapters/clickhouse.js.map +1 -0
- package/dist/cjs/adapters/introspection.spec.d.ts +2 -0
- package/dist/cjs/adapters/introspection.spec.d.ts.map +1 -0
- package/dist/cjs/adapters/introspection.spec.js +201 -0
- package/dist/cjs/adapters/introspection.spec.js.map +1 -0
- package/dist/cjs/adapters/postgres.d.ts +29 -0
- package/dist/cjs/adapters/postgres.d.ts.map +1 -0
- package/dist/cjs/adapters/postgres.js +384 -0
- package/dist/cjs/adapters/postgres.js.map +1 -0
- package/dist/cjs/adapters/types.d.ts +34 -0
- package/dist/cjs/adapters/types.d.ts.map +1 -0
- package/dist/cjs/adapters/types.js +3 -0
- package/dist/cjs/adapters/types.js.map +1 -0
- package/dist/cjs/anonymize.spec.d.ts +2 -0
- package/dist/cjs/anonymize.spec.d.ts.map +1 -0
- package/dist/cjs/anonymize.spec.js +80 -0
- package/dist/cjs/anonymize.spec.js.map +1 -0
- package/dist/cjs/clickhouseClient.spec.d.ts +2 -0
- package/dist/cjs/clickhouseClient.spec.d.ts.map +1 -0
- package/dist/cjs/clickhouseClient.spec.js +286 -0
- package/dist/cjs/clickhouseClient.spec.js.map +1 -0
- package/dist/cjs/connectors/clickhouse.d.ts +4 -4
- package/dist/cjs/connectors/clickhouse.d.ts.map +1 -1
- package/dist/cjs/connectors/clickhouse.js +30 -23
- package/dist/cjs/connectors/clickhouse.js.map +1 -1
- package/dist/cjs/index.d.ts +69 -5
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +257 -50
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.test.d.ts +2 -0
- package/dist/cjs/index.test.d.ts.map +1 -0
- package/dist/cjs/index.test.js +112 -0
- package/dist/cjs/index.test.js.map +1 -0
- package/dist/cjs/multidb.spec.d.ts +2 -0
- package/dist/cjs/multidb.spec.d.ts.map +1 -0
- package/dist/cjs/multidb.spec.js +76 -0
- package/dist/cjs/multidb.spec.js.map +1 -0
- package/dist/esm/adapters/clickhouse.d.ts +36 -0
- package/dist/esm/adapters/clickhouse.d.ts.map +1 -0
- package/dist/esm/adapters/clickhouse.js +252 -0
- package/dist/esm/adapters/clickhouse.js.map +1 -0
- package/dist/esm/adapters/introspection.spec.d.ts +2 -0
- package/dist/esm/adapters/introspection.spec.d.ts.map +1 -0
- package/dist/esm/adapters/introspection.spec.js +199 -0
- package/dist/esm/adapters/introspection.spec.js.map +1 -0
- package/dist/esm/adapters/postgres.d.ts +29 -0
- package/dist/esm/adapters/postgres.d.ts.map +1 -0
- package/dist/esm/adapters/postgres.js +380 -0
- package/dist/esm/adapters/postgres.js.map +1 -0
- package/dist/esm/adapters/types.d.ts +34 -0
- package/dist/esm/adapters/types.d.ts.map +1 -0
- package/dist/esm/adapters/types.js +2 -0
- package/dist/esm/adapters/types.js.map +1 -0
- package/dist/esm/anonymize.spec.d.ts +2 -0
- package/dist/esm/anonymize.spec.d.ts.map +1 -0
- package/dist/esm/anonymize.spec.js +78 -0
- package/dist/esm/anonymize.spec.js.map +1 -0
- package/dist/esm/clickhouseClient.spec.d.ts +2 -0
- package/dist/esm/clickhouseClient.spec.d.ts.map +1 -0
- package/dist/esm/clickhouseClient.spec.js +281 -0
- package/dist/esm/clickhouseClient.spec.js.map +1 -0
- package/dist/esm/connectors/clickhouse.d.ts +4 -4
- package/dist/esm/connectors/clickhouse.d.ts.map +1 -1
- package/dist/esm/connectors/clickhouse.js +32 -25
- package/dist/esm/connectors/clickhouse.js.map +1 -1
- package/dist/esm/index.d.ts +69 -5
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +256 -50
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.test.d.ts +2 -0
- package/dist/esm/index.test.d.ts.map +1 -0
- package/dist/esm/index.test.js +110 -0
- package/dist/esm/index.test.js.map +1 -0
- package/dist/esm/multidb.spec.d.ts +2 -0
- package/dist/esm/multidb.spec.d.ts.map +1 -0
- package/dist/esm/multidb.spec.js +74 -0
- package/dist/esm/multidb.spec.js.map +1 -0
- package/package.json +5 -2
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IntrospectOptions, SchemaIntrospection } from "../schema/types.js";
|
|
2
|
+
export type DatabaseDialect = "clickhouse" | "postgres" | "mysql";
|
|
3
|
+
export interface DatabaseExecutionResult {
|
|
4
|
+
fields: string[];
|
|
5
|
+
rows: Array<Record<string, unknown>>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Database adapter interface for abstracting database-specific operations.
|
|
9
|
+
* Allows the SDK to work with multiple database types.
|
|
10
|
+
*/
|
|
11
|
+
export interface DatabaseAdapter {
|
|
12
|
+
/**
|
|
13
|
+
* Execute a SQL query and return results
|
|
14
|
+
*/
|
|
15
|
+
execute(sql: string): Promise<DatabaseExecutionResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Validate SQL query (e.g., using EXPLAIN)
|
|
18
|
+
* Throws an error if the SQL is invalid
|
|
19
|
+
*/
|
|
20
|
+
validate(sql: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Introspect database schema metadata
|
|
23
|
+
*/
|
|
24
|
+
introspect(options?: IntrospectOptions): Promise<SchemaIntrospection>;
|
|
25
|
+
/**
|
|
26
|
+
* Get the database dialect/type
|
|
27
|
+
*/
|
|
28
|
+
getDialect(): DatabaseDialect;
|
|
29
|
+
/**
|
|
30
|
+
* Optional: Close/cleanup database connection
|
|
31
|
+
*/
|
|
32
|
+
close?(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAEvD;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC;;OAEG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAEtE;;OAEG;IACH,UAAU,IAAI,eAAe,CAAC;IAE9B;;OAEG;IACH,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymize.spec.d.ts","sourceRoot":"","sources":["../../src/anonymize.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const index_js_1 = require("./index.js");
|
|
5
|
+
(0, vitest_1.describe)("anonymizeResults", () => {
|
|
6
|
+
(0, vitest_1.it)("anonymizes numeric values", () => {
|
|
7
|
+
const input = [
|
|
8
|
+
{ year: 2025, transactionSum: 1000 },
|
|
9
|
+
{ year: 2024, transactionSum: 2000 },
|
|
10
|
+
];
|
|
11
|
+
const result = (0, index_js_1.anonymizeResults)(input);
|
|
12
|
+
(0, vitest_1.expect)(result).toEqual([
|
|
13
|
+
{ year: "number", transactionSum: "number" },
|
|
14
|
+
{ year: "number", transactionSum: "number" },
|
|
15
|
+
]);
|
|
16
|
+
});
|
|
17
|
+
(0, vitest_1.it)("anonymizes mixed types", () => {
|
|
18
|
+
const input = [
|
|
19
|
+
{
|
|
20
|
+
id: 1,
|
|
21
|
+
name: "John Doe",
|
|
22
|
+
active: true,
|
|
23
|
+
score: 95.5,
|
|
24
|
+
metadata: null,
|
|
25
|
+
tags: ["admin", "user"],
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
const result = (0, index_js_1.anonymizeResults)(input);
|
|
29
|
+
(0, vitest_1.expect)(result).toEqual([
|
|
30
|
+
{
|
|
31
|
+
id: "number",
|
|
32
|
+
name: "string",
|
|
33
|
+
active: "boolean",
|
|
34
|
+
score: "number",
|
|
35
|
+
metadata: "null",
|
|
36
|
+
tags: "array",
|
|
37
|
+
},
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
(0, vitest_1.it)("handles empty arrays", () => {
|
|
41
|
+
const result = (0, index_js_1.anonymizeResults)([]);
|
|
42
|
+
(0, vitest_1.expect)(result).toEqual([]);
|
|
43
|
+
});
|
|
44
|
+
(0, vitest_1.it)("handles objects with nested structures", () => {
|
|
45
|
+
const input = [
|
|
46
|
+
{
|
|
47
|
+
user: { name: "Alice" },
|
|
48
|
+
count: 42,
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
const result = (0, index_js_1.anonymizeResults)(input);
|
|
52
|
+
(0, vitest_1.expect)(result).toEqual([
|
|
53
|
+
{
|
|
54
|
+
user: "object",
|
|
55
|
+
count: "number",
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
(0, vitest_1.it)("preserves column structure across multiple rows", () => {
|
|
60
|
+
const input = [
|
|
61
|
+
{ col1: "value1", col2: 100, col3: true },
|
|
62
|
+
{ col1: "value2", col2: 200, col3: false },
|
|
63
|
+
{ col1: "value3", col2: 300, col3: true },
|
|
64
|
+
];
|
|
65
|
+
const result = (0, index_js_1.anonymizeResults)(input);
|
|
66
|
+
(0, vitest_1.expect)(result).toEqual([
|
|
67
|
+
{ col1: "string", col2: "number", col3: "boolean" },
|
|
68
|
+
{ col1: "string", col2: "number", col3: "boolean" },
|
|
69
|
+
{ col1: "string", col2: "number", col3: "boolean" },
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
(0, vitest_1.it)("handles undefined values", () => {
|
|
73
|
+
const input = [{ defined: 123, undefined: undefined }];
|
|
74
|
+
const result = (0, index_js_1.anonymizeResults)(input);
|
|
75
|
+
(0, vitest_1.expect)(result).toEqual([
|
|
76
|
+
{ defined: "number", undefined: "undefined" },
|
|
77
|
+
]);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=anonymize.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymize.spec.js","sourceRoot":"","sources":["../../src/anonymize.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clickhouseClient.spec.d.ts","sourceRoot":"","sources":["../../src/clickhouseClient.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const duckdb_1 = __importDefault(require("duckdb"));
|
|
7
|
+
const vitest_1 = require("vitest");
|
|
8
|
+
const index_js_1 = require("./index.js");
|
|
9
|
+
// @ts-expect-error
|
|
10
|
+
globalThis.fetch = async (input, _init) => {
|
|
11
|
+
const url = String(input);
|
|
12
|
+
if (url.endsWith("/v2/active-charts")) {
|
|
13
|
+
return {
|
|
14
|
+
ok: true,
|
|
15
|
+
status: 200,
|
|
16
|
+
text: async () => JSON.stringify({
|
|
17
|
+
data: [
|
|
18
|
+
{
|
|
19
|
+
id: "ac1",
|
|
20
|
+
chart_id: "1",
|
|
21
|
+
order: 1,
|
|
22
|
+
meta: null,
|
|
23
|
+
organization_id: null,
|
|
24
|
+
tenant_id: null,
|
|
25
|
+
user_id: null,
|
|
26
|
+
created_at: null,
|
|
27
|
+
updated_at: null,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
pagination: {
|
|
31
|
+
page: 1,
|
|
32
|
+
limit: 10,
|
|
33
|
+
total: 1,
|
|
34
|
+
totalPages: 1,
|
|
35
|
+
hasNext: false,
|
|
36
|
+
hasPrev: false,
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (/\/v2\/charts\/[^/]+$/.test(url)) {
|
|
42
|
+
return {
|
|
43
|
+
ok: true,
|
|
44
|
+
status: 200,
|
|
45
|
+
text: async () => JSON.stringify({
|
|
46
|
+
id: "1",
|
|
47
|
+
title: "Single",
|
|
48
|
+
description: null,
|
|
49
|
+
sql: "SELECT id, value FROM demo ORDER BY id",
|
|
50
|
+
vega_lite_spec: { mark: "point" },
|
|
51
|
+
query_id: null,
|
|
52
|
+
organization_id: null,
|
|
53
|
+
tenant_id: null,
|
|
54
|
+
user_id: null,
|
|
55
|
+
created_at: null,
|
|
56
|
+
updated_at: null,
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (url.endsWith("/v2/charts")) {
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
status: 200,
|
|
64
|
+
text: async () => JSON.stringify({
|
|
65
|
+
data: [
|
|
66
|
+
{
|
|
67
|
+
id: "1",
|
|
68
|
+
title: "Demo",
|
|
69
|
+
description: null,
|
|
70
|
+
sql: "SELECT id, value FROM demo ORDER BY id",
|
|
71
|
+
vega_lite_spec: { mark: "bar" },
|
|
72
|
+
query_id: null,
|
|
73
|
+
organization_id: null,
|
|
74
|
+
tenant_id: null,
|
|
75
|
+
user_id: null,
|
|
76
|
+
created_at: null,
|
|
77
|
+
updated_at: null,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
pagination: {
|
|
81
|
+
page: 1,
|
|
82
|
+
limit: 10,
|
|
83
|
+
total: 1,
|
|
84
|
+
totalPages: 1,
|
|
85
|
+
hasNext: false,
|
|
86
|
+
hasPrev: false,
|
|
87
|
+
},
|
|
88
|
+
}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (url.endsWith("/v2/generate-sql")) {
|
|
92
|
+
return {
|
|
93
|
+
ok: true,
|
|
94
|
+
status: 200,
|
|
95
|
+
text: async () => JSON.stringify({
|
|
96
|
+
sql: "SELECT id as x, value as y FROM demo ORDER BY id",
|
|
97
|
+
rationale: "ok",
|
|
98
|
+
context: [],
|
|
99
|
+
}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (url.endsWith("/v2/generate-chart")) {
|
|
103
|
+
return {
|
|
104
|
+
ok: true,
|
|
105
|
+
status: 200,
|
|
106
|
+
text: async () => JSON.stringify({ vegaLiteSpec: { mark: "line" }, notes: null }),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (/\/v2\/active-charts\/[^/]+$/.test(url)) {
|
|
110
|
+
const id = url.split("/").pop();
|
|
111
|
+
if (id === "ac1") {
|
|
112
|
+
return {
|
|
113
|
+
ok: true,
|
|
114
|
+
status: 200,
|
|
115
|
+
text: async () => JSON.stringify({
|
|
116
|
+
id: "ac1",
|
|
117
|
+
chart_id: "1",
|
|
118
|
+
order: 1,
|
|
119
|
+
meta: null,
|
|
120
|
+
organization_id: null,
|
|
121
|
+
tenant_id: null,
|
|
122
|
+
user_id: null,
|
|
123
|
+
created_at: null,
|
|
124
|
+
updated_at: null,
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (id === "ac2") {
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
status: 200,
|
|
132
|
+
text: async () => JSON.stringify({
|
|
133
|
+
id: "ac2",
|
|
134
|
+
chart_id: "1",
|
|
135
|
+
order: 1,
|
|
136
|
+
meta: null,
|
|
137
|
+
organization_id: null,
|
|
138
|
+
tenant_id: null,
|
|
139
|
+
user_id: null,
|
|
140
|
+
created_at: null,
|
|
141
|
+
updated_at: null,
|
|
142
|
+
chart: {
|
|
143
|
+
id: "1",
|
|
144
|
+
title: "Nested",
|
|
145
|
+
description: null,
|
|
146
|
+
sql: "SELECT id, value FROM demo ORDER BY id",
|
|
147
|
+
vega_lite_spec: { mark: "square" },
|
|
148
|
+
query_id: null,
|
|
149
|
+
organization_id: null,
|
|
150
|
+
tenant_id: null,
|
|
151
|
+
user_id: null,
|
|
152
|
+
created_at: null,
|
|
153
|
+
updated_at: null,
|
|
154
|
+
},
|
|
155
|
+
}),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// other endpoints not used in this test
|
|
160
|
+
return { ok: false, status: 404, text: async () => "" };
|
|
161
|
+
};
|
|
162
|
+
// Helper to create an in-memory DuckDB connection and run queries
|
|
163
|
+
function createDuckDb() {
|
|
164
|
+
const db = new duckdb_1.default.Database(":memory:");
|
|
165
|
+
const conn = db.connect();
|
|
166
|
+
return { db, conn };
|
|
167
|
+
}
|
|
168
|
+
(0, vitest_1.describe)("attachClickhouseClient", () => {
|
|
169
|
+
let conn;
|
|
170
|
+
let clickhouseClientFn;
|
|
171
|
+
(0, vitest_1.beforeAll)(async () => {
|
|
172
|
+
({ conn } = createDuckDb());
|
|
173
|
+
clickhouseClientFn = async ({ query }) => {
|
|
174
|
+
const rows = await new Promise((resolve, reject) => {
|
|
175
|
+
conn.all(query, (err, result) => {
|
|
176
|
+
if (err)
|
|
177
|
+
return reject(err);
|
|
178
|
+
resolve(result);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
const result = {
|
|
182
|
+
json: async () => rows,
|
|
183
|
+
};
|
|
184
|
+
return result;
|
|
185
|
+
};
|
|
186
|
+
await new Promise((resolve, reject) => {
|
|
187
|
+
conn.run("CREATE TABLE demo(id INTEGER, value VARCHAR)", (err) => {
|
|
188
|
+
if (err)
|
|
189
|
+
return reject(err);
|
|
190
|
+
conn.run("INSERT INTO demo VALUES (1, 'a'), (2, 'b')", (err2) => {
|
|
191
|
+
if (err2)
|
|
192
|
+
return reject(err2);
|
|
193
|
+
resolve();
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
(0, vitest_1.afterAll)(() => {
|
|
199
|
+
try {
|
|
200
|
+
conn.close();
|
|
201
|
+
}
|
|
202
|
+
catch { }
|
|
203
|
+
});
|
|
204
|
+
(0, vitest_1.it)("returns values from runDataOnCLient when listing charts", async () => {
|
|
205
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
206
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
207
|
+
const result = await sdk.listCharts({ tenantId: "t1" });
|
|
208
|
+
(0, vitest_1.expect)(result.data.length).toBe(1);
|
|
209
|
+
const chart = result.data[0];
|
|
210
|
+
(0, vitest_1.expect)(chart.vega_lite_spec?.data?.values).toEqual([
|
|
211
|
+
{ id: 1, value: "a" },
|
|
212
|
+
{ id: 2, value: "b" },
|
|
213
|
+
]);
|
|
214
|
+
});
|
|
215
|
+
(0, vitest_1.it)("hydrates data when getting a single chart", async () => {
|
|
216
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
217
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
218
|
+
const chart = await sdk.getChart("1", { tenantId: "t1" });
|
|
219
|
+
(0, vitest_1.expect)(chart.id).toBe("1");
|
|
220
|
+
(0, vitest_1.expect)(chart.vega_lite_spec?.data?.values).toEqual([
|
|
221
|
+
{ id: 1, value: "a" },
|
|
222
|
+
{ id: 2, value: "b" },
|
|
223
|
+
]);
|
|
224
|
+
});
|
|
225
|
+
(0, vitest_1.it)("lists active charts without data when withdata=false", async () => {
|
|
226
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
227
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
228
|
+
const result = await sdk.listActiveCharts({
|
|
229
|
+
tenantId: "t1",
|
|
230
|
+
withdata: false,
|
|
231
|
+
});
|
|
232
|
+
(0, vitest_1.expect)(result.data.length).toBe(1);
|
|
233
|
+
const firstNoData = result.data[0];
|
|
234
|
+
if (!firstNoData)
|
|
235
|
+
throw new Error("missing active chart");
|
|
236
|
+
(0, vitest_1.expect)(firstNoData.chart).toBeUndefined();
|
|
237
|
+
});
|
|
238
|
+
(0, vitest_1.it)("lists active charts with data when withdata=true", async () => {
|
|
239
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
240
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
241
|
+
const result = await sdk.listActiveCharts({
|
|
242
|
+
tenantId: "t1",
|
|
243
|
+
withdata: true,
|
|
244
|
+
});
|
|
245
|
+
(0, vitest_1.expect)(result.data.length).toBe(1);
|
|
246
|
+
const firstWithData = result.data[0];
|
|
247
|
+
if (!firstWithData || !firstWithData.chart)
|
|
248
|
+
throw new Error("missing hydrated active chart");
|
|
249
|
+
(0, vitest_1.expect)(Boolean(firstWithData.chart)).toBe(true);
|
|
250
|
+
(0, vitest_1.expect)(firstWithData.chart.vega_lite_spec?.data?.values).toEqual([
|
|
251
|
+
{ id: 1, value: "a" },
|
|
252
|
+
{ id: 2, value: "b" },
|
|
253
|
+
]);
|
|
254
|
+
});
|
|
255
|
+
(0, vitest_1.it)("gets active chart without nested chart unchanged", async () => {
|
|
256
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
257
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
258
|
+
const ac = await sdk.getActiveChart("ac1", { tenantId: "t1" });
|
|
259
|
+
(0, vitest_1.expect)(ac.id).toBe("ac1");
|
|
260
|
+
(0, vitest_1.expect)("chart" in ac ? ac.chart : undefined).toBeUndefined();
|
|
261
|
+
});
|
|
262
|
+
(0, vitest_1.it)("gets active chart with nested chart hydrated", async () => {
|
|
263
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
264
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
265
|
+
const ac = await sdk.getActiveChart("ac2", { tenantId: "t1" });
|
|
266
|
+
if (!ac.chart)
|
|
267
|
+
throw new Error("expected nested chart");
|
|
268
|
+
(0, vitest_1.expect)(ac.chart.vega_lite_spec?.data?.values).toEqual([
|
|
269
|
+
{ id: 1, value: "a" },
|
|
270
|
+
{ id: 2, value: "b" },
|
|
271
|
+
]);
|
|
272
|
+
});
|
|
273
|
+
(0, vitest_1.it)("works with ask() by executing SQL against DuckDB", async () => {
|
|
274
|
+
const sdk = new index_js_1.QueryPanelSdkAPI("http://api", "test-token");
|
|
275
|
+
sdk.attachClickhouseClient(clickhouseClientFn);
|
|
276
|
+
const result = await sdk.ask("q", { tenantId: "t1" });
|
|
277
|
+
(0, vitest_1.expect)(result.sql).toContain("SELECT id as x, value as y");
|
|
278
|
+
(0, vitest_1.expect)(result.fields).toEqual(["x", "y"]);
|
|
279
|
+
(0, vitest_1.expect)(result.rows).toEqual([
|
|
280
|
+
{ x: 1, y: "a" },
|
|
281
|
+
{ x: 2, y: "b" },
|
|
282
|
+
]);
|
|
283
|
+
(0, vitest_1.expect)(result.chart.vegaLiteSpec).toMatchObject({ mark: "line" });
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
//# sourceMappingURL=clickhouseClient.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clickhouseClient.spec.js","sourceRoot":"","sources":["../../src/clickhouseClient.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { type ClickHouseClient, type ClickHouseClientConfigOptions } from
|
|
2
|
-
import type { IntrospectOptions, SchemaIntrospection } from
|
|
3
|
-
import type { DatabaseConnector, QueryOptions } from
|
|
1
|
+
import { type ClickHouseClient, type ClickHouseClientConfigOptions } from "@clickhouse/client";
|
|
2
|
+
import type { IntrospectOptions, SchemaIntrospection } from "../schema/types.js";
|
|
3
|
+
import type { DatabaseConnector, QueryOptions } from "./base.js";
|
|
4
4
|
export interface ClickHouseConnectorConfig {
|
|
5
5
|
/** Fully qualified ClickHouse URL. Overrides host/port/protocol when provided. */
|
|
6
6
|
url?: string;
|
|
7
7
|
host?: string;
|
|
8
8
|
port?: number;
|
|
9
|
-
protocol?:
|
|
9
|
+
protocol?: "http" | "https";
|
|
10
10
|
database: string;
|
|
11
11
|
username?: string;
|
|
12
12
|
password?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../../src/connectors/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../../src/connectors/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAIlC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAEX,iBAAiB,EACjB,mBAAmB,EAEnB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEjE,MAAM,WAAW,yBAAyB;IACzC,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7C,aAAa,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,4BAA4B;IAC5C,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,gBAAgB,CAAC;CACvC;AA4BD,qBAAa,mBAAoB,YAAW,iBAAiB;IAO3D,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAP3B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAEC;gBAGb,MAAM,EAAE,yBAAyB,EACjC,SAAS,GAAE,4BAAiC;IAKxD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,CAAC,EAAE,CAAC;IAmCT,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAyGrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAMd,YAAY;YAcZ,QAAQ;IAYtB,OAAO,CAAC,iBAAiB;CAkCzB"}
|
|
@@ -7,7 +7,7 @@ class ClickHouseConnector {
|
|
|
7
7
|
constructor(config, overrides = {}) {
|
|
8
8
|
this.config = config;
|
|
9
9
|
this.overrides = overrides;
|
|
10
|
-
this.defaultFormat =
|
|
10
|
+
this.defaultFormat = "JSONEachRow";
|
|
11
11
|
this.client = overrides.client ?? null;
|
|
12
12
|
}
|
|
13
13
|
async connect() {
|
|
@@ -26,14 +26,16 @@ class ClickHouseConnector {
|
|
|
26
26
|
Object.assign(params, { query_params: options.params });
|
|
27
27
|
}
|
|
28
28
|
if (options?.settings) {
|
|
29
|
-
Object.assign(params, {
|
|
29
|
+
Object.assign(params, {
|
|
30
|
+
clickhouse_settings: options.settings,
|
|
31
|
+
});
|
|
30
32
|
}
|
|
31
33
|
const result = await client.query(params);
|
|
32
34
|
const payload = await result.json();
|
|
33
35
|
if (Array.isArray(payload)) {
|
|
34
36
|
return payload;
|
|
35
37
|
}
|
|
36
|
-
if (payload && typeof payload ===
|
|
38
|
+
if (payload && typeof payload === "object") {
|
|
37
39
|
const maybeData = payload.data;
|
|
38
40
|
if (Array.isArray(maybeData)) {
|
|
39
41
|
return maybeData;
|
|
@@ -50,12 +52,14 @@ class ClickHouseConnector {
|
|
|
50
52
|
if (hasFilter) {
|
|
51
53
|
queryParams.tables = allowTables;
|
|
52
54
|
}
|
|
53
|
-
const filterClause = hasFilter ?
|
|
55
|
+
const filterClause = hasFilter ? " AND name IN {tables:Array(String)}" : "";
|
|
54
56
|
const tables = await this.query(`SELECT name, engine, comment, total_rows, total_bytes, is_view, primary_key, sorting_key
|
|
55
57
|
FROM system.tables
|
|
56
58
|
WHERE database = {db:String}${filterClause}
|
|
57
59
|
ORDER BY name`, { params: queryParams });
|
|
58
|
-
const columnFilterClause = hasFilter
|
|
60
|
+
const columnFilterClause = hasFilter
|
|
61
|
+
? " AND table IN {tables:Array(String)}"
|
|
62
|
+
: "";
|
|
59
63
|
const columns = await this.query(`SELECT table, name, type, position, default_kind, default_expression, comment,
|
|
60
64
|
codec_expression, ttl_expression, is_in_primary_key,
|
|
61
65
|
data_compressed_bytes, data_uncompressed_bytes
|
|
@@ -74,15 +78,16 @@ class ClickHouseConnector {
|
|
|
74
78
|
const totalRows = toNumber(table.total_rows);
|
|
75
79
|
const totalBytes = toNumber(table.total_bytes);
|
|
76
80
|
for (const column of tableColumns) {
|
|
77
|
-
column.isPrimaryKey =
|
|
81
|
+
column.isPrimaryKey =
|
|
82
|
+
column.isPrimaryKey || primaryKeyColumns.includes(column.name);
|
|
78
83
|
}
|
|
79
84
|
const indexes = primaryKeyColumns.length
|
|
80
85
|
? [
|
|
81
86
|
{
|
|
82
|
-
name:
|
|
87
|
+
name: "primary_key",
|
|
83
88
|
columns: primaryKeyColumns,
|
|
84
89
|
unique: true,
|
|
85
|
-
type:
|
|
90
|
+
type: "PRIMARY KEY",
|
|
86
91
|
...(table.primary_key ? { definition: table.primary_key } : {}),
|
|
87
92
|
},
|
|
88
93
|
]
|
|
@@ -90,8 +95,8 @@ class ClickHouseConnector {
|
|
|
90
95
|
const constraints = primaryKeyColumns.length
|
|
91
96
|
? [
|
|
92
97
|
{
|
|
93
|
-
name:
|
|
94
|
-
type:
|
|
98
|
+
name: "primary_key",
|
|
99
|
+
type: "PRIMARY KEY",
|
|
95
100
|
columns: primaryKeyColumns,
|
|
96
101
|
},
|
|
97
102
|
]
|
|
@@ -117,7 +122,7 @@ class ClickHouseConnector {
|
|
|
117
122
|
});
|
|
118
123
|
return {
|
|
119
124
|
db: {
|
|
120
|
-
kind:
|
|
125
|
+
kind: "clickhouse",
|
|
121
126
|
name: this.config.database,
|
|
122
127
|
},
|
|
123
128
|
tables: tableSchemas,
|
|
@@ -134,10 +139,12 @@ class ClickHouseConnector {
|
|
|
134
139
|
if (this.client) {
|
|
135
140
|
return this.client;
|
|
136
141
|
}
|
|
137
|
-
this.client =
|
|
142
|
+
this.client =
|
|
143
|
+
this.overrides?.clientFactory?.() ??
|
|
144
|
+
(0, client_1.createClient)(this.buildClientConfig());
|
|
138
145
|
const pingResult = await this.safePing(this.client);
|
|
139
|
-
if (pingResult &&
|
|
140
|
-
throw pingResult.error ?? new Error(
|
|
146
|
+
if (pingResult && "success" in pingResult && pingResult.success === false) {
|
|
147
|
+
throw pingResult.error ?? new Error("ClickHouse ping failed");
|
|
141
148
|
}
|
|
142
149
|
return this.client;
|
|
143
150
|
}
|
|
@@ -159,8 +166,8 @@ class ClickHouseConnector {
|
|
|
159
166
|
merged.url = this.config.url;
|
|
160
167
|
}
|
|
161
168
|
else if (this.config.host) {
|
|
162
|
-
const protocol = this.config.protocol ??
|
|
163
|
-
const port = this.config.port ?? (protocol ===
|
|
169
|
+
const protocol = this.config.protocol ?? "https";
|
|
170
|
+
const port = this.config.port ?? (protocol === "https" ? 8443 : 8123);
|
|
164
171
|
merged.url = `${protocol}://${this.config.host}:${port}`;
|
|
165
172
|
}
|
|
166
173
|
merged.database = this.config.database;
|
|
@@ -194,7 +201,7 @@ function normalizeTableFilter(tables) {
|
|
|
194
201
|
const trimmed = table.trim();
|
|
195
202
|
if (!trimmed)
|
|
196
203
|
continue;
|
|
197
|
-
const parts = trimmed.split(
|
|
204
|
+
const parts = trimmed.split(".");
|
|
198
205
|
const tableName = parts[parts.length - 1];
|
|
199
206
|
if (!tableName || seen.has(tableName))
|
|
200
207
|
continue;
|
|
@@ -251,7 +258,7 @@ function transformColumnRow(row) {
|
|
|
251
258
|
function toNumber(value) {
|
|
252
259
|
if (value === null || value === undefined)
|
|
253
260
|
return undefined;
|
|
254
|
-
if (typeof value ===
|
|
261
|
+
if (typeof value === "number")
|
|
255
262
|
return value;
|
|
256
263
|
const parsed = Number.parseFloat(String(value));
|
|
257
264
|
return Number.isNaN(parsed) ? undefined : parsed;
|
|
@@ -263,14 +270,14 @@ function sanitize(value) {
|
|
|
263
270
|
return trimmed.length ? trimmed : undefined;
|
|
264
271
|
}
|
|
265
272
|
function asTableType(isView) {
|
|
266
|
-
if (typeof isView ===
|
|
267
|
-
return isView > 0 ?
|
|
273
|
+
if (typeof isView === "number") {
|
|
274
|
+
return isView > 0 ? "view" : "table";
|
|
268
275
|
}
|
|
269
|
-
if (typeof isView ===
|
|
276
|
+
if (typeof isView === "string") {
|
|
270
277
|
const normalized = isView.toLowerCase();
|
|
271
|
-
return normalized ===
|
|
278
|
+
return normalized === "1" || normalized === "true" ? "view" : "table";
|
|
272
279
|
}
|
|
273
|
-
return
|
|
280
|
+
return "table";
|
|
274
281
|
}
|
|
275
282
|
function buildTableStatistics(totalRows, totalBytes) {
|
|
276
283
|
if (totalRows === undefined && totalBytes === undefined)
|