@querypanel/node-sdk 1.0.28 → 1.0.29
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/dist/index.cjs +797 -1824
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +218 -138
- package/dist/index.d.ts +218 -138
- package/dist/index.js +796 -1821
- package/dist/index.js.map +1 -1
- package/package.json +73 -73
package/dist/index.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { createHash, randomUUID } from "crypto";
|
|
3
|
+
import { importPKCS8, SignJWT } from "jose";
|
|
4
|
+
|
|
1
5
|
// src/utils/clickhouse.ts
|
|
2
6
|
var WRAPPER_REGEX = /^(Nullable|LowCardinality|SimpleAggregateFunction)\((.+)\)$/i;
|
|
7
|
+
function isNullableType(type) {
|
|
8
|
+
return /Nullable\s*\(/i.test(type);
|
|
9
|
+
}
|
|
3
10
|
function unwrapTypeModifiers(type) {
|
|
4
11
|
let current = type.trim();
|
|
5
12
|
let match = WRAPPER_REGEX.exec(current);
|
|
@@ -13,6 +20,26 @@ function unwrapTypeModifiers(type) {
|
|
|
13
20
|
}
|
|
14
21
|
return current;
|
|
15
22
|
}
|
|
23
|
+
function extractPrecisionScale(type) {
|
|
24
|
+
const unwrapped = unwrapTypeModifiers(type);
|
|
25
|
+
const decimalMatch = unwrapped.match(/Decimal(?:\d+)?\((\d+)\s*,\s*(\d+)\)/i);
|
|
26
|
+
if (!decimalMatch) return {};
|
|
27
|
+
const precision = decimalMatch[1];
|
|
28
|
+
const scale = decimalMatch[2];
|
|
29
|
+
if (!precision || !scale) return {};
|
|
30
|
+
return {
|
|
31
|
+
precision: Number.parseInt(precision, 10),
|
|
32
|
+
scale: Number.parseInt(scale, 10)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function extractFixedStringLength(type) {
|
|
36
|
+
const unwrapped = unwrapTypeModifiers(type);
|
|
37
|
+
const match = unwrapped.match(/^(?:FixedString|StringFixed)\((\d+)\)$/i);
|
|
38
|
+
if (!match) return void 0;
|
|
39
|
+
const length = match[1];
|
|
40
|
+
if (!length) return void 0;
|
|
41
|
+
return Number.parseInt(length, 10);
|
|
42
|
+
}
|
|
16
43
|
function parseKeyExpression(expression) {
|
|
17
44
|
if (!expression) return [];
|
|
18
45
|
let value = expression.trim();
|
|
@@ -100,10 +127,6 @@ var ClickHouseAdapter = class {
|
|
|
100
127
|
getDialect() {
|
|
101
128
|
return "clickhouse";
|
|
102
129
|
}
|
|
103
|
-
/**
|
|
104
|
-
* Simplified introspection: only collect table/column metadata for IngestRequest
|
|
105
|
-
* No indexes, constraints, or statistics
|
|
106
|
-
*/
|
|
107
130
|
async introspect(options) {
|
|
108
131
|
const tablesToIntrospect = options?.tables ? normalizeTableFilter(options.tables) : this.allowedTables;
|
|
109
132
|
const allowTables = tablesToIntrospect ?? [];
|
|
@@ -116,7 +139,7 @@ var ClickHouseAdapter = class {
|
|
|
116
139
|
}
|
|
117
140
|
const filterClause = hasFilter ? " AND name IN {tables:Array(String)}" : "";
|
|
118
141
|
const tables = await this.query(
|
|
119
|
-
`SELECT name, engine, comment, primary_key
|
|
142
|
+
`SELECT name, engine, comment, total_rows, total_bytes, primary_key, sorting_key
|
|
120
143
|
FROM system.tables
|
|
121
144
|
WHERE database = {db:String}${filterClause}
|
|
122
145
|
ORDER BY name`,
|
|
@@ -124,7 +147,7 @@ var ClickHouseAdapter = class {
|
|
|
124
147
|
);
|
|
125
148
|
const columnFilterClause = hasFilter ? " AND table IN {tables:Array(String)}" : "";
|
|
126
149
|
const columns = await this.query(
|
|
127
|
-
`SELECT table, name, type, position, comment, is_in_primary_key
|
|
150
|
+
`SELECT table, name, type, position, default_kind, default_expression, comment, is_in_primary_key
|
|
128
151
|
FROM system.columns
|
|
129
152
|
WHERE database = {db:String}${columnFilterClause}
|
|
130
153
|
ORDER BY table, position`,
|
|
@@ -139,19 +162,44 @@ var ClickHouseAdapter = class {
|
|
|
139
162
|
const tableSchemas = tables.map((table) => {
|
|
140
163
|
const tableColumns = columnsByTable.get(table.name) ?? [];
|
|
141
164
|
const primaryKeyColumns = parseKeyExpression(table.primary_key);
|
|
165
|
+
const totalRows = toNumber(table.total_rows);
|
|
166
|
+
const totalBytes = toNumber(table.total_bytes);
|
|
142
167
|
for (const column of tableColumns) {
|
|
143
168
|
column.isPrimaryKey = column.isPrimaryKey || primaryKeyColumns.includes(column.name);
|
|
144
169
|
}
|
|
170
|
+
const indexes = primaryKeyColumns.length ? [
|
|
171
|
+
{
|
|
172
|
+
name: "primary_key",
|
|
173
|
+
columns: primaryKeyColumns,
|
|
174
|
+
unique: true,
|
|
175
|
+
type: "PRIMARY KEY",
|
|
176
|
+
...table.primary_key ? { definition: table.primary_key } : {}
|
|
177
|
+
}
|
|
178
|
+
] : [];
|
|
179
|
+
const constraints = primaryKeyColumns.length ? [
|
|
180
|
+
{
|
|
181
|
+
name: "primary_key",
|
|
182
|
+
type: "PRIMARY KEY",
|
|
183
|
+
columns: primaryKeyColumns
|
|
184
|
+
}
|
|
185
|
+
] : [];
|
|
145
186
|
const base = {
|
|
146
187
|
name: table.name,
|
|
147
188
|
schema: this.databaseName,
|
|
148
189
|
type: asTableType(table.engine),
|
|
149
|
-
|
|
190
|
+
engine: table.engine,
|
|
191
|
+
columns: tableColumns,
|
|
192
|
+
indexes,
|
|
193
|
+
constraints
|
|
150
194
|
};
|
|
151
195
|
const comment = sanitize(table.comment);
|
|
152
196
|
if (comment !== void 0) {
|
|
153
197
|
base.comment = comment;
|
|
154
198
|
}
|
|
199
|
+
const statistics = buildTableStatistics(totalRows, totalBytes);
|
|
200
|
+
if (statistics) {
|
|
201
|
+
base.statistics = statistics;
|
|
202
|
+
}
|
|
155
203
|
return base;
|
|
156
204
|
});
|
|
157
205
|
return {
|
|
@@ -163,6 +211,10 @@ var ClickHouseAdapter = class {
|
|
|
163
211
|
introspectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
164
212
|
};
|
|
165
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Validate that the SQL query only references allowed tables.
|
|
216
|
+
* This is a basic validation that extracts table-like patterns from the query.
|
|
217
|
+
*/
|
|
166
218
|
validateQueryTables(sql) {
|
|
167
219
|
if (!this.allowedTables || this.allowedTables.length === 0) {
|
|
168
220
|
return;
|
|
@@ -240,15 +292,29 @@ function normalizeTableFilter(tables) {
|
|
|
240
292
|
return normalized;
|
|
241
293
|
}
|
|
242
294
|
function transformColumnRow(row) {
|
|
295
|
+
const nullable = isNullableType(row.type);
|
|
243
296
|
const unwrappedType = unwrapTypeModifiers(row.type);
|
|
297
|
+
const { precision, scale } = extractPrecisionScale(row.type);
|
|
298
|
+
const maxLength = extractFixedStringLength(row.type);
|
|
244
299
|
const column = {
|
|
245
300
|
name: row.name,
|
|
246
301
|
type: unwrappedType,
|
|
247
302
|
rawType: row.type,
|
|
248
|
-
|
|
303
|
+
nullable,
|
|
304
|
+
isPrimaryKey: Boolean(toNumber(row.is_in_primary_key)),
|
|
305
|
+
isForeignKey: false
|
|
249
306
|
};
|
|
307
|
+
const defaultKind = sanitize(row.default_kind);
|
|
308
|
+
if (defaultKind !== void 0) column.defaultKind = defaultKind;
|
|
309
|
+
const defaultExpression = sanitize(row.default_expression);
|
|
310
|
+
if (defaultExpression !== void 0) {
|
|
311
|
+
column.defaultExpression = defaultExpression;
|
|
312
|
+
}
|
|
250
313
|
const comment = sanitize(row.comment);
|
|
251
314
|
if (comment !== void 0) column.comment = comment;
|
|
315
|
+
if (maxLength !== void 0) column.maxLength = maxLength;
|
|
316
|
+
if (precision !== void 0) column.precision = precision;
|
|
317
|
+
if (scale !== void 0) column.scale = scale;
|
|
252
318
|
return column;
|
|
253
319
|
}
|
|
254
320
|
function asTableType(engine) {
|
|
@@ -260,6 +326,13 @@ function asTableType(engine) {
|
|
|
260
326
|
}
|
|
261
327
|
return "table";
|
|
262
328
|
}
|
|
329
|
+
function buildTableStatistics(totalRows, totalBytes) {
|
|
330
|
+
if (totalRows === void 0 && totalBytes === void 0) return void 0;
|
|
331
|
+
const stats = {};
|
|
332
|
+
if (totalRows !== void 0) stats.totalRows = totalRows;
|
|
333
|
+
if (totalBytes !== void 0) stats.totalBytes = totalBytes;
|
|
334
|
+
return stats;
|
|
335
|
+
}
|
|
263
336
|
function sanitize(value) {
|
|
264
337
|
if (value === null || value === void 0) return void 0;
|
|
265
338
|
const trimmed = String(value).trim();
|
|
@@ -302,6 +375,10 @@ var PostgresAdapter = class {
|
|
|
302
375
|
const fields = result.fields.map((f) => f.name);
|
|
303
376
|
return { fields, rows: result.rows };
|
|
304
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Validate that the SQL query only references allowed tables.
|
|
380
|
+
* This is a basic validation that extracts table-like patterns from the query.
|
|
381
|
+
*/
|
|
305
382
|
validateQueryTables(sql) {
|
|
306
383
|
if (!this.allowedTables || this.allowedTables.length === 0) {
|
|
307
384
|
return;
|
|
@@ -327,6 +404,11 @@ var PostgresAdapter = class {
|
|
|
327
404
|
/**
|
|
328
405
|
* Convert named params to positional array for PostgreSQL
|
|
329
406
|
* PostgreSQL expects $1, $2, $3 in SQL and an array of values [val1, val2, val3]
|
|
407
|
+
*
|
|
408
|
+
* Supports two formats:
|
|
409
|
+
* 1. Numeric keys: { '1': 'value1', '2': 'value2' } - maps directly to $1, $2
|
|
410
|
+
* 2. Named keys: { 'tenant_id': 'value' } - values extracted in alphabetical order
|
|
411
|
+
* 3. Mixed: { '1': 'value1', 'tenant_id': 'value' } - numeric keys first, then named keys
|
|
330
412
|
*/
|
|
331
413
|
convertNamedToPositionalParams(params) {
|
|
332
414
|
const numericKeys = Object.keys(params).filter((k) => /^\d+$/.test(k)).map((k) => Number.parseInt(k, 10)).sort((a, b) => a - b);
|
|
@@ -359,10 +441,6 @@ var PostgresAdapter = class {
|
|
|
359
441
|
getDialect() {
|
|
360
442
|
return "postgres";
|
|
361
443
|
}
|
|
362
|
-
/**
|
|
363
|
-
* Simplified introspection: only collect table/column metadata for IngestRequest
|
|
364
|
-
* No indexes, constraints, or statistics
|
|
365
|
-
*/
|
|
366
444
|
async introspect(options) {
|
|
367
445
|
const tablesToIntrospect = options?.tables ? normalizeTableFilter2(options.tables, this.defaultSchema) : this.allowedTables;
|
|
368
446
|
const normalizedTables = tablesToIntrospect ?? [];
|
|
@@ -374,20 +452,39 @@ var PostgresAdapter = class {
|
|
|
374
452
|
buildColumnsQuery(normalizedTables)
|
|
375
453
|
);
|
|
376
454
|
const columnRows = columnsResult.rows;
|
|
455
|
+
const constraintsResult = await this.clientFn(
|
|
456
|
+
buildConstraintsQuery(normalizedTables)
|
|
457
|
+
);
|
|
458
|
+
const constraintRows = constraintsResult.rows;
|
|
459
|
+
const indexesResult = await this.clientFn(
|
|
460
|
+
buildIndexesQuery(normalizedTables)
|
|
461
|
+
);
|
|
462
|
+
const indexRows = indexesResult.rows;
|
|
377
463
|
const tablesByKey = /* @__PURE__ */ new Map();
|
|
464
|
+
const columnsByKey = /* @__PURE__ */ new Map();
|
|
378
465
|
for (const row of tableRows) {
|
|
379
466
|
const key = tableKey(row.schema_name, row.table_name);
|
|
467
|
+
const statistics = buildTableStatistics2(
|
|
468
|
+
toNumber2(row.total_rows),
|
|
469
|
+
toNumber2(row.total_bytes)
|
|
470
|
+
);
|
|
380
471
|
const table = {
|
|
381
472
|
name: row.table_name,
|
|
382
473
|
schema: row.schema_name,
|
|
383
474
|
type: asTableType2(row.table_type),
|
|
384
|
-
columns: []
|
|
475
|
+
columns: [],
|
|
476
|
+
indexes: [],
|
|
477
|
+
constraints: []
|
|
385
478
|
};
|
|
386
479
|
const comment = sanitize2(row.comment);
|
|
387
480
|
if (comment !== void 0) {
|
|
388
481
|
table.comment = comment;
|
|
389
482
|
}
|
|
483
|
+
if (statistics) {
|
|
484
|
+
table.statistics = statistics;
|
|
485
|
+
}
|
|
390
486
|
tablesByKey.set(key, table);
|
|
487
|
+
columnsByKey.set(key, /* @__PURE__ */ new Map());
|
|
391
488
|
}
|
|
392
489
|
for (const row of columnRows) {
|
|
393
490
|
const key = tableKey(row.table_schema, row.table_name);
|
|
@@ -396,13 +493,80 @@ var PostgresAdapter = class {
|
|
|
396
493
|
const column = {
|
|
397
494
|
name: row.column_name,
|
|
398
495
|
type: row.data_type,
|
|
399
|
-
|
|
496
|
+
nullable: row.is_nullable.toUpperCase() === "YES",
|
|
497
|
+
isPrimaryKey: false,
|
|
498
|
+
isForeignKey: false
|
|
400
499
|
};
|
|
401
500
|
const rawType = row.udt_name ?? void 0;
|
|
402
501
|
if (rawType !== void 0) column.rawType = rawType;
|
|
502
|
+
const defaultExpression = sanitize2(row.column_default);
|
|
503
|
+
if (defaultExpression !== void 0)
|
|
504
|
+
column.defaultExpression = defaultExpression;
|
|
403
505
|
const comment = sanitize2(row.description);
|
|
404
506
|
if (comment !== void 0) column.comment = comment;
|
|
507
|
+
const maxLength = row.character_maximum_length ?? void 0;
|
|
508
|
+
if (maxLength !== void 0) column.maxLength = maxLength;
|
|
509
|
+
const precision = row.numeric_precision ?? void 0;
|
|
510
|
+
if (precision !== void 0) column.precision = precision;
|
|
511
|
+
const scale = row.numeric_scale ?? void 0;
|
|
512
|
+
if (scale !== void 0) column.scale = scale;
|
|
405
513
|
table.columns.push(column);
|
|
514
|
+
columnsByKey.get(key)?.set(row.column_name, column);
|
|
515
|
+
}
|
|
516
|
+
const constraintGroups = groupConstraints(constraintRows);
|
|
517
|
+
for (const group of constraintGroups) {
|
|
518
|
+
const key = tableKey(group.table_schema, group.table_name);
|
|
519
|
+
const table = tablesByKey.get(key);
|
|
520
|
+
if (!table) continue;
|
|
521
|
+
const constraint = {
|
|
522
|
+
name: group.constraint_name,
|
|
523
|
+
type: group.constraint_type,
|
|
524
|
+
columns: [...group.columns]
|
|
525
|
+
};
|
|
526
|
+
if (group.type === "FOREIGN KEY") {
|
|
527
|
+
if (group.foreign_table_name) {
|
|
528
|
+
const referencedTable = group.foreign_table_schema ? `${group.foreign_table_schema}.${group.foreign_table_name}` : group.foreign_table_name;
|
|
529
|
+
constraint.referencedTable = referencedTable;
|
|
530
|
+
}
|
|
531
|
+
if (group.foreign_columns.length) {
|
|
532
|
+
constraint.referencedColumns = [...group.foreign_columns];
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
table.constraints.push(constraint);
|
|
536
|
+
for (let index = 0; index < group.columns.length; index += 1) {
|
|
537
|
+
const columnName = group.columns[index];
|
|
538
|
+
if (!columnName) continue;
|
|
539
|
+
const column = columnsByKey.get(key)?.get(columnName);
|
|
540
|
+
if (!column) continue;
|
|
541
|
+
if (group.type === "PRIMARY KEY") {
|
|
542
|
+
column.isPrimaryKey = true;
|
|
543
|
+
}
|
|
544
|
+
if (group.type === "FOREIGN KEY") {
|
|
545
|
+
column.isForeignKey = true;
|
|
546
|
+
if (group.foreign_table_name) {
|
|
547
|
+
column.foreignKeyTable = group.foreign_table_schema ? `${group.foreign_table_schema}.${group.foreign_table_name}` : group.foreign_table_name;
|
|
548
|
+
}
|
|
549
|
+
const referencedColumn = group.foreign_columns[index];
|
|
550
|
+
if (referencedColumn) {
|
|
551
|
+
column.foreignKeyColumn = referencedColumn;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
for (const row of indexRows) {
|
|
557
|
+
const key = tableKey(row.schema_name, row.table_name);
|
|
558
|
+
const table = tablesByKey.get(key);
|
|
559
|
+
if (!table) continue;
|
|
560
|
+
const columns = coerceStringArray(row.column_names).map((c) => c.trim()).filter(Boolean);
|
|
561
|
+
const index = {
|
|
562
|
+
name: row.index_name,
|
|
563
|
+
columns,
|
|
564
|
+
unique: Boolean(row.indisunique),
|
|
565
|
+
type: columns.length === 1 ? "INDEX" : "COMPOSITE INDEX"
|
|
566
|
+
};
|
|
567
|
+
const definition = sanitize2(row.definition);
|
|
568
|
+
if (definition !== void 0) index.definition = definition;
|
|
569
|
+
table.indexes.push(index);
|
|
406
570
|
}
|
|
407
571
|
const tables = Array.from(tablesByKey.values()).sort((a, b) => {
|
|
408
572
|
if (a.schema === b.schema) {
|
|
@@ -420,6 +584,36 @@ var PostgresAdapter = class {
|
|
|
420
584
|
};
|
|
421
585
|
}
|
|
422
586
|
};
|
|
587
|
+
function groupConstraints(rows) {
|
|
588
|
+
const groups = /* @__PURE__ */ new Map();
|
|
589
|
+
for (const row of rows) {
|
|
590
|
+
const key = `${row.table_schema}.${row.table_name}.${row.constraint_name}`;
|
|
591
|
+
let group = groups.get(key);
|
|
592
|
+
if (!group) {
|
|
593
|
+
group = {
|
|
594
|
+
table_schema: row.table_schema,
|
|
595
|
+
table_name: row.table_name,
|
|
596
|
+
constraint_name: row.constraint_name,
|
|
597
|
+
constraint_type: row.constraint_type,
|
|
598
|
+
columns: [],
|
|
599
|
+
foreign_columns: [],
|
|
600
|
+
type: row.constraint_type
|
|
601
|
+
};
|
|
602
|
+
groups.set(key, group);
|
|
603
|
+
}
|
|
604
|
+
if (row.column_name) {
|
|
605
|
+
group.columns.push(row.column_name);
|
|
606
|
+
}
|
|
607
|
+
if (row.constraint_type === "FOREIGN KEY") {
|
|
608
|
+
group.foreign_table_schema = row.foreign_table_schema;
|
|
609
|
+
group.foreign_table_name = row.foreign_table_name;
|
|
610
|
+
if (row.foreign_column_name) {
|
|
611
|
+
group.foreign_columns.push(row.foreign_column_name);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return Array.from(groups.values());
|
|
616
|
+
}
|
|
423
617
|
function normalizeTableFilter2(tables, defaultSchema) {
|
|
424
618
|
if (!tables?.length) return [];
|
|
425
619
|
const normalized = [];
|
|
@@ -452,7 +646,9 @@ function buildTablesQuery(tables) {
|
|
|
452
646
|
WHEN 'm' THEN 'materialized_view'
|
|
453
647
|
ELSE c.relkind::text
|
|
454
648
|
END AS table_type,
|
|
455
|
-
obj_description(c.oid) AS comment
|
|
649
|
+
obj_description(c.oid) AS comment,
|
|
650
|
+
c.reltuples AS total_rows,
|
|
651
|
+
pg_total_relation_size(c.oid) AS total_bytes
|
|
456
652
|
FROM pg_class c
|
|
457
653
|
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
458
654
|
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
@@ -472,18 +668,13 @@ function buildColumnsQuery(tables) {
|
|
|
472
668
|
cols.column_name,
|
|
473
669
|
cols.data_type,
|
|
474
670
|
cols.udt_name,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
WHERE tc.constraint_type = 'PRIMARY KEY'
|
|
483
|
-
AND tc.table_schema = cols.table_schema
|
|
484
|
-
AND tc.table_name = cols.table_name
|
|
485
|
-
AND kcu.column_name = cols.column_name
|
|
486
|
-
) AS is_primary_key
|
|
671
|
+
cols.is_nullable,
|
|
672
|
+
cols.column_default,
|
|
673
|
+
cols.character_maximum_length,
|
|
674
|
+
cols.numeric_precision,
|
|
675
|
+
cols.numeric_scale,
|
|
676
|
+
cols.ordinal_position,
|
|
677
|
+
pgd.description
|
|
487
678
|
FROM information_schema.columns cols
|
|
488
679
|
LEFT JOIN pg_catalog.pg_class c
|
|
489
680
|
ON c.relname = cols.table_name
|
|
@@ -498,6 +689,50 @@ function buildColumnsQuery(tables) {
|
|
|
498
689
|
${filter}
|
|
499
690
|
ORDER BY cols.table_schema, cols.table_name, cols.ordinal_position;`;
|
|
500
691
|
}
|
|
692
|
+
function buildConstraintsQuery(tables) {
|
|
693
|
+
const filter = buildFilterClause(tables, "tc.table_schema", "tc.table_name");
|
|
694
|
+
return `SELECT
|
|
695
|
+
tc.table_schema,
|
|
696
|
+
tc.table_name,
|
|
697
|
+
tc.constraint_name,
|
|
698
|
+
tc.constraint_type,
|
|
699
|
+
kcu.column_name,
|
|
700
|
+
ccu.table_schema AS foreign_table_schema,
|
|
701
|
+
ccu.table_name AS foreign_table_name,
|
|
702
|
+
ccu.column_name AS foreign_column_name
|
|
703
|
+
FROM information_schema.table_constraints tc
|
|
704
|
+
LEFT JOIN information_schema.key_column_usage kcu
|
|
705
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
706
|
+
AND tc.table_schema = kcu.table_schema
|
|
707
|
+
LEFT JOIN information_schema.constraint_column_usage ccu
|
|
708
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
709
|
+
AND ccu.table_schema = tc.table_schema
|
|
710
|
+
WHERE tc.constraint_type IN ('PRIMARY KEY', 'UNIQUE', 'FOREIGN KEY')
|
|
711
|
+
AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')
|
|
712
|
+
${filter}
|
|
713
|
+
ORDER BY tc.table_schema, tc.table_name, tc.constraint_name, kcu.ordinal_position;`;
|
|
714
|
+
}
|
|
715
|
+
function buildIndexesQuery(tables) {
|
|
716
|
+
const filter = buildFilterClause(tables, "n.nspname", "c.relname");
|
|
717
|
+
return `SELECT
|
|
718
|
+
n.nspname AS schema_name,
|
|
719
|
+
c.relname AS table_name,
|
|
720
|
+
ci.relname AS index_name,
|
|
721
|
+
idx.indisunique,
|
|
722
|
+
array_remove(
|
|
723
|
+
array_agg(pg_get_indexdef(idx.indexrelid, g.k, true) ORDER BY g.k),
|
|
724
|
+
NULL
|
|
725
|
+
) AS column_names,
|
|
726
|
+
pg_get_indexdef(idx.indexrelid) AS definition
|
|
727
|
+
FROM pg_class c
|
|
728
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
729
|
+
JOIN pg_index idx ON idx.indrelid = c.oid
|
|
730
|
+
JOIN pg_class ci ON ci.oid = idx.indexrelid
|
|
731
|
+
JOIN LATERAL generate_subscripts(idx.indkey, 1) AS g(k) ON true
|
|
732
|
+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
|
|
733
|
+
${filter}
|
|
734
|
+
GROUP BY n.nspname, c.relname, ci.relname, idx.indisunique, idx.indexrelid;`;
|
|
735
|
+
}
|
|
501
736
|
function buildFilterClause(tables, schemaExpr, tableExpr) {
|
|
502
737
|
if (!tables.length) return "";
|
|
503
738
|
const clauses = tables.map(({ schema, table }) => {
|
|
@@ -518,1264 +753,568 @@ function asTableType2(value) {
|
|
|
518
753
|
}
|
|
519
754
|
return "table";
|
|
520
755
|
}
|
|
756
|
+
function buildTableStatistics2(totalRows, totalBytes) {
|
|
757
|
+
if (totalRows === void 0 && totalBytes === void 0) return void 0;
|
|
758
|
+
const stats = {};
|
|
759
|
+
if (totalRows !== void 0) stats.totalRows = totalRows;
|
|
760
|
+
if (totalBytes !== void 0) stats.totalBytes = totalBytes;
|
|
761
|
+
return stats;
|
|
762
|
+
}
|
|
521
763
|
function sanitize2(value) {
|
|
522
764
|
if (value === null || value === void 0) return void 0;
|
|
523
765
|
const trimmed = String(value).trim();
|
|
524
766
|
return trimmed.length ? trimmed : void 0;
|
|
525
767
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
function concat(...buffers) {
|
|
532
|
-
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
|
533
|
-
const buf = new Uint8Array(size);
|
|
534
|
-
let i = 0;
|
|
535
|
-
for (const buffer of buffers) {
|
|
536
|
-
buf.set(buffer, i);
|
|
537
|
-
i += buffer.length;
|
|
538
|
-
}
|
|
539
|
-
return buf;
|
|
540
|
-
}
|
|
541
|
-
function encode(string) {
|
|
542
|
-
const bytes = new Uint8Array(string.length);
|
|
543
|
-
for (let i = 0; i < string.length; i++) {
|
|
544
|
-
const code = string.charCodeAt(i);
|
|
545
|
-
if (code > 127) {
|
|
546
|
-
throw new TypeError("non-ASCII string encountered in encode()");
|
|
547
|
-
}
|
|
548
|
-
bytes[i] = code;
|
|
549
|
-
}
|
|
550
|
-
return bytes;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// node_modules/jose/dist/webapi/lib/base64.js
|
|
554
|
-
function encodeBase64(input) {
|
|
555
|
-
if (Uint8Array.prototype.toBase64) {
|
|
556
|
-
return input.toBase64();
|
|
557
|
-
}
|
|
558
|
-
const CHUNK_SIZE = 32768;
|
|
559
|
-
const arr = [];
|
|
560
|
-
for (let i = 0; i < input.length; i += CHUNK_SIZE) {
|
|
561
|
-
arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
562
|
-
}
|
|
563
|
-
return btoa(arr.join(""));
|
|
768
|
+
function toNumber2(value) {
|
|
769
|
+
if (value === null || value === void 0) return void 0;
|
|
770
|
+
if (typeof value === "number") return value;
|
|
771
|
+
const parsed = Number.parseFloat(String(value));
|
|
772
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
564
773
|
}
|
|
565
|
-
function
|
|
566
|
-
if (
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
return
|
|
774
|
+
function coerceStringArray(value) {
|
|
775
|
+
if (!value) return [];
|
|
776
|
+
if (Array.isArray(value)) {
|
|
777
|
+
return value.map((entry) => String(entry));
|
|
778
|
+
}
|
|
779
|
+
const text = String(value).trim();
|
|
780
|
+
if (!text) return [];
|
|
781
|
+
const withoutBraces = text.startsWith("{") && text.endsWith("}") ? text.slice(1, -1) : text;
|
|
782
|
+
if (!withoutBraces) return [];
|
|
783
|
+
return withoutBraces.split(",").map((part) => part.trim().replace(/^"(.+)"$/, "$1")).filter(Boolean);
|
|
575
784
|
}
|
|
576
785
|
|
|
577
|
-
//
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
786
|
+
// src/index.ts
|
|
787
|
+
var QueryPanelSdkAPI = class {
|
|
788
|
+
baseUrl;
|
|
789
|
+
privateKey;
|
|
790
|
+
organizationId;
|
|
791
|
+
defaultTenantId;
|
|
792
|
+
additionalHeaders;
|
|
793
|
+
fetchImpl;
|
|
794
|
+
cachedPrivateKey;
|
|
795
|
+
databases = /* @__PURE__ */ new Map();
|
|
796
|
+
databaseMetadata = /* @__PURE__ */ new Map();
|
|
797
|
+
defaultDatabase;
|
|
798
|
+
lastSyncHashes = /* @__PURE__ */ new Map();
|
|
799
|
+
syncedDatabases = /* @__PURE__ */ new Set();
|
|
800
|
+
constructor(baseUrl, privateKey, organizationId, options) {
|
|
801
|
+
if (!baseUrl) {
|
|
802
|
+
throw new Error("Base URL is required");
|
|
803
|
+
}
|
|
804
|
+
if (!privateKey) {
|
|
805
|
+
throw new Error("Private key is required");
|
|
806
|
+
}
|
|
807
|
+
if (!organizationId) {
|
|
808
|
+
throw new Error("Organization ID is required");
|
|
809
|
+
}
|
|
810
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
811
|
+
this.privateKey = privateKey;
|
|
812
|
+
this.organizationId = organizationId;
|
|
813
|
+
this.defaultTenantId = options?.defaultTenantId;
|
|
814
|
+
this.additionalHeaders = options?.additionalHeaders;
|
|
815
|
+
this.fetchImpl = options?.fetch ?? globalThis.fetch;
|
|
816
|
+
if (!this.fetchImpl) {
|
|
817
|
+
throw new Error(
|
|
818
|
+
"Fetch implementation not found. Provide options.fetch or use Node 18+."
|
|
819
|
+
);
|
|
820
|
+
}
|
|
587
821
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
822
|
+
attachClickhouse(name, clientFn, options) {
|
|
823
|
+
const adapter = new ClickHouseAdapter(clientFn, options);
|
|
824
|
+
this.attachDatabase(name, adapter);
|
|
825
|
+
const metadata = {
|
|
826
|
+
name,
|
|
827
|
+
dialect: "clickhouse",
|
|
828
|
+
description: options?.description,
|
|
829
|
+
tags: options?.tags,
|
|
830
|
+
tenantFieldName: options?.tenantFieldName,
|
|
831
|
+
tenantFieldType: options?.tenantFieldType ?? "String",
|
|
832
|
+
enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
|
|
833
|
+
};
|
|
834
|
+
this.databaseMetadata.set(name, metadata);
|
|
593
835
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
836
|
+
attachPostgres(name, clientFn, options) {
|
|
837
|
+
const adapter = new PostgresAdapter(clientFn, options);
|
|
838
|
+
this.attachDatabase(name, adapter);
|
|
839
|
+
const metadata = {
|
|
840
|
+
name,
|
|
841
|
+
dialect: "postgres",
|
|
842
|
+
description: options?.description,
|
|
843
|
+
tags: options?.tags,
|
|
844
|
+
tenantFieldName: options?.tenantFieldName,
|
|
845
|
+
enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
|
|
846
|
+
};
|
|
847
|
+
this.databaseMetadata.set(name, metadata);
|
|
599
848
|
}
|
|
600
|
-
|
|
601
|
-
|
|
849
|
+
attachDatabase(name, adapter) {
|
|
850
|
+
this.databases.set(name, adapter);
|
|
851
|
+
if (!this.defaultDatabase) {
|
|
852
|
+
this.defaultDatabase = name;
|
|
853
|
+
}
|
|
602
854
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
855
|
+
async syncSchema(databaseName, options, signal) {
|
|
856
|
+
const tenantId = this.resolveTenantId(options.tenantId);
|
|
857
|
+
const adapter = this.getDatabase(databaseName);
|
|
858
|
+
const introspection = await adapter.introspect(
|
|
859
|
+
options.tables ? { tables: options.tables } : void 0
|
|
860
|
+
);
|
|
861
|
+
const payload = this.buildSchemaRequest(
|
|
862
|
+
databaseName,
|
|
863
|
+
adapter,
|
|
864
|
+
introspection
|
|
865
|
+
);
|
|
866
|
+
const hash = this.hashSchemaRequest(payload);
|
|
867
|
+
const previousHash = this.lastSyncHashes.get(databaseName);
|
|
868
|
+
if (!options.force && previousHash === hash) {
|
|
869
|
+
return {
|
|
870
|
+
success: true,
|
|
871
|
+
message: "Schema unchanged; skipping ingestion",
|
|
872
|
+
chunks: 0,
|
|
873
|
+
chunks_with_annotations: 0,
|
|
874
|
+
schema_hash: hash,
|
|
875
|
+
skipped: true
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
const sessionId = randomUUID();
|
|
879
|
+
const response = await this.post(
|
|
880
|
+
"/ingest",
|
|
881
|
+
payload,
|
|
882
|
+
tenantId,
|
|
883
|
+
options.userId,
|
|
884
|
+
options.scopes,
|
|
885
|
+
signal,
|
|
886
|
+
sessionId
|
|
887
|
+
);
|
|
888
|
+
this.lastSyncHashes.set(databaseName, hash);
|
|
889
|
+
this.syncedDatabases.add(databaseName);
|
|
890
|
+
return response;
|
|
614
891
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
return parseInt(hash.name.slice(4), 10);
|
|
634
|
-
}
|
|
635
|
-
function getNamedCurve(alg) {
|
|
636
|
-
switch (alg) {
|
|
637
|
-
case "ES256":
|
|
638
|
-
return "P-256";
|
|
639
|
-
case "ES384":
|
|
640
|
-
return "P-384";
|
|
641
|
-
case "ES512":
|
|
642
|
-
return "P-521";
|
|
643
|
-
default:
|
|
644
|
-
throw new Error("unreachable");
|
|
892
|
+
async ingestKnowledgeBaseChunks(payload, options, signal) {
|
|
893
|
+
const tenantId = this.resolveTenantId(
|
|
894
|
+
payload.tenantId ?? options?.tenantId
|
|
895
|
+
);
|
|
896
|
+
return await this.post(
|
|
897
|
+
"/knowledge-base/chunks",
|
|
898
|
+
{
|
|
899
|
+
organization_id: this.organizationId,
|
|
900
|
+
tenant_id: tenantId,
|
|
901
|
+
database: payload.database,
|
|
902
|
+
dialect: payload.dialect,
|
|
903
|
+
tables: payload.tables
|
|
904
|
+
},
|
|
905
|
+
tenantId,
|
|
906
|
+
options?.userId,
|
|
907
|
+
options?.scopes,
|
|
908
|
+
signal
|
|
909
|
+
);
|
|
645
910
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
911
|
+
async introspect(databaseName, tables) {
|
|
912
|
+
const adapter = this.getDatabase(databaseName);
|
|
913
|
+
return await adapter.introspect(tables ? { tables } : void 0);
|
|
650
914
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
if (!isAlgorithm(key.algorithm, "RSA-PSS"))
|
|
680
|
-
throw unusable("RSA-PSS");
|
|
681
|
-
const expected = parseInt(alg.slice(2), 10);
|
|
682
|
-
const actual = getHashLength(key.algorithm.hash);
|
|
683
|
-
if (actual !== expected)
|
|
684
|
-
throw unusable(`SHA-${expected}`, "algorithm.hash");
|
|
685
|
-
break;
|
|
686
|
-
}
|
|
687
|
-
case "Ed25519":
|
|
688
|
-
case "EdDSA": {
|
|
689
|
-
if (!isAlgorithm(key.algorithm, "Ed25519"))
|
|
690
|
-
throw unusable("Ed25519");
|
|
691
|
-
break;
|
|
915
|
+
async ask(question, options, signal) {
|
|
916
|
+
const tenantId = this.resolveTenantId(options.tenantId);
|
|
917
|
+
await this.ensureSchemasSynced(
|
|
918
|
+
tenantId,
|
|
919
|
+
options.userId,
|
|
920
|
+
options.scopes,
|
|
921
|
+
options.disableAutoSync
|
|
922
|
+
);
|
|
923
|
+
const sessionId = randomUUID();
|
|
924
|
+
const queryResponse = await this.post(
|
|
925
|
+
"/query",
|
|
926
|
+
{
|
|
927
|
+
question,
|
|
928
|
+
...options.lastError ? { last_error: options.lastError } : {},
|
|
929
|
+
...options.previousSql ? { previous_sql: options.previousSql } : {},
|
|
930
|
+
...options.maxRetry ? { max_retry: options.maxRetry } : {}
|
|
931
|
+
},
|
|
932
|
+
tenantId,
|
|
933
|
+
options.userId,
|
|
934
|
+
options.scopes,
|
|
935
|
+
signal,
|
|
936
|
+
sessionId
|
|
937
|
+
);
|
|
938
|
+
const databaseName = options.database ?? this.defaultDatabase;
|
|
939
|
+
if (!databaseName) {
|
|
940
|
+
throw new Error(
|
|
941
|
+
"No database attached. Call attachPostgres/attachClickhouse first."
|
|
942
|
+
);
|
|
692
943
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
944
|
+
const adapter = this.getDatabase(databaseName);
|
|
945
|
+
const paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
|
|
946
|
+
const paramValues = this.mapGeneratedParams(paramMetadata);
|
|
947
|
+
const metadata = this.databaseMetadata.get(databaseName);
|
|
948
|
+
if (metadata) {
|
|
949
|
+
queryResponse.sql = this.ensureTenantIsolation(
|
|
950
|
+
queryResponse.sql,
|
|
951
|
+
paramValues,
|
|
952
|
+
metadata,
|
|
953
|
+
tenantId
|
|
954
|
+
);
|
|
699
955
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
956
|
+
await adapter.validate(queryResponse.sql, paramValues);
|
|
957
|
+
const execution = await adapter.execute(queryResponse.sql, paramValues);
|
|
958
|
+
const rows = execution.rows ?? [];
|
|
959
|
+
let chart = {
|
|
960
|
+
vegaLiteSpec: null,
|
|
961
|
+
notes: rows.length === 0 ? "Query returned no rows." : null
|
|
962
|
+
};
|
|
963
|
+
if (rows.length > 0) {
|
|
964
|
+
const chartResponse = await this.post(
|
|
965
|
+
"/chart",
|
|
966
|
+
{
|
|
967
|
+
question,
|
|
968
|
+
sql: queryResponse.sql,
|
|
969
|
+
rationale: queryResponse.rationale,
|
|
970
|
+
fields: execution.fields,
|
|
971
|
+
rows: anonymizeResults(rows),
|
|
972
|
+
max_retries: options.chartMaxRetries ?? 3,
|
|
973
|
+
query_id: queryResponse.queryId
|
|
974
|
+
},
|
|
975
|
+
tenantId,
|
|
976
|
+
options.userId,
|
|
977
|
+
options.scopes,
|
|
978
|
+
signal,
|
|
979
|
+
sessionId
|
|
980
|
+
);
|
|
981
|
+
chart = {
|
|
982
|
+
vegaLiteSpec: chartResponse.chart ? {
|
|
983
|
+
...chartResponse.chart,
|
|
984
|
+
data: { values: rows }
|
|
985
|
+
} : null,
|
|
986
|
+
notes: chartResponse.notes
|
|
987
|
+
};
|
|
710
988
|
}
|
|
711
|
-
|
|
712
|
-
|
|
989
|
+
return {
|
|
990
|
+
sql: queryResponse.sql,
|
|
991
|
+
params: paramValues,
|
|
992
|
+
paramMetadata,
|
|
993
|
+
rationale: queryResponse.rationale,
|
|
994
|
+
dialect: queryResponse.dialect,
|
|
995
|
+
queryId: queryResponse.queryId,
|
|
996
|
+
rows,
|
|
997
|
+
fields: execution.fields,
|
|
998
|
+
chart,
|
|
999
|
+
context: queryResponse.context
|
|
1000
|
+
};
|
|
713
1001
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
msg += ` Received function ${actual.name}`;
|
|
732
|
-
} else if (typeof actual === "object" && actual != null) {
|
|
733
|
-
if (actual.constructor?.name) {
|
|
734
|
-
msg += ` Received an instance of ${actual.constructor.name}`;
|
|
735
|
-
}
|
|
1002
|
+
async upsertAnnotation(input, options, signal) {
|
|
1003
|
+
const tenantId = this.resolveTenantId(input.tenantId ?? options?.tenantId);
|
|
1004
|
+
const response = await this.post(
|
|
1005
|
+
"/knowledge-base/annotations",
|
|
1006
|
+
{
|
|
1007
|
+
organization_id: this.organizationId,
|
|
1008
|
+
tenant_id: tenantId,
|
|
1009
|
+
target_identifier: input.targetIdentifier,
|
|
1010
|
+
content: input.content,
|
|
1011
|
+
user_id: input.userId
|
|
1012
|
+
},
|
|
1013
|
+
tenantId,
|
|
1014
|
+
options?.userId,
|
|
1015
|
+
options?.scopes,
|
|
1016
|
+
signal
|
|
1017
|
+
);
|
|
1018
|
+
return response.annotation;
|
|
736
1019
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
return key instanceof CryptoKey;
|
|
748
|
-
} catch {
|
|
749
|
-
return false;
|
|
1020
|
+
async listAnnotations(options, signal) {
|
|
1021
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1022
|
+
const response = await this.get(
|
|
1023
|
+
"/knowledge-base/annotations",
|
|
1024
|
+
tenantId,
|
|
1025
|
+
options?.userId,
|
|
1026
|
+
options?.scopes,
|
|
1027
|
+
signal
|
|
1028
|
+
);
|
|
1029
|
+
return response.annotations;
|
|
750
1030
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
for (const header of sources) {
|
|
763
|
-
const parameters = Object.keys(header);
|
|
764
|
-
if (!acc || acc.size === 0) {
|
|
765
|
-
acc = new Set(parameters);
|
|
766
|
-
continue;
|
|
767
|
-
}
|
|
768
|
-
for (const parameter of parameters) {
|
|
769
|
-
if (acc.has(parameter)) {
|
|
770
|
-
return false;
|
|
1031
|
+
async getAnnotation(targetIdentifier, options, signal) {
|
|
1032
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1033
|
+
const response = await this.get(
|
|
1034
|
+
`/knowledge-base/annotations/${encodeURIComponent(targetIdentifier)}`,
|
|
1035
|
+
tenantId,
|
|
1036
|
+
options?.userId,
|
|
1037
|
+
options?.scopes,
|
|
1038
|
+
signal
|
|
1039
|
+
).catch((error) => {
|
|
1040
|
+
if (error?.status === 404) {
|
|
1041
|
+
return { success: false, annotation: null };
|
|
771
1042
|
}
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
return true;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
// node_modules/jose/dist/webapi/lib/is_object.js
|
|
779
|
-
var isObjectLike = (value) => typeof value === "object" && value !== null;
|
|
780
|
-
function isObject(input) {
|
|
781
|
-
if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") {
|
|
782
|
-
return false;
|
|
1043
|
+
throw error;
|
|
1044
|
+
});
|
|
1045
|
+
return response.annotation ?? null;
|
|
783
1046
|
}
|
|
784
|
-
|
|
785
|
-
|
|
1047
|
+
async deleteAnnotation(targetIdentifier, options, signal) {
|
|
1048
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1049
|
+
await this.delete(
|
|
1050
|
+
`/knowledge-base/annotations/${encodeURIComponent(targetIdentifier)}`,
|
|
1051
|
+
tenantId,
|
|
1052
|
+
options?.userId,
|
|
1053
|
+
options?.scopes,
|
|
1054
|
+
signal
|
|
1055
|
+
);
|
|
786
1056
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
1057
|
+
async createChart(body, options, signal) {
|
|
1058
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1059
|
+
return await this.post(
|
|
1060
|
+
"/charts",
|
|
1061
|
+
body,
|
|
1062
|
+
tenantId,
|
|
1063
|
+
options?.userId,
|
|
1064
|
+
options?.scopes,
|
|
1065
|
+
signal
|
|
1066
|
+
);
|
|
790
1067
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if (
|
|
799
|
-
|
|
1068
|
+
async listCharts(options, signal) {
|
|
1069
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1070
|
+
const params = new URLSearchParams();
|
|
1071
|
+
if (options?.pagination?.page)
|
|
1072
|
+
params.set("page", `${options.pagination.page}`);
|
|
1073
|
+
if (options?.pagination?.limit)
|
|
1074
|
+
params.set("limit", `${options.pagination.limit}`);
|
|
1075
|
+
if (options?.sortBy) params.set("sort_by", options.sortBy);
|
|
1076
|
+
if (options?.sortDir) params.set("sort_dir", options.sortDir);
|
|
1077
|
+
if (options?.title) params.set("title", options.title);
|
|
1078
|
+
if (options?.userFilter) params.set("user_id", options.userFilter);
|
|
1079
|
+
if (options?.createdFrom) params.set("created_from", options.createdFrom);
|
|
1080
|
+
if (options?.createdTo) params.set("created_to", options.createdTo);
|
|
1081
|
+
if (options?.updatedFrom) params.set("updated_from", options.updatedFrom);
|
|
1082
|
+
if (options?.updatedTo) params.set("updated_to", options.updatedTo);
|
|
1083
|
+
const response = await this.get(
|
|
1084
|
+
`/charts${params.toString() ? `?${params.toString()}` : ""}`,
|
|
1085
|
+
tenantId,
|
|
1086
|
+
options?.userId,
|
|
1087
|
+
options?.scopes,
|
|
1088
|
+
signal
|
|
1089
|
+
);
|
|
1090
|
+
if (options?.includeData) {
|
|
1091
|
+
response.data = await Promise.all(
|
|
1092
|
+
response.data.map(async (chart) => ({
|
|
1093
|
+
...chart,
|
|
1094
|
+
vega_lite_spec: {
|
|
1095
|
+
...chart.vega_lite_spec,
|
|
1096
|
+
data: {
|
|
1097
|
+
values: await this.runSafeQueryOnClient(
|
|
1098
|
+
chart.sql,
|
|
1099
|
+
chart.database ?? void 0,
|
|
1100
|
+
chart.sql_params ?? void 0
|
|
1101
|
+
)
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
}))
|
|
1105
|
+
);
|
|
800
1106
|
}
|
|
1107
|
+
return response;
|
|
801
1108
|
}
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
length = length << 8 | state.data[state.pos++];
|
|
822
|
-
}
|
|
823
|
-
return length;
|
|
824
|
-
}
|
|
825
|
-
return first;
|
|
826
|
-
};
|
|
827
|
-
var expectTag = (state, expectedTag, errorMessage) => {
|
|
828
|
-
if (state.data[state.pos++] !== expectedTag) {
|
|
829
|
-
throw new Error(errorMessage);
|
|
830
|
-
}
|
|
831
|
-
};
|
|
832
|
-
var getSubarray = (state, length) => {
|
|
833
|
-
const result = state.data.subarray(state.pos, state.pos + length);
|
|
834
|
-
state.pos += length;
|
|
835
|
-
return result;
|
|
836
|
-
};
|
|
837
|
-
var parseAlgorithmOID = (state) => {
|
|
838
|
-
expectTag(state, 6, "Expected algorithm OID");
|
|
839
|
-
const oidLen = parseLength(state);
|
|
840
|
-
return getSubarray(state, oidLen);
|
|
841
|
-
};
|
|
842
|
-
function parsePKCS8Header(state) {
|
|
843
|
-
expectTag(state, 48, "Invalid PKCS#8 structure");
|
|
844
|
-
parseLength(state);
|
|
845
|
-
expectTag(state, 2, "Expected version field");
|
|
846
|
-
const verLen = parseLength(state);
|
|
847
|
-
state.pos += verLen;
|
|
848
|
-
expectTag(state, 48, "Expected algorithm identifier");
|
|
849
|
-
const algIdLen = parseLength(state);
|
|
850
|
-
const algIdStart = state.pos;
|
|
851
|
-
return { algIdStart, algIdLength: algIdLen };
|
|
852
|
-
}
|
|
853
|
-
var parseECAlgorithmIdentifier = (state) => {
|
|
854
|
-
const algOid = parseAlgorithmOID(state);
|
|
855
|
-
if (bytesEqual(algOid, [43, 101, 110])) {
|
|
856
|
-
return "X25519";
|
|
857
|
-
}
|
|
858
|
-
if (!bytesEqual(algOid, [42, 134, 72, 206, 61, 2, 1])) {
|
|
859
|
-
throw new Error("Unsupported key algorithm");
|
|
860
|
-
}
|
|
861
|
-
expectTag(state, 6, "Expected curve OID");
|
|
862
|
-
const curveOidLen = parseLength(state);
|
|
863
|
-
const curveOid = getSubarray(state, curveOidLen);
|
|
864
|
-
for (const { name, oid } of [
|
|
865
|
-
{ name: "P-256", oid: [42, 134, 72, 206, 61, 3, 1, 7] },
|
|
866
|
-
{ name: "P-384", oid: [43, 129, 4, 0, 34] },
|
|
867
|
-
{ name: "P-521", oid: [43, 129, 4, 0, 35] }
|
|
868
|
-
]) {
|
|
869
|
-
if (bytesEqual(curveOid, oid)) {
|
|
870
|
-
return name;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
throw new Error("Unsupported named curve");
|
|
874
|
-
};
|
|
875
|
-
var genericImport = async (keyFormat, keyData, alg, options) => {
|
|
876
|
-
let algorithm;
|
|
877
|
-
let keyUsages;
|
|
878
|
-
const isPublic = keyFormat === "spki";
|
|
879
|
-
const getSigUsages = () => isPublic ? ["verify"] : ["sign"];
|
|
880
|
-
const getEncUsages = () => isPublic ? ["encrypt", "wrapKey"] : ["decrypt", "unwrapKey"];
|
|
881
|
-
switch (alg) {
|
|
882
|
-
case "PS256":
|
|
883
|
-
case "PS384":
|
|
884
|
-
case "PS512":
|
|
885
|
-
algorithm = { name: "RSA-PSS", hash: `SHA-${alg.slice(-3)}` };
|
|
886
|
-
keyUsages = getSigUsages();
|
|
887
|
-
break;
|
|
888
|
-
case "RS256":
|
|
889
|
-
case "RS384":
|
|
890
|
-
case "RS512":
|
|
891
|
-
algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${alg.slice(-3)}` };
|
|
892
|
-
keyUsages = getSigUsages();
|
|
893
|
-
break;
|
|
894
|
-
case "RSA-OAEP":
|
|
895
|
-
case "RSA-OAEP-256":
|
|
896
|
-
case "RSA-OAEP-384":
|
|
897
|
-
case "RSA-OAEP-512":
|
|
898
|
-
algorithm = {
|
|
899
|
-
name: "RSA-OAEP",
|
|
900
|
-
hash: `SHA-${parseInt(alg.slice(-3), 10) || 1}`
|
|
901
|
-
};
|
|
902
|
-
keyUsages = getEncUsages();
|
|
903
|
-
break;
|
|
904
|
-
case "ES256":
|
|
905
|
-
case "ES384":
|
|
906
|
-
case "ES512": {
|
|
907
|
-
const curveMap = { ES256: "P-256", ES384: "P-384", ES512: "P-521" };
|
|
908
|
-
algorithm = { name: "ECDSA", namedCurve: curveMap[alg] };
|
|
909
|
-
keyUsages = getSigUsages();
|
|
910
|
-
break;
|
|
911
|
-
}
|
|
912
|
-
case "ECDH-ES":
|
|
913
|
-
case "ECDH-ES+A128KW":
|
|
914
|
-
case "ECDH-ES+A192KW":
|
|
915
|
-
case "ECDH-ES+A256KW": {
|
|
916
|
-
try {
|
|
917
|
-
const namedCurve = options.getNamedCurve(keyData);
|
|
918
|
-
algorithm = namedCurve === "X25519" ? { name: "X25519" } : { name: "ECDH", namedCurve };
|
|
919
|
-
} catch (cause) {
|
|
920
|
-
throw new JOSENotSupported("Invalid or unsupported key format");
|
|
921
|
-
}
|
|
922
|
-
keyUsages = isPublic ? [] : ["deriveBits"];
|
|
923
|
-
break;
|
|
924
|
-
}
|
|
925
|
-
case "Ed25519":
|
|
926
|
-
case "EdDSA":
|
|
927
|
-
algorithm = { name: "Ed25519" };
|
|
928
|
-
keyUsages = getSigUsages();
|
|
929
|
-
break;
|
|
930
|
-
case "ML-DSA-44":
|
|
931
|
-
case "ML-DSA-65":
|
|
932
|
-
case "ML-DSA-87":
|
|
933
|
-
algorithm = { name: alg };
|
|
934
|
-
keyUsages = getSigUsages();
|
|
935
|
-
break;
|
|
936
|
-
default:
|
|
937
|
-
throw new JOSENotSupported('Invalid or unsupported "alg" (Algorithm) value');
|
|
938
|
-
}
|
|
939
|
-
return crypto.subtle.importKey(keyFormat, keyData, algorithm, options?.extractable ?? (isPublic ? true : false), keyUsages);
|
|
940
|
-
};
|
|
941
|
-
var processPEMData = (pem, pattern) => {
|
|
942
|
-
return decodeBase64(pem.replace(pattern, ""));
|
|
943
|
-
};
|
|
944
|
-
var fromPKCS8 = (pem, alg, options) => {
|
|
945
|
-
const keyData = processPEMData(pem, /(?:-----(?:BEGIN|END) PRIVATE KEY-----|\s)/g);
|
|
946
|
-
let opts = options;
|
|
947
|
-
if (alg?.startsWith?.("ECDH-ES")) {
|
|
948
|
-
opts ||= {};
|
|
949
|
-
opts.getNamedCurve = (keyData2) => {
|
|
950
|
-
const state = createASN1State(keyData2);
|
|
951
|
-
parsePKCS8Header(state);
|
|
952
|
-
return parseECAlgorithmIdentifier(state);
|
|
953
|
-
};
|
|
954
|
-
}
|
|
955
|
-
return genericImport("pkcs8", keyData, alg, opts);
|
|
956
|
-
};
|
|
957
|
-
|
|
958
|
-
// node_modules/jose/dist/webapi/lib/jwk_to_key.js
|
|
959
|
-
function subtleMapping(jwk) {
|
|
960
|
-
let algorithm;
|
|
961
|
-
let keyUsages;
|
|
962
|
-
switch (jwk.kty) {
|
|
963
|
-
case "AKP": {
|
|
964
|
-
switch (jwk.alg) {
|
|
965
|
-
case "ML-DSA-44":
|
|
966
|
-
case "ML-DSA-65":
|
|
967
|
-
case "ML-DSA-87":
|
|
968
|
-
algorithm = { name: jwk.alg };
|
|
969
|
-
keyUsages = jwk.priv ? ["sign"] : ["verify"];
|
|
970
|
-
break;
|
|
971
|
-
default:
|
|
972
|
-
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
973
|
-
}
|
|
974
|
-
break;
|
|
975
|
-
}
|
|
976
|
-
case "RSA": {
|
|
977
|
-
switch (jwk.alg) {
|
|
978
|
-
case "PS256":
|
|
979
|
-
case "PS384":
|
|
980
|
-
case "PS512":
|
|
981
|
-
algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` };
|
|
982
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
983
|
-
break;
|
|
984
|
-
case "RS256":
|
|
985
|
-
case "RS384":
|
|
986
|
-
case "RS512":
|
|
987
|
-
algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` };
|
|
988
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
989
|
-
break;
|
|
990
|
-
case "RSA-OAEP":
|
|
991
|
-
case "RSA-OAEP-256":
|
|
992
|
-
case "RSA-OAEP-384":
|
|
993
|
-
case "RSA-OAEP-512":
|
|
994
|
-
algorithm = {
|
|
995
|
-
name: "RSA-OAEP",
|
|
996
|
-
hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`
|
|
997
|
-
};
|
|
998
|
-
keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
|
|
999
|
-
break;
|
|
1000
|
-
default:
|
|
1001
|
-
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
1002
|
-
}
|
|
1003
|
-
break;
|
|
1004
|
-
}
|
|
1005
|
-
case "EC": {
|
|
1006
|
-
switch (jwk.alg) {
|
|
1007
|
-
case "ES256":
|
|
1008
|
-
algorithm = { name: "ECDSA", namedCurve: "P-256" };
|
|
1009
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
1010
|
-
break;
|
|
1011
|
-
case "ES384":
|
|
1012
|
-
algorithm = { name: "ECDSA", namedCurve: "P-384" };
|
|
1013
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
1014
|
-
break;
|
|
1015
|
-
case "ES512":
|
|
1016
|
-
algorithm = { name: "ECDSA", namedCurve: "P-521" };
|
|
1017
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
1018
|
-
break;
|
|
1019
|
-
case "ECDH-ES":
|
|
1020
|
-
case "ECDH-ES+A128KW":
|
|
1021
|
-
case "ECDH-ES+A192KW":
|
|
1022
|
-
case "ECDH-ES+A256KW":
|
|
1023
|
-
algorithm = { name: "ECDH", namedCurve: jwk.crv };
|
|
1024
|
-
keyUsages = jwk.d ? ["deriveBits"] : [];
|
|
1025
|
-
break;
|
|
1026
|
-
default:
|
|
1027
|
-
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
1028
|
-
}
|
|
1029
|
-
break;
|
|
1030
|
-
}
|
|
1031
|
-
case "OKP": {
|
|
1032
|
-
switch (jwk.alg) {
|
|
1033
|
-
case "Ed25519":
|
|
1034
|
-
case "EdDSA":
|
|
1035
|
-
algorithm = { name: "Ed25519" };
|
|
1036
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
1037
|
-
break;
|
|
1038
|
-
case "ECDH-ES":
|
|
1039
|
-
case "ECDH-ES+A128KW":
|
|
1040
|
-
case "ECDH-ES+A192KW":
|
|
1041
|
-
case "ECDH-ES+A256KW":
|
|
1042
|
-
algorithm = { name: jwk.crv };
|
|
1043
|
-
keyUsages = jwk.d ? ["deriveBits"] : [];
|
|
1044
|
-
break;
|
|
1045
|
-
default:
|
|
1046
|
-
throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
|
|
1047
|
-
}
|
|
1048
|
-
break;
|
|
1049
|
-
}
|
|
1050
|
-
default:
|
|
1051
|
-
throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value');
|
|
1052
|
-
}
|
|
1053
|
-
return { algorithm, keyUsages };
|
|
1054
|
-
}
|
|
1055
|
-
async function jwkToKey(jwk) {
|
|
1056
|
-
if (!jwk.alg) {
|
|
1057
|
-
throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
|
|
1058
|
-
}
|
|
1059
|
-
const { algorithm, keyUsages } = subtleMapping(jwk);
|
|
1060
|
-
const keyData = { ...jwk };
|
|
1061
|
-
if (keyData.kty !== "AKP") {
|
|
1062
|
-
delete keyData.alg;
|
|
1063
|
-
}
|
|
1064
|
-
delete keyData.use;
|
|
1065
|
-
return crypto.subtle.importKey("jwk", keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
// node_modules/jose/dist/webapi/key/import.js
|
|
1069
|
-
async function importPKCS8(pkcs8, alg, options) {
|
|
1070
|
-
if (typeof pkcs8 !== "string" || pkcs8.indexOf("-----BEGIN PRIVATE KEY-----") !== 0) {
|
|
1071
|
-
throw new TypeError('"pkcs8" must be PKCS#8 formatted string');
|
|
1072
|
-
}
|
|
1073
|
-
return fromPKCS8(pkcs8, alg, options);
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
// node_modules/jose/dist/webapi/lib/validate_crit.js
|
|
1077
|
-
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
|
|
1078
|
-
if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0) {
|
|
1079
|
-
throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
|
|
1080
|
-
}
|
|
1081
|
-
if (!protectedHeader || protectedHeader.crit === void 0) {
|
|
1082
|
-
return /* @__PURE__ */ new Set();
|
|
1083
|
-
}
|
|
1084
|
-
if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) {
|
|
1085
|
-
throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
|
|
1086
|
-
}
|
|
1087
|
-
let recognized;
|
|
1088
|
-
if (recognizedOption !== void 0) {
|
|
1089
|
-
recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
|
|
1090
|
-
} else {
|
|
1091
|
-
recognized = recognizedDefault;
|
|
1092
|
-
}
|
|
1093
|
-
for (const parameter of protectedHeader.crit) {
|
|
1094
|
-
if (!recognized.has(parameter)) {
|
|
1095
|
-
throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
|
|
1096
|
-
}
|
|
1097
|
-
if (joseHeader[parameter] === void 0) {
|
|
1098
|
-
throw new Err(`Extension Header Parameter "${parameter}" is missing`);
|
|
1099
|
-
}
|
|
1100
|
-
if (recognized.get(parameter) && protectedHeader[parameter] === void 0) {
|
|
1101
|
-
throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
return new Set(protectedHeader.crit);
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
// node_modules/jose/dist/webapi/lib/is_jwk.js
|
|
1108
|
-
var isJWK = (key) => isObject(key) && typeof key.kty === "string";
|
|
1109
|
-
var isPrivateJWK = (key) => key.kty !== "oct" && (key.kty === "AKP" && typeof key.priv === "string" || typeof key.d === "string");
|
|
1110
|
-
var isPublicJWK = (key) => key.kty !== "oct" && key.d === void 0 && key.priv === void 0;
|
|
1111
|
-
var isSecretJWK = (key) => key.kty === "oct" && typeof key.k === "string";
|
|
1112
|
-
|
|
1113
|
-
// node_modules/jose/dist/webapi/lib/normalize_key.js
|
|
1114
|
-
var cache;
|
|
1115
|
-
var handleJWK = async (key, jwk, alg, freeze = false) => {
|
|
1116
|
-
cache ||= /* @__PURE__ */ new WeakMap();
|
|
1117
|
-
let cached = cache.get(key);
|
|
1118
|
-
if (cached?.[alg]) {
|
|
1119
|
-
return cached[alg];
|
|
1120
|
-
}
|
|
1121
|
-
const cryptoKey = await jwkToKey({ ...jwk, alg });
|
|
1122
|
-
if (freeze)
|
|
1123
|
-
Object.freeze(key);
|
|
1124
|
-
if (!cached) {
|
|
1125
|
-
cache.set(key, { [alg]: cryptoKey });
|
|
1126
|
-
} else {
|
|
1127
|
-
cached[alg] = cryptoKey;
|
|
1128
|
-
}
|
|
1129
|
-
return cryptoKey;
|
|
1130
|
-
};
|
|
1131
|
-
var handleKeyObject = (keyObject, alg) => {
|
|
1132
|
-
cache ||= /* @__PURE__ */ new WeakMap();
|
|
1133
|
-
let cached = cache.get(keyObject);
|
|
1134
|
-
if (cached?.[alg]) {
|
|
1135
|
-
return cached[alg];
|
|
1136
|
-
}
|
|
1137
|
-
const isPublic = keyObject.type === "public";
|
|
1138
|
-
const extractable = isPublic ? true : false;
|
|
1139
|
-
let cryptoKey;
|
|
1140
|
-
if (keyObject.asymmetricKeyType === "x25519") {
|
|
1141
|
-
switch (alg) {
|
|
1142
|
-
case "ECDH-ES":
|
|
1143
|
-
case "ECDH-ES+A128KW":
|
|
1144
|
-
case "ECDH-ES+A192KW":
|
|
1145
|
-
case "ECDH-ES+A256KW":
|
|
1146
|
-
break;
|
|
1147
|
-
default:
|
|
1148
|
-
throw new TypeError("given KeyObject instance cannot be used for this algorithm");
|
|
1149
|
-
}
|
|
1150
|
-
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ["deriveBits"]);
|
|
1151
|
-
}
|
|
1152
|
-
if (keyObject.asymmetricKeyType === "ed25519") {
|
|
1153
|
-
if (alg !== "EdDSA" && alg !== "Ed25519") {
|
|
1154
|
-
throw new TypeError("given KeyObject instance cannot be used for this algorithm");
|
|
1155
|
-
}
|
|
1156
|
-
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
|
|
1157
|
-
isPublic ? "verify" : "sign"
|
|
1158
|
-
]);
|
|
1159
|
-
}
|
|
1160
|
-
switch (keyObject.asymmetricKeyType) {
|
|
1161
|
-
case "ml-dsa-44":
|
|
1162
|
-
case "ml-dsa-65":
|
|
1163
|
-
case "ml-dsa-87": {
|
|
1164
|
-
if (alg !== keyObject.asymmetricKeyType.toUpperCase()) {
|
|
1165
|
-
throw new TypeError("given KeyObject instance cannot be used for this algorithm");
|
|
1166
|
-
}
|
|
1167
|
-
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [
|
|
1168
|
-
isPublic ? "verify" : "sign"
|
|
1169
|
-
]);
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
if (keyObject.asymmetricKeyType === "rsa") {
|
|
1173
|
-
let hash;
|
|
1174
|
-
switch (alg) {
|
|
1175
|
-
case "RSA-OAEP":
|
|
1176
|
-
hash = "SHA-1";
|
|
1177
|
-
break;
|
|
1178
|
-
case "RS256":
|
|
1179
|
-
case "PS256":
|
|
1180
|
-
case "RSA-OAEP-256":
|
|
1181
|
-
hash = "SHA-256";
|
|
1182
|
-
break;
|
|
1183
|
-
case "RS384":
|
|
1184
|
-
case "PS384":
|
|
1185
|
-
case "RSA-OAEP-384":
|
|
1186
|
-
hash = "SHA-384";
|
|
1187
|
-
break;
|
|
1188
|
-
case "RS512":
|
|
1189
|
-
case "PS512":
|
|
1190
|
-
case "RSA-OAEP-512":
|
|
1191
|
-
hash = "SHA-512";
|
|
1192
|
-
break;
|
|
1193
|
-
default:
|
|
1194
|
-
throw new TypeError("given KeyObject instance cannot be used for this algorithm");
|
|
1195
|
-
}
|
|
1196
|
-
if (alg.startsWith("RSA-OAEP")) {
|
|
1197
|
-
return keyObject.toCryptoKey({
|
|
1198
|
-
name: "RSA-OAEP",
|
|
1199
|
-
hash
|
|
1200
|
-
}, extractable, isPublic ? ["encrypt"] : ["decrypt"]);
|
|
1201
|
-
}
|
|
1202
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
1203
|
-
name: alg.startsWith("PS") ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
|
|
1204
|
-
hash
|
|
1205
|
-
}, extractable, [isPublic ? "verify" : "sign"]);
|
|
1206
|
-
}
|
|
1207
|
-
if (keyObject.asymmetricKeyType === "ec") {
|
|
1208
|
-
const nist = /* @__PURE__ */ new Map([
|
|
1209
|
-
["prime256v1", "P-256"],
|
|
1210
|
-
["secp384r1", "P-384"],
|
|
1211
|
-
["secp521r1", "P-521"]
|
|
1212
|
-
]);
|
|
1213
|
-
const namedCurve = nist.get(keyObject.asymmetricKeyDetails?.namedCurve);
|
|
1214
|
-
if (!namedCurve) {
|
|
1215
|
-
throw new TypeError("given KeyObject instance cannot be used for this algorithm");
|
|
1216
|
-
}
|
|
1217
|
-
if (alg === "ES256" && namedCurve === "P-256") {
|
|
1218
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
1219
|
-
name: "ECDSA",
|
|
1220
|
-
namedCurve
|
|
1221
|
-
}, extractable, [isPublic ? "verify" : "sign"]);
|
|
1222
|
-
}
|
|
1223
|
-
if (alg === "ES384" && namedCurve === "P-384") {
|
|
1224
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
1225
|
-
name: "ECDSA",
|
|
1226
|
-
namedCurve
|
|
1227
|
-
}, extractable, [isPublic ? "verify" : "sign"]);
|
|
1228
|
-
}
|
|
1229
|
-
if (alg === "ES512" && namedCurve === "P-521") {
|
|
1230
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
1231
|
-
name: "ECDSA",
|
|
1232
|
-
namedCurve
|
|
1233
|
-
}, extractable, [isPublic ? "verify" : "sign"]);
|
|
1234
|
-
}
|
|
1235
|
-
if (alg.startsWith("ECDH-ES")) {
|
|
1236
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
1237
|
-
name: "ECDH",
|
|
1238
|
-
namedCurve
|
|
1239
|
-
}, extractable, isPublic ? [] : ["deriveBits"]);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
if (!cryptoKey) {
|
|
1243
|
-
throw new TypeError("given KeyObject instance cannot be used for this algorithm");
|
|
1244
|
-
}
|
|
1245
|
-
if (!cached) {
|
|
1246
|
-
cache.set(keyObject, { [alg]: cryptoKey });
|
|
1247
|
-
} else {
|
|
1248
|
-
cached[alg] = cryptoKey;
|
|
1249
|
-
}
|
|
1250
|
-
return cryptoKey;
|
|
1251
|
-
};
|
|
1252
|
-
async function normalizeKey(key, alg) {
|
|
1253
|
-
if (key instanceof Uint8Array) {
|
|
1254
|
-
return key;
|
|
1255
|
-
}
|
|
1256
|
-
if (isCryptoKey(key)) {
|
|
1257
|
-
return key;
|
|
1258
|
-
}
|
|
1259
|
-
if (isKeyObject(key)) {
|
|
1260
|
-
if (key.type === "secret") {
|
|
1261
|
-
return key.export();
|
|
1262
|
-
}
|
|
1263
|
-
if ("toCryptoKey" in key && typeof key.toCryptoKey === "function") {
|
|
1264
|
-
try {
|
|
1265
|
-
return handleKeyObject(key, alg);
|
|
1266
|
-
} catch (err) {
|
|
1267
|
-
if (err instanceof TypeError) {
|
|
1268
|
-
throw err;
|
|
1109
|
+
async getChart(id, options, signal) {
|
|
1110
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1111
|
+
const chart = await this.get(
|
|
1112
|
+
`/charts/${encodeURIComponent(id)}`,
|
|
1113
|
+
tenantId,
|
|
1114
|
+
options?.userId,
|
|
1115
|
+
options?.scopes,
|
|
1116
|
+
signal
|
|
1117
|
+
);
|
|
1118
|
+
return {
|
|
1119
|
+
...chart,
|
|
1120
|
+
vega_lite_spec: {
|
|
1121
|
+
...chart.vega_lite_spec,
|
|
1122
|
+
data: {
|
|
1123
|
+
values: await this.runSafeQueryOnClient(
|
|
1124
|
+
chart.sql,
|
|
1125
|
+
chart.database ?? void 0,
|
|
1126
|
+
chart.sql_params ?? void 0
|
|
1127
|
+
)
|
|
1269
1128
|
}
|
|
1270
1129
|
}
|
|
1271
|
-
}
|
|
1272
|
-
let jwk = key.export({ format: "jwk" });
|
|
1273
|
-
return handleJWK(key, jwk, alg);
|
|
1274
|
-
}
|
|
1275
|
-
if (isJWK(key)) {
|
|
1276
|
-
if (key.k) {
|
|
1277
|
-
return decode(key.k);
|
|
1278
|
-
}
|
|
1279
|
-
return handleJWK(key, key, alg, true);
|
|
1280
|
-
}
|
|
1281
|
-
throw new Error("unreachable");
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
// node_modules/jose/dist/webapi/lib/check_key_type.js
|
|
1285
|
-
var tag = (key) => key?.[Symbol.toStringTag];
|
|
1286
|
-
var jwkMatchesOp = (alg, key, usage) => {
|
|
1287
|
-
if (key.use !== void 0) {
|
|
1288
|
-
let expected;
|
|
1289
|
-
switch (usage) {
|
|
1290
|
-
case "sign":
|
|
1291
|
-
case "verify":
|
|
1292
|
-
expected = "sig";
|
|
1293
|
-
break;
|
|
1294
|
-
case "encrypt":
|
|
1295
|
-
case "decrypt":
|
|
1296
|
-
expected = "enc";
|
|
1297
|
-
break;
|
|
1298
|
-
}
|
|
1299
|
-
if (key.use !== expected) {
|
|
1300
|
-
throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
if (key.alg !== void 0 && key.alg !== alg) {
|
|
1304
|
-
throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
|
|
1305
|
-
}
|
|
1306
|
-
if (Array.isArray(key.key_ops)) {
|
|
1307
|
-
let expectedKeyOp;
|
|
1308
|
-
switch (true) {
|
|
1309
|
-
case (usage === "sign" || usage === "verify"):
|
|
1310
|
-
case alg === "dir":
|
|
1311
|
-
case alg.includes("CBC-HS"):
|
|
1312
|
-
expectedKeyOp = usage;
|
|
1313
|
-
break;
|
|
1314
|
-
case alg.startsWith("PBES2"):
|
|
1315
|
-
expectedKeyOp = "deriveBits";
|
|
1316
|
-
break;
|
|
1317
|
-
case /^A\d{3}(?:GCM)?(?:KW)?$/.test(alg):
|
|
1318
|
-
if (!alg.includes("GCM") && alg.endsWith("KW")) {
|
|
1319
|
-
expectedKeyOp = usage === "encrypt" ? "wrapKey" : "unwrapKey";
|
|
1320
|
-
} else {
|
|
1321
|
-
expectedKeyOp = usage;
|
|
1322
|
-
}
|
|
1323
|
-
break;
|
|
1324
|
-
case (usage === "encrypt" && alg.startsWith("RSA")):
|
|
1325
|
-
expectedKeyOp = "wrapKey";
|
|
1326
|
-
break;
|
|
1327
|
-
case usage === "decrypt":
|
|
1328
|
-
expectedKeyOp = alg.startsWith("RSA") ? "unwrapKey" : "deriveBits";
|
|
1329
|
-
break;
|
|
1330
|
-
}
|
|
1331
|
-
if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) {
|
|
1332
|
-
throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
return true;
|
|
1336
|
-
};
|
|
1337
|
-
var symmetricTypeCheck = (alg, key, usage) => {
|
|
1338
|
-
if (key instanceof Uint8Array)
|
|
1339
|
-
return;
|
|
1340
|
-
if (isJWK(key)) {
|
|
1341
|
-
if (isSecretJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
1342
|
-
return;
|
|
1343
|
-
throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
|
|
1344
|
-
}
|
|
1345
|
-
if (!isKeyLike(key)) {
|
|
1346
|
-
throw new TypeError(withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key", "Uint8Array"));
|
|
1347
|
-
}
|
|
1348
|
-
if (key.type !== "secret") {
|
|
1349
|
-
throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
|
|
1350
|
-
}
|
|
1351
|
-
};
|
|
1352
|
-
var asymmetricTypeCheck = (alg, key, usage) => {
|
|
1353
|
-
if (isJWK(key)) {
|
|
1354
|
-
switch (usage) {
|
|
1355
|
-
case "decrypt":
|
|
1356
|
-
case "sign":
|
|
1357
|
-
if (isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
1358
|
-
return;
|
|
1359
|
-
throw new TypeError(`JSON Web Key for this operation be a private JWK`);
|
|
1360
|
-
case "encrypt":
|
|
1361
|
-
case "verify":
|
|
1362
|
-
if (isPublicJWK(key) && jwkMatchesOp(alg, key, usage))
|
|
1363
|
-
return;
|
|
1364
|
-
throw new TypeError(`JSON Web Key for this operation be a public JWK`);
|
|
1365
|
-
}
|
|
1366
|
-
}
|
|
1367
|
-
if (!isKeyLike(key)) {
|
|
1368
|
-
throw new TypeError(withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key"));
|
|
1369
|
-
}
|
|
1370
|
-
if (key.type === "secret") {
|
|
1371
|
-
throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
|
|
1372
|
-
}
|
|
1373
|
-
if (key.type === "public") {
|
|
1374
|
-
switch (usage) {
|
|
1375
|
-
case "sign":
|
|
1376
|
-
throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
|
|
1377
|
-
case "decrypt":
|
|
1378
|
-
throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
1379
|
-
}
|
|
1130
|
+
};
|
|
1380
1131
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1132
|
+
async updateChart(id, body, options, signal) {
|
|
1133
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1134
|
+
return await this.put(
|
|
1135
|
+
`/charts/${encodeURIComponent(id)}`,
|
|
1136
|
+
body,
|
|
1137
|
+
tenantId,
|
|
1138
|
+
options?.userId,
|
|
1139
|
+
options?.scopes,
|
|
1140
|
+
signal
|
|
1141
|
+
);
|
|
1388
1142
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
break;
|
|
1399
|
-
default:
|
|
1400
|
-
asymmetricTypeCheck(alg, key, usage);
|
|
1143
|
+
async deleteChart(id, options, signal) {
|
|
1144
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1145
|
+
await this.delete(
|
|
1146
|
+
`/charts/${encodeURIComponent(id)}`,
|
|
1147
|
+
tenantId,
|
|
1148
|
+
options?.userId,
|
|
1149
|
+
options?.scopes,
|
|
1150
|
+
signal
|
|
1151
|
+
);
|
|
1401
1152
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
case "PS256":
|
|
1413
|
-
case "PS384":
|
|
1414
|
-
case "PS512":
|
|
1415
|
-
return { hash, name: "RSA-PSS", saltLength: parseInt(alg.slice(-3), 10) >> 3 };
|
|
1416
|
-
case "RS256":
|
|
1417
|
-
case "RS384":
|
|
1418
|
-
case "RS512":
|
|
1419
|
-
return { hash, name: "RSASSA-PKCS1-v1_5" };
|
|
1420
|
-
case "ES256":
|
|
1421
|
-
case "ES384":
|
|
1422
|
-
case "ES512":
|
|
1423
|
-
return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve };
|
|
1424
|
-
case "Ed25519":
|
|
1425
|
-
case "EdDSA":
|
|
1426
|
-
return { name: "Ed25519" };
|
|
1427
|
-
case "ML-DSA-44":
|
|
1428
|
-
case "ML-DSA-65":
|
|
1429
|
-
case "ML-DSA-87":
|
|
1430
|
-
return { name: alg };
|
|
1431
|
-
default:
|
|
1432
|
-
throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
1153
|
+
async createActiveChart(body, options, signal) {
|
|
1154
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1155
|
+
return await this.post(
|
|
1156
|
+
"/active-charts",
|
|
1157
|
+
body,
|
|
1158
|
+
tenantId,
|
|
1159
|
+
options?.userId,
|
|
1160
|
+
options?.scopes,
|
|
1161
|
+
signal
|
|
1162
|
+
);
|
|
1433
1163
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
if (
|
|
1440
|
-
|
|
1164
|
+
async listActiveCharts(options, signal) {
|
|
1165
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1166
|
+
const params = new URLSearchParams();
|
|
1167
|
+
if (options?.pagination?.page)
|
|
1168
|
+
params.set("page", `${options.pagination.page}`);
|
|
1169
|
+
if (options?.pagination?.limit)
|
|
1170
|
+
params.set("limit", `${options.pagination.limit}`);
|
|
1171
|
+
if (options?.sortBy) params.set("sort_by", options.sortBy);
|
|
1172
|
+
if (options?.sortDir) params.set("sort_dir", options.sortDir);
|
|
1173
|
+
if (options?.title) params.set("name", options.title);
|
|
1174
|
+
if (options?.userFilter) params.set("user_id", options.userFilter);
|
|
1175
|
+
if (options?.createdFrom) params.set("created_from", options.createdFrom);
|
|
1176
|
+
if (options?.createdTo) params.set("created_to", options.createdTo);
|
|
1177
|
+
if (options?.updatedFrom) params.set("updated_from", options.updatedFrom);
|
|
1178
|
+
if (options?.updatedTo) params.set("updated_to", options.updatedTo);
|
|
1179
|
+
const response = await this.get(
|
|
1180
|
+
`/active-charts${params.toString() ? `?${params.toString()}` : ""}`,
|
|
1181
|
+
tenantId,
|
|
1182
|
+
options?.userId,
|
|
1183
|
+
options?.scopes,
|
|
1184
|
+
signal
|
|
1185
|
+
);
|
|
1186
|
+
if (options?.withData) {
|
|
1187
|
+
response.data = await Promise.all(
|
|
1188
|
+
response.data.map(async (active) => ({
|
|
1189
|
+
...active,
|
|
1190
|
+
chart: active.chart ? await this.getChart(active.chart_id, options, signal) : null
|
|
1191
|
+
}))
|
|
1192
|
+
);
|
|
1441
1193
|
}
|
|
1442
|
-
return
|
|
1194
|
+
return response;
|
|
1443
1195
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
if (!matched || matched[4] && matched[1]) {
|
|
1459
|
-
throw new TypeError("Invalid time period format");
|
|
1460
|
-
}
|
|
1461
|
-
const value = parseFloat(matched[2]);
|
|
1462
|
-
const unit = matched[3].toLowerCase();
|
|
1463
|
-
let numericDate;
|
|
1464
|
-
switch (unit) {
|
|
1465
|
-
case "sec":
|
|
1466
|
-
case "secs":
|
|
1467
|
-
case "second":
|
|
1468
|
-
case "seconds":
|
|
1469
|
-
case "s":
|
|
1470
|
-
numericDate = Math.round(value);
|
|
1471
|
-
break;
|
|
1472
|
-
case "minute":
|
|
1473
|
-
case "minutes":
|
|
1474
|
-
case "min":
|
|
1475
|
-
case "mins":
|
|
1476
|
-
case "m":
|
|
1477
|
-
numericDate = Math.round(value * minute);
|
|
1478
|
-
break;
|
|
1479
|
-
case "hour":
|
|
1480
|
-
case "hours":
|
|
1481
|
-
case "hr":
|
|
1482
|
-
case "hrs":
|
|
1483
|
-
case "h":
|
|
1484
|
-
numericDate = Math.round(value * hour);
|
|
1485
|
-
break;
|
|
1486
|
-
case "day":
|
|
1487
|
-
case "days":
|
|
1488
|
-
case "d":
|
|
1489
|
-
numericDate = Math.round(value * day);
|
|
1490
|
-
break;
|
|
1491
|
-
case "week":
|
|
1492
|
-
case "weeks":
|
|
1493
|
-
case "w":
|
|
1494
|
-
numericDate = Math.round(value * week);
|
|
1495
|
-
break;
|
|
1496
|
-
default:
|
|
1497
|
-
numericDate = Math.round(value * year);
|
|
1498
|
-
break;
|
|
1499
|
-
}
|
|
1500
|
-
if (matched[1] === "-" || matched[4] === "ago") {
|
|
1501
|
-
return -numericDate;
|
|
1502
|
-
}
|
|
1503
|
-
return numericDate;
|
|
1504
|
-
}
|
|
1505
|
-
function validateInput(label, input) {
|
|
1506
|
-
if (!Number.isFinite(input)) {
|
|
1507
|
-
throw new TypeError(`Invalid ${label} input`);
|
|
1508
|
-
}
|
|
1509
|
-
return input;
|
|
1510
|
-
}
|
|
1511
|
-
var JWTClaimsBuilder = class {
|
|
1512
|
-
#payload;
|
|
1513
|
-
constructor(payload) {
|
|
1514
|
-
if (!isObject(payload)) {
|
|
1515
|
-
throw new TypeError("JWT Claims Set MUST be an object");
|
|
1196
|
+
async getActiveChart(id, options, signal) {
|
|
1197
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1198
|
+
const active = await this.get(
|
|
1199
|
+
`/active-charts/${encodeURIComponent(id)}`,
|
|
1200
|
+
tenantId,
|
|
1201
|
+
options?.userId,
|
|
1202
|
+
options?.scopes,
|
|
1203
|
+
signal
|
|
1204
|
+
);
|
|
1205
|
+
if (options?.withData && active.chart_id) {
|
|
1206
|
+
return {
|
|
1207
|
+
...active,
|
|
1208
|
+
chart: await this.getChart(active.chart_id, options, signal)
|
|
1209
|
+
};
|
|
1516
1210
|
}
|
|
1517
|
-
|
|
1518
|
-
}
|
|
1519
|
-
data() {
|
|
1520
|
-
return encoder.encode(JSON.stringify(this.#payload));
|
|
1211
|
+
return active;
|
|
1521
1212
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
this.#payload.sub = value;
|
|
1533
|
-
}
|
|
1534
|
-
get aud() {
|
|
1535
|
-
return this.#payload.aud;
|
|
1536
|
-
}
|
|
1537
|
-
set aud(value) {
|
|
1538
|
-
this.#payload.aud = value;
|
|
1539
|
-
}
|
|
1540
|
-
set jti(value) {
|
|
1541
|
-
this.#payload.jti = value;
|
|
1542
|
-
}
|
|
1543
|
-
set nbf(value) {
|
|
1544
|
-
if (typeof value === "number") {
|
|
1545
|
-
this.#payload.nbf = validateInput("setNotBefore", value);
|
|
1546
|
-
} else if (value instanceof Date) {
|
|
1547
|
-
this.#payload.nbf = validateInput("setNotBefore", epoch(value));
|
|
1548
|
-
} else {
|
|
1549
|
-
this.#payload.nbf = epoch(/* @__PURE__ */ new Date()) + secs(value);
|
|
1550
|
-
}
|
|
1213
|
+
async updateActiveChart(id, body, options, signal) {
|
|
1214
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1215
|
+
return await this.put(
|
|
1216
|
+
`/active-charts/${encodeURIComponent(id)}`,
|
|
1217
|
+
body,
|
|
1218
|
+
tenantId,
|
|
1219
|
+
options?.userId,
|
|
1220
|
+
options?.scopes,
|
|
1221
|
+
signal
|
|
1222
|
+
);
|
|
1551
1223
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1224
|
+
async deleteActiveChart(id, options, signal) {
|
|
1225
|
+
const tenantId = this.resolveTenantId(options?.tenantId);
|
|
1226
|
+
await this.delete(
|
|
1227
|
+
`/active-charts/${encodeURIComponent(id)}`,
|
|
1228
|
+
tenantId,
|
|
1229
|
+
options?.userId,
|
|
1230
|
+
options?.scopes,
|
|
1231
|
+
signal
|
|
1232
|
+
);
|
|
1560
1233
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
this.#payload.iat = validateInput("setIssuedAt", epoch(value));
|
|
1566
|
-
} else if (typeof value === "string") {
|
|
1567
|
-
this.#payload.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value));
|
|
1568
|
-
} else {
|
|
1569
|
-
this.#payload.iat = validateInput("setIssuedAt", value);
|
|
1234
|
+
getDatabase(name) {
|
|
1235
|
+
const dbName = name ?? this.defaultDatabase;
|
|
1236
|
+
if (!dbName) {
|
|
1237
|
+
throw new Error("No database attached.");
|
|
1570
1238
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data);
|
|
1579
|
-
return new Uint8Array(signature);
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
// node_modules/jose/dist/webapi/jws/flattened/sign.js
|
|
1583
|
-
var FlattenedSign = class {
|
|
1584
|
-
#payload;
|
|
1585
|
-
#protectedHeader;
|
|
1586
|
-
#unprotectedHeader;
|
|
1587
|
-
constructor(payload) {
|
|
1588
|
-
if (!(payload instanceof Uint8Array)) {
|
|
1589
|
-
throw new TypeError("payload must be an instance of Uint8Array");
|
|
1239
|
+
const adapter = this.databases.get(dbName);
|
|
1240
|
+
if (!adapter) {
|
|
1241
|
+
throw new Error(
|
|
1242
|
+
`Database '${dbName}' not found. Attached: ${Array.from(
|
|
1243
|
+
this.databases.keys()
|
|
1244
|
+
).join(", ")}`
|
|
1245
|
+
);
|
|
1590
1246
|
}
|
|
1591
|
-
|
|
1247
|
+
return adapter;
|
|
1592
1248
|
}
|
|
1593
|
-
|
|
1594
|
-
if (
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1249
|
+
async ensureSchemasSynced(tenantId, userId, scopes, disableAutoSync) {
|
|
1250
|
+
if (disableAutoSync) return;
|
|
1251
|
+
const unsynced = Array.from(this.databases.keys()).filter(
|
|
1252
|
+
(name) => !this.syncedDatabases.has(name)
|
|
1253
|
+
);
|
|
1254
|
+
await Promise.all(
|
|
1255
|
+
unsynced.map(
|
|
1256
|
+
(name) => this.syncSchema(name, { tenantId, userId, scopes }).catch((error) => {
|
|
1257
|
+
console.warn(`Failed to sync schema for ${name}:`, error);
|
|
1258
|
+
})
|
|
1259
|
+
)
|
|
1260
|
+
);
|
|
1599
1261
|
}
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1262
|
+
resolveTenantId(tenantId) {
|
|
1263
|
+
const resolved = tenantId ?? this.defaultTenantId;
|
|
1264
|
+
if (!resolved) {
|
|
1265
|
+
throw new Error(
|
|
1266
|
+
"tenantId is required. Provide it per request or via defaultTenantId option."
|
|
1267
|
+
);
|
|
1603
1268
|
}
|
|
1604
|
-
|
|
1605
|
-
return this;
|
|
1269
|
+
return resolved;
|
|
1606
1270
|
}
|
|
1607
|
-
async
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
1613
|
-
}
|
|
1614
|
-
const joseHeader = {
|
|
1615
|
-
...this.#protectedHeader,
|
|
1616
|
-
...this.#unprotectedHeader
|
|
1617
|
-
};
|
|
1618
|
-
const extensions = validateCrit(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options?.crit, this.#protectedHeader, joseHeader);
|
|
1619
|
-
let b64 = true;
|
|
1620
|
-
if (extensions.has("b64")) {
|
|
1621
|
-
b64 = this.#protectedHeader.b64;
|
|
1622
|
-
if (typeof b64 !== "boolean") {
|
|
1623
|
-
throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
const { alg } = joseHeader;
|
|
1627
|
-
if (typeof alg !== "string" || !alg) {
|
|
1628
|
-
throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
|
|
1629
|
-
}
|
|
1630
|
-
checkKeyType(alg, key, "sign");
|
|
1631
|
-
let payloadS;
|
|
1632
|
-
let payloadB;
|
|
1633
|
-
if (b64) {
|
|
1634
|
-
payloadS = encode2(this.#payload);
|
|
1635
|
-
payloadB = encode(payloadS);
|
|
1636
|
-
} else {
|
|
1637
|
-
payloadB = this.#payload;
|
|
1638
|
-
payloadS = "";
|
|
1639
|
-
}
|
|
1640
|
-
let protectedHeaderString;
|
|
1641
|
-
let protectedHeaderBytes;
|
|
1642
|
-
if (this.#protectedHeader) {
|
|
1643
|
-
protectedHeaderString = encode2(JSON.stringify(this.#protectedHeader));
|
|
1644
|
-
protectedHeaderBytes = encode(protectedHeaderString);
|
|
1645
|
-
} else {
|
|
1646
|
-
protectedHeaderString = "";
|
|
1647
|
-
protectedHeaderBytes = new Uint8Array();
|
|
1648
|
-
}
|
|
1649
|
-
const data = concat(protectedHeaderBytes, encode("."), payloadB);
|
|
1650
|
-
const k = await normalizeKey(key, alg);
|
|
1651
|
-
const signature = await sign(alg, k, data);
|
|
1652
|
-
const jws = {
|
|
1653
|
-
signature: encode2(signature),
|
|
1654
|
-
payload: payloadS
|
|
1271
|
+
async headers(tenantId, userId, scopes, includeJson = true, sessionId) {
|
|
1272
|
+
const token = await this.generateJWT(tenantId, userId, scopes);
|
|
1273
|
+
const headers = {
|
|
1274
|
+
Authorization: `Bearer ${token}`,
|
|
1275
|
+
Accept: "application/json"
|
|
1655
1276
|
};
|
|
1656
|
-
if (
|
|
1657
|
-
|
|
1658
|
-
}
|
|
1659
|
-
if (this.#protectedHeader) {
|
|
1660
|
-
jws.protected = protectedHeaderString;
|
|
1277
|
+
if (includeJson) {
|
|
1278
|
+
headers["Content-Type"] = "application/json";
|
|
1661
1279
|
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
};
|
|
1665
|
-
|
|
1666
|
-
// node_modules/jose/dist/webapi/jws/compact/sign.js
|
|
1667
|
-
var CompactSign = class {
|
|
1668
|
-
#flattened;
|
|
1669
|
-
constructor(payload) {
|
|
1670
|
-
this.#flattened = new FlattenedSign(payload);
|
|
1671
|
-
}
|
|
1672
|
-
setProtectedHeader(protectedHeader) {
|
|
1673
|
-
this.#flattened.setProtectedHeader(protectedHeader);
|
|
1674
|
-
return this;
|
|
1675
|
-
}
|
|
1676
|
-
async sign(key, options) {
|
|
1677
|
-
const jws = await this.#flattened.sign(key, options);
|
|
1678
|
-
if (jws.payload === void 0) {
|
|
1679
|
-
throw new TypeError("use the flattened module for creating JWS with b64: false");
|
|
1280
|
+
if (sessionId) {
|
|
1281
|
+
headers["x-session-id"] = sessionId;
|
|
1680
1282
|
}
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
};
|
|
1684
|
-
|
|
1685
|
-
// node_modules/jose/dist/webapi/jwt/sign.js
|
|
1686
|
-
var SignJWT = class {
|
|
1687
|
-
#protectedHeader;
|
|
1688
|
-
#jwt;
|
|
1689
|
-
constructor(payload = {}) {
|
|
1690
|
-
this.#jwt = new JWTClaimsBuilder(payload);
|
|
1691
|
-
}
|
|
1692
|
-
setIssuer(issuer) {
|
|
1693
|
-
this.#jwt.iss = issuer;
|
|
1694
|
-
return this;
|
|
1695
|
-
}
|
|
1696
|
-
setSubject(subject) {
|
|
1697
|
-
this.#jwt.sub = subject;
|
|
1698
|
-
return this;
|
|
1699
|
-
}
|
|
1700
|
-
setAudience(audience) {
|
|
1701
|
-
this.#jwt.aud = audience;
|
|
1702
|
-
return this;
|
|
1703
|
-
}
|
|
1704
|
-
setJti(jwtId) {
|
|
1705
|
-
this.#jwt.jti = jwtId;
|
|
1706
|
-
return this;
|
|
1707
|
-
}
|
|
1708
|
-
setNotBefore(input) {
|
|
1709
|
-
this.#jwt.nbf = input;
|
|
1710
|
-
return this;
|
|
1711
|
-
}
|
|
1712
|
-
setExpirationTime(input) {
|
|
1713
|
-
this.#jwt.exp = input;
|
|
1714
|
-
return this;
|
|
1715
|
-
}
|
|
1716
|
-
setIssuedAt(input) {
|
|
1717
|
-
this.#jwt.iat = input;
|
|
1718
|
-
return this;
|
|
1719
|
-
}
|
|
1720
|
-
setProtectedHeader(protectedHeader) {
|
|
1721
|
-
this.#protectedHeader = protectedHeader;
|
|
1722
|
-
return this;
|
|
1723
|
-
}
|
|
1724
|
-
async sign(key, options) {
|
|
1725
|
-
const sig = new CompactSign(this.#jwt.data());
|
|
1726
|
-
sig.setProtectedHeader(this.#protectedHeader);
|
|
1727
|
-
if (Array.isArray(this.#protectedHeader?.crit) && this.#protectedHeader.crit.includes("b64") && this.#protectedHeader.b64 === false) {
|
|
1728
|
-
throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
1283
|
+
if (this.additionalHeaders) {
|
|
1284
|
+
Object.assign(headers, this.additionalHeaders);
|
|
1729
1285
|
}
|
|
1730
|
-
return
|
|
1286
|
+
return headers;
|
|
1731
1287
|
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
additionalHeaders;
|
|
1741
|
-
fetchImpl;
|
|
1742
|
-
cachedPrivateKey;
|
|
1743
|
-
constructor(baseUrl, privateKey, organizationId, options) {
|
|
1744
|
-
if (!baseUrl) {
|
|
1745
|
-
throw new Error("Base URL is required");
|
|
1746
|
-
}
|
|
1747
|
-
if (!privateKey) {
|
|
1748
|
-
throw new Error("Private key is required");
|
|
1749
|
-
}
|
|
1750
|
-
if (!organizationId) {
|
|
1751
|
-
throw new Error("Organization ID is required");
|
|
1288
|
+
async request(path, init) {
|
|
1289
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, init);
|
|
1290
|
+
const text = await response.text();
|
|
1291
|
+
let json;
|
|
1292
|
+
try {
|
|
1293
|
+
json = text ? JSON.parse(text) : void 0;
|
|
1294
|
+
} catch {
|
|
1295
|
+
json = void 0;
|
|
1752
1296
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
this.defaultTenantId = options?.defaultTenantId;
|
|
1757
|
-
this.additionalHeaders = options?.additionalHeaders;
|
|
1758
|
-
this.fetchImpl = options?.fetch ?? globalThis.fetch;
|
|
1759
|
-
if (!this.fetchImpl) {
|
|
1760
|
-
throw new Error(
|
|
1761
|
-
"Fetch implementation not found. Provide options.fetch or use Node 18+."
|
|
1297
|
+
if (!response.ok) {
|
|
1298
|
+
const error = new Error(
|
|
1299
|
+
json?.error || response.statusText || "Request failed"
|
|
1762
1300
|
);
|
|
1301
|
+
error.status = response.status;
|
|
1302
|
+
if (json?.details) error.details = json.details;
|
|
1303
|
+
throw error;
|
|
1763
1304
|
}
|
|
1764
|
-
|
|
1765
|
-
getDefaultTenantId() {
|
|
1766
|
-
return this.defaultTenantId;
|
|
1305
|
+
return json;
|
|
1767
1306
|
}
|
|
1768
1307
|
async get(path, tenantId, userId, scopes, signal, sessionId) {
|
|
1769
1308
|
return await this.request(path, {
|
|
1770
1309
|
method: "GET",
|
|
1771
|
-
headers: await this.
|
|
1310
|
+
headers: await this.headers(tenantId, userId, scopes, false, sessionId),
|
|
1772
1311
|
signal
|
|
1773
1312
|
});
|
|
1774
1313
|
}
|
|
1775
1314
|
async post(path, body, tenantId, userId, scopes, signal, sessionId) {
|
|
1776
1315
|
return await this.request(path, {
|
|
1777
1316
|
method: "POST",
|
|
1778
|
-
headers: await this.
|
|
1317
|
+
headers: await this.headers(tenantId, userId, scopes, true, sessionId),
|
|
1779
1318
|
body: JSON.stringify(body ?? {}),
|
|
1780
1319
|
signal
|
|
1781
1320
|
});
|
|
@@ -1783,7 +1322,7 @@ var ApiClient = class {
|
|
|
1783
1322
|
async put(path, body, tenantId, userId, scopes, signal, sessionId) {
|
|
1784
1323
|
return await this.request(path, {
|
|
1785
1324
|
method: "PUT",
|
|
1786
|
-
headers: await this.
|
|
1325
|
+
headers: await this.headers(tenantId, userId, scopes, true, sessionId),
|
|
1787
1326
|
body: JSON.stringify(body ?? {}),
|
|
1788
1327
|
signal
|
|
1789
1328
|
});
|
|
@@ -1791,46 +1330,10 @@ var ApiClient = class {
|
|
|
1791
1330
|
async delete(path, tenantId, userId, scopes, signal, sessionId) {
|
|
1792
1331
|
return await this.request(path, {
|
|
1793
1332
|
method: "DELETE",
|
|
1794
|
-
headers: await this.
|
|
1333
|
+
headers: await this.headers(tenantId, userId, scopes, false, sessionId),
|
|
1795
1334
|
signal
|
|
1796
1335
|
});
|
|
1797
1336
|
}
|
|
1798
|
-
async request(path, init) {
|
|
1799
|
-
const response = await this.fetchImpl(`${this.baseUrl}${path}`, init);
|
|
1800
|
-
const text = await response.text();
|
|
1801
|
-
let json;
|
|
1802
|
-
try {
|
|
1803
|
-
json = text ? JSON.parse(text) : void 0;
|
|
1804
|
-
} catch {
|
|
1805
|
-
json = void 0;
|
|
1806
|
-
}
|
|
1807
|
-
if (!response.ok) {
|
|
1808
|
-
const error = new Error(
|
|
1809
|
-
json?.error || response.statusText || "Request failed"
|
|
1810
|
-
);
|
|
1811
|
-
error.status = response.status;
|
|
1812
|
-
if (json?.details) error.details = json.details;
|
|
1813
|
-
throw error;
|
|
1814
|
-
}
|
|
1815
|
-
return json;
|
|
1816
|
-
}
|
|
1817
|
-
async buildHeaders(tenantId, userId, scopes, includeJson = true, sessionId) {
|
|
1818
|
-
const token = await this.generateJWT(tenantId, userId, scopes);
|
|
1819
|
-
const headers = {
|
|
1820
|
-
Authorization: `Bearer ${token}`,
|
|
1821
|
-
Accept: "application/json"
|
|
1822
|
-
};
|
|
1823
|
-
if (includeJson) {
|
|
1824
|
-
headers["Content-Type"] = "application/json";
|
|
1825
|
-
}
|
|
1826
|
-
if (sessionId) {
|
|
1827
|
-
headers["x-session-id"] = sessionId;
|
|
1828
|
-
}
|
|
1829
|
-
if (this.additionalHeaders) {
|
|
1830
|
-
Object.assign(headers, this.additionalHeaders);
|
|
1831
|
-
}
|
|
1832
|
-
return headers;
|
|
1833
|
-
}
|
|
1834
1337
|
async generateJWT(tenantId, userId, scopes) {
|
|
1835
1338
|
if (!this.cachedPrivateKey) {
|
|
1836
1339
|
this.cachedPrivateKey = await importPKCS8(this.privateKey, "RS256");
|
|
@@ -1843,69 +1346,34 @@ var ApiClient = class {
|
|
|
1843
1346
|
if (scopes?.length) payload.scopes = scopes;
|
|
1844
1347
|
return await new SignJWT(payload).setProtectedHeader({ alg: "RS256" }).setIssuedAt().setExpirationTime("1h").sign(this.cachedPrivateKey);
|
|
1845
1348
|
}
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
getDatabase(name) {
|
|
1861
|
-
const dbName = name ?? this.defaultDatabase;
|
|
1862
|
-
if (!dbName) {
|
|
1863
|
-
throw new Error("No database attached.");
|
|
1864
|
-
}
|
|
1865
|
-
const adapter = this.databases.get(dbName);
|
|
1866
|
-
if (!adapter) {
|
|
1867
|
-
throw new Error(
|
|
1868
|
-
`Database '${dbName}' not found. Attached: ${Array.from(
|
|
1869
|
-
this.databases.keys()
|
|
1870
|
-
).join(", ")}`
|
|
1871
|
-
);
|
|
1872
|
-
}
|
|
1873
|
-
return adapter;
|
|
1874
|
-
}
|
|
1875
|
-
getDatabaseMetadata(name) {
|
|
1876
|
-
const dbName = name ?? this.defaultDatabase;
|
|
1877
|
-
if (!dbName) return void 0;
|
|
1878
|
-
return this.databaseMetadata.get(dbName);
|
|
1879
|
-
}
|
|
1880
|
-
getDefaultDatabase() {
|
|
1881
|
-
return this.defaultDatabase;
|
|
1882
|
-
}
|
|
1883
|
-
async validateAndExecute(sql, params, databaseName, tenantId) {
|
|
1884
|
-
const adapter = this.getDatabase(databaseName);
|
|
1885
|
-
const metadata = this.getDatabaseMetadata(databaseName);
|
|
1886
|
-
let finalSql = sql;
|
|
1887
|
-
if (metadata) {
|
|
1888
|
-
finalSql = this.ensureTenantIsolation(sql, params, metadata, tenantId);
|
|
1889
|
-
}
|
|
1890
|
-
await adapter.validate(finalSql, params);
|
|
1891
|
-
const result = await adapter.execute(finalSql, params);
|
|
1349
|
+
buildSchemaRequest(databaseName, adapter, introspection) {
|
|
1350
|
+
const dialect = adapter.getDialect();
|
|
1351
|
+
const tables = introspection.tables.map((table) => ({
|
|
1352
|
+
table_name: table.name,
|
|
1353
|
+
description: table.comment ?? `Table ${table.name}`,
|
|
1354
|
+
columns: table.columns.map((column) => ({
|
|
1355
|
+
name: column.name,
|
|
1356
|
+
data_type: column.rawType ?? column.type,
|
|
1357
|
+
is_primary_key: Boolean(column.isPrimaryKey),
|
|
1358
|
+
description: column.comment ?? ""
|
|
1359
|
+
}))
|
|
1360
|
+
}));
|
|
1892
1361
|
return {
|
|
1893
|
-
|
|
1894
|
-
|
|
1362
|
+
database: databaseName,
|
|
1363
|
+
dialect,
|
|
1364
|
+
tables
|
|
1895
1365
|
};
|
|
1896
1366
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
return [];
|
|
1908
|
-
}
|
|
1367
|
+
hashSchemaRequest(payload) {
|
|
1368
|
+
const normalized = payload.tables.map((table) => ({
|
|
1369
|
+
name: table.table_name,
|
|
1370
|
+
columns: table.columns.map((column) => ({
|
|
1371
|
+
name: column.name,
|
|
1372
|
+
type: column.data_type,
|
|
1373
|
+
primary: column.is_primary_key
|
|
1374
|
+
}))
|
|
1375
|
+
}));
|
|
1376
|
+
return createHash("sha256").update(JSON.stringify(normalized)).digest("hex");
|
|
1909
1377
|
}
|
|
1910
1378
|
mapGeneratedParams(params) {
|
|
1911
1379
|
const record = {};
|
|
@@ -1940,375 +1408,20 @@ var QueryEngine = class {
|
|
|
1940
1408
|
}
|
|
1941
1409
|
return `${sql} WHERE ${tenantPredicate}`;
|
|
1942
1410
|
}
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
// src/routes/charts.ts
|
|
1946
|
-
async function createChart(client, body, options, signal) {
|
|
1947
|
-
const tenantId = resolveTenantId(client, options?.tenantId);
|
|
1948
|
-
return await client.post(
|
|
1949
|
-
"/charts",
|
|
1950
|
-
body,
|
|
1951
|
-
tenantId,
|
|
1952
|
-
options?.userId,
|
|
1953
|
-
options?.scopes,
|
|
1954
|
-
signal
|
|
1955
|
-
);
|
|
1956
|
-
}
|
|
1957
|
-
async function listCharts(client, queryEngine, options, signal) {
|
|
1958
|
-
const tenantId = resolveTenantId(client, options?.tenantId);
|
|
1959
|
-
const params = new URLSearchParams();
|
|
1960
|
-
if (options?.pagination?.page)
|
|
1961
|
-
params.set("page", `${options.pagination.page}`);
|
|
1962
|
-
if (options?.pagination?.limit)
|
|
1963
|
-
params.set("limit", `${options.pagination.limit}`);
|
|
1964
|
-
if (options?.sortBy) params.set("sort_by", options.sortBy);
|
|
1965
|
-
if (options?.sortDir) params.set("sort_dir", options.sortDir);
|
|
1966
|
-
if (options?.title) params.set("title", options.title);
|
|
1967
|
-
if (options?.userFilter) params.set("user_id", options.userFilter);
|
|
1968
|
-
if (options?.createdFrom) params.set("created_from", options.createdFrom);
|
|
1969
|
-
if (options?.createdTo) params.set("created_to", options.createdTo);
|
|
1970
|
-
if (options?.updatedFrom) params.set("updated_from", options.updatedFrom);
|
|
1971
|
-
if (options?.updatedTo) params.set("updated_to", options.updatedTo);
|
|
1972
|
-
const response = await client.get(
|
|
1973
|
-
`/charts${params.toString() ? `?${params.toString()}` : ""}`,
|
|
1974
|
-
tenantId,
|
|
1975
|
-
options?.userId,
|
|
1976
|
-
options?.scopes,
|
|
1977
|
-
signal
|
|
1978
|
-
);
|
|
1979
|
-
if (options?.includeData) {
|
|
1980
|
-
response.data = await Promise.all(
|
|
1981
|
-
response.data.map(async (chart) => ({
|
|
1982
|
-
...chart,
|
|
1983
|
-
vega_lite_spec: {
|
|
1984
|
-
...chart.vega_lite_spec,
|
|
1985
|
-
data: {
|
|
1986
|
-
values: await queryEngine.execute(
|
|
1987
|
-
chart.sql,
|
|
1988
|
-
chart.sql_params ?? void 0,
|
|
1989
|
-
chart.target_db ?? void 0
|
|
1990
|
-
)
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
}))
|
|
1994
|
-
);
|
|
1995
|
-
}
|
|
1996
|
-
return response;
|
|
1997
|
-
}
|
|
1998
|
-
async function getChart(client, queryEngine, id, options, signal) {
|
|
1999
|
-
const tenantId = resolveTenantId(client, options?.tenantId);
|
|
2000
|
-
const chart = await client.get(
|
|
2001
|
-
`/charts/${encodeURIComponent(id)}`,
|
|
2002
|
-
tenantId,
|
|
2003
|
-
options?.userId,
|
|
2004
|
-
options?.scopes,
|
|
2005
|
-
signal
|
|
2006
|
-
);
|
|
2007
|
-
return {
|
|
2008
|
-
...chart,
|
|
2009
|
-
vega_lite_spec: {
|
|
2010
|
-
...chart.vega_lite_spec,
|
|
2011
|
-
data: {
|
|
2012
|
-
values: await queryEngine.execute(
|
|
2013
|
-
chart.sql,
|
|
2014
|
-
chart.sql_params ?? void 0,
|
|
2015
|
-
chart.target_db ?? void 0
|
|
2016
|
-
)
|
|
2017
|
-
}
|
|
2018
|
-
}
|
|
2019
|
-
};
|
|
2020
|
-
}
|
|
2021
|
-
async function updateChart(client, id, body, options, signal) {
|
|
2022
|
-
const tenantId = resolveTenantId(client, options?.tenantId);
|
|
2023
|
-
return await client.put(
|
|
2024
|
-
`/charts/${encodeURIComponent(id)}`,
|
|
2025
|
-
body,
|
|
2026
|
-
tenantId,
|
|
2027
|
-
options?.userId,
|
|
2028
|
-
options?.scopes,
|
|
2029
|
-
signal
|
|
2030
|
-
);
|
|
2031
|
-
}
|
|
2032
|
-
async function deleteChart(client, id, options, signal) {
|
|
2033
|
-
const tenantId = resolveTenantId(client, options?.tenantId);
|
|
2034
|
-
await client.delete(
|
|
2035
|
-
`/charts/${encodeURIComponent(id)}`,
|
|
2036
|
-
tenantId,
|
|
2037
|
-
options?.userId,
|
|
2038
|
-
options?.scopes,
|
|
2039
|
-
signal
|
|
2040
|
-
);
|
|
2041
|
-
}
|
|
2042
|
-
function resolveTenantId(client, tenantId) {
|
|
2043
|
-
const resolved = tenantId ?? client.getDefaultTenantId();
|
|
2044
|
-
if (!resolved) {
|
|
2045
|
-
throw new Error(
|
|
2046
|
-
"tenantId is required. Provide it per request or via defaultTenantId option."
|
|
2047
|
-
);
|
|
2048
|
-
}
|
|
2049
|
-
return resolved;
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
// src/routes/active-charts.ts
|
|
2053
|
-
async function createActiveChart(client, body, options, signal) {
|
|
2054
|
-
const tenantId = resolveTenantId2(client, options?.tenantId);
|
|
2055
|
-
return await client.post(
|
|
2056
|
-
"/active-charts",
|
|
2057
|
-
body,
|
|
2058
|
-
tenantId,
|
|
2059
|
-
options?.userId,
|
|
2060
|
-
options?.scopes,
|
|
2061
|
-
signal
|
|
2062
|
-
);
|
|
2063
|
-
}
|
|
2064
|
-
async function listActiveCharts(client, queryEngine, options, signal) {
|
|
2065
|
-
const tenantId = resolveTenantId2(client, options?.tenantId);
|
|
2066
|
-
const params = new URLSearchParams();
|
|
2067
|
-
if (options?.pagination?.page)
|
|
2068
|
-
params.set("page", `${options.pagination.page}`);
|
|
2069
|
-
if (options?.pagination?.limit)
|
|
2070
|
-
params.set("limit", `${options.pagination.limit}`);
|
|
2071
|
-
if (options?.sortBy) params.set("sort_by", options.sortBy);
|
|
2072
|
-
if (options?.sortDir) params.set("sort_dir", options.sortDir);
|
|
2073
|
-
if (options?.title) params.set("name", options.title);
|
|
2074
|
-
if (options?.userFilter) params.set("user_id", options.userFilter);
|
|
2075
|
-
if (options?.createdFrom) params.set("created_from", options.createdFrom);
|
|
2076
|
-
if (options?.createdTo) params.set("created_to", options.createdTo);
|
|
2077
|
-
if (options?.updatedFrom) params.set("updated_from", options.updatedFrom);
|
|
2078
|
-
if (options?.updatedTo) params.set("updated_to", options.updatedTo);
|
|
2079
|
-
const response = await client.get(
|
|
2080
|
-
`/active-charts${params.toString() ? `?${params.toString()}` : ""}`,
|
|
2081
|
-
tenantId,
|
|
2082
|
-
options?.userId,
|
|
2083
|
-
options?.scopes,
|
|
2084
|
-
signal
|
|
2085
|
-
);
|
|
2086
|
-
if (options?.withData) {
|
|
2087
|
-
response.data = await Promise.all(
|
|
2088
|
-
response.data.map(async (active) => ({
|
|
2089
|
-
...active,
|
|
2090
|
-
chart: active.chart ? await getChart(
|
|
2091
|
-
client,
|
|
2092
|
-
queryEngine,
|
|
2093
|
-
active.chart_id,
|
|
2094
|
-
options,
|
|
2095
|
-
signal
|
|
2096
|
-
) : null
|
|
2097
|
-
}))
|
|
2098
|
-
);
|
|
2099
|
-
}
|
|
2100
|
-
return response;
|
|
2101
|
-
}
|
|
2102
|
-
async function getActiveChart(client, queryEngine, id, options, signal) {
|
|
2103
|
-
const tenantId = resolveTenantId2(client, options?.tenantId);
|
|
2104
|
-
const active = await client.get(
|
|
2105
|
-
`/active-charts/${encodeURIComponent(id)}`,
|
|
2106
|
-
tenantId,
|
|
2107
|
-
options?.userId,
|
|
2108
|
-
options?.scopes,
|
|
2109
|
-
signal
|
|
2110
|
-
);
|
|
2111
|
-
if (options?.withData && active.chart_id) {
|
|
2112
|
-
return {
|
|
2113
|
-
...active,
|
|
2114
|
-
chart: await getChart(
|
|
2115
|
-
client,
|
|
2116
|
-
queryEngine,
|
|
2117
|
-
active.chart_id,
|
|
2118
|
-
options,
|
|
2119
|
-
signal
|
|
2120
|
-
)
|
|
2121
|
-
};
|
|
2122
|
-
}
|
|
2123
|
-
return active;
|
|
2124
|
-
}
|
|
2125
|
-
async function updateActiveChart(client, id, body, options, signal) {
|
|
2126
|
-
const tenantId = resolveTenantId2(client, options?.tenantId);
|
|
2127
|
-
return await client.put(
|
|
2128
|
-
`/active-charts/${encodeURIComponent(id)}`,
|
|
2129
|
-
body,
|
|
2130
|
-
tenantId,
|
|
2131
|
-
options?.userId,
|
|
2132
|
-
options?.scopes,
|
|
2133
|
-
signal
|
|
2134
|
-
);
|
|
2135
|
-
}
|
|
2136
|
-
async function deleteActiveChart(client, id, options, signal) {
|
|
2137
|
-
const tenantId = resolveTenantId2(client, options?.tenantId);
|
|
2138
|
-
await client.delete(
|
|
2139
|
-
`/active-charts/${encodeURIComponent(id)}`,
|
|
2140
|
-
tenantId,
|
|
2141
|
-
options?.userId,
|
|
2142
|
-
options?.scopes,
|
|
2143
|
-
signal
|
|
2144
|
-
);
|
|
2145
|
-
}
|
|
2146
|
-
function resolveTenantId2(client, tenantId) {
|
|
2147
|
-
const resolved = tenantId ?? client.getDefaultTenantId();
|
|
2148
|
-
if (!resolved) {
|
|
2149
|
-
throw new Error(
|
|
2150
|
-
"tenantId is required. Provide it per request or via defaultTenantId option."
|
|
2151
|
-
);
|
|
2152
|
-
}
|
|
2153
|
-
return resolved;
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
|
-
// src/routes/ingest.ts
|
|
2157
|
-
import { randomUUID } from "crypto";
|
|
2158
|
-
async function syncSchema(client, queryEngine, databaseName, options, signal) {
|
|
2159
|
-
const tenantId = resolveTenantId3(client, options.tenantId);
|
|
2160
|
-
const adapter = queryEngine.getDatabase(databaseName);
|
|
2161
|
-
const introspection = await adapter.introspect(
|
|
2162
|
-
options.tables ? { tables: options.tables } : void 0
|
|
2163
|
-
);
|
|
2164
|
-
const payload = buildSchemaRequest(databaseName, adapter, introspection);
|
|
2165
|
-
const sessionId = randomUUID();
|
|
2166
|
-
const response = await client.post(
|
|
2167
|
-
"/ingest",
|
|
2168
|
-
payload,
|
|
2169
|
-
tenantId,
|
|
2170
|
-
options.userId,
|
|
2171
|
-
options.scopes,
|
|
2172
|
-
signal,
|
|
2173
|
-
sessionId
|
|
2174
|
-
);
|
|
2175
|
-
return response;
|
|
2176
|
-
}
|
|
2177
|
-
function resolveTenantId3(client, tenantId) {
|
|
2178
|
-
const resolved = tenantId ?? client.getDefaultTenantId();
|
|
2179
|
-
if (!resolved) {
|
|
2180
|
-
throw new Error(
|
|
2181
|
-
"tenantId is required. Provide it per request or via defaultTenantId option."
|
|
2182
|
-
);
|
|
2183
|
-
}
|
|
2184
|
-
return resolved;
|
|
2185
|
-
}
|
|
2186
|
-
function buildSchemaRequest(databaseName, adapter, introspection) {
|
|
2187
|
-
const dialect = adapter.getDialect();
|
|
2188
|
-
const tables = introspection.tables.map((table) => ({
|
|
2189
|
-
table_name: table.name,
|
|
2190
|
-
description: table.comment ?? `Table ${table.name}`,
|
|
2191
|
-
columns: table.columns.map((column) => ({
|
|
2192
|
-
name: column.name,
|
|
2193
|
-
data_type: column.rawType ?? column.type,
|
|
2194
|
-
is_primary_key: Boolean(column.isPrimaryKey),
|
|
2195
|
-
description: column.comment ?? ""
|
|
2196
|
-
}))
|
|
2197
|
-
}));
|
|
2198
|
-
return {
|
|
2199
|
-
database: databaseName,
|
|
2200
|
-
dialect,
|
|
2201
|
-
tables
|
|
2202
|
-
};
|
|
2203
|
-
}
|
|
2204
|
-
|
|
2205
|
-
// src/routes/query.ts
|
|
2206
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
2207
|
-
async function ask(client, queryEngine, question, options, signal) {
|
|
2208
|
-
const tenantId = resolveTenantId4(client, options.tenantId);
|
|
2209
|
-
const sessionId = randomUUID2();
|
|
2210
|
-
const maxRetry = options.maxRetry ?? 0;
|
|
2211
|
-
let attempt = 0;
|
|
2212
|
-
let lastError = options.lastError;
|
|
2213
|
-
let previousSql = options.previousSql;
|
|
2214
|
-
while (attempt <= maxRetry) {
|
|
2215
|
-
console.log({ lastError, previousSql });
|
|
2216
|
-
const queryResponse = await client.post(
|
|
2217
|
-
"/query",
|
|
2218
|
-
{
|
|
2219
|
-
question,
|
|
2220
|
-
...lastError ? { last_error: lastError } : {},
|
|
2221
|
-
...previousSql ? { previous_sql: previousSql } : {},
|
|
2222
|
-
...options.maxRetry ? { max_retry: options.maxRetry } : {}
|
|
2223
|
-
},
|
|
2224
|
-
tenantId,
|
|
2225
|
-
options.userId,
|
|
2226
|
-
options.scopes,
|
|
2227
|
-
signal,
|
|
2228
|
-
sessionId
|
|
2229
|
-
);
|
|
2230
|
-
const databaseName = queryResponse.database ?? options.database ?? queryEngine.getDefaultDatabase();
|
|
2231
|
-
if (!databaseName) {
|
|
2232
|
-
throw new Error(
|
|
2233
|
-
"No database attached. Call attachPostgres/attachClickhouse first."
|
|
2234
|
-
);
|
|
2235
|
-
}
|
|
2236
|
-
const paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
|
|
2237
|
-
const paramValues = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1411
|
+
async runSafeQueryOnClient(sql, database, params) {
|
|
2238
1412
|
try {
|
|
2239
|
-
const
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
databaseName,
|
|
2243
|
-
tenantId
|
|
2244
|
-
);
|
|
2245
|
-
const rows = execution.rows ?? [];
|
|
2246
|
-
let chart = {
|
|
2247
|
-
vegaLiteSpec: null,
|
|
2248
|
-
notes: rows.length === 0 ? "Query returned no rows." : null
|
|
2249
|
-
};
|
|
2250
|
-
if (rows.length > 0) {
|
|
2251
|
-
const chartResponse = await client.post(
|
|
2252
|
-
"/chart",
|
|
2253
|
-
{
|
|
2254
|
-
question,
|
|
2255
|
-
sql: queryResponse.sql,
|
|
2256
|
-
rationale: queryResponse.rationale,
|
|
2257
|
-
fields: execution.fields,
|
|
2258
|
-
rows: anonymizeResults(rows),
|
|
2259
|
-
max_retries: options.chartMaxRetries ?? 3,
|
|
2260
|
-
query_id: queryResponse.queryId
|
|
2261
|
-
},
|
|
2262
|
-
tenantId,
|
|
2263
|
-
options.userId,
|
|
2264
|
-
options.scopes,
|
|
2265
|
-
signal,
|
|
2266
|
-
sessionId
|
|
2267
|
-
);
|
|
2268
|
-
chart = {
|
|
2269
|
-
vegaLiteSpec: chartResponse.chart ? {
|
|
2270
|
-
...chartResponse.chart,
|
|
2271
|
-
data: { values: rows }
|
|
2272
|
-
} : null,
|
|
2273
|
-
notes: chartResponse.notes
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
|
-
return {
|
|
2277
|
-
sql: queryResponse.sql,
|
|
2278
|
-
params: paramValues,
|
|
2279
|
-
paramMetadata,
|
|
2280
|
-
rationale: queryResponse.rationale,
|
|
2281
|
-
dialect: queryResponse.dialect,
|
|
2282
|
-
queryId: queryResponse.queryId,
|
|
2283
|
-
rows,
|
|
2284
|
-
fields: execution.fields,
|
|
2285
|
-
chart,
|
|
2286
|
-
context: queryResponse.context,
|
|
2287
|
-
attempts: attempt + 1
|
|
2288
|
-
};
|
|
1413
|
+
const adapter = this.getDatabase(database);
|
|
1414
|
+
const result = await adapter.execute(sql, params);
|
|
1415
|
+
return result.rows;
|
|
2289
1416
|
} catch (error) {
|
|
2290
|
-
attempt++;
|
|
2291
|
-
if (attempt > maxRetry) {
|
|
2292
|
-
throw error;
|
|
2293
|
-
}
|
|
2294
|
-
lastError = error instanceof Error ? error.message : String(error);
|
|
2295
|
-
previousSql = queryResponse.sql;
|
|
2296
1417
|
console.warn(
|
|
2297
|
-
`
|
|
1418
|
+
`Failed to execute SQL locally for database '${database}':`,
|
|
1419
|
+
error
|
|
2298
1420
|
);
|
|
1421
|
+
return [];
|
|
2299
1422
|
}
|
|
2300
1423
|
}
|
|
2301
|
-
|
|
2302
|
-
}
|
|
2303
|
-
function resolveTenantId4(client, tenantId) {
|
|
2304
|
-
const resolved = tenantId ?? client.getDefaultTenantId();
|
|
2305
|
-
if (!resolved) {
|
|
2306
|
-
throw new Error(
|
|
2307
|
-
"tenantId is required. Provide it per request or via defaultTenantId option."
|
|
2308
|
-
);
|
|
2309
|
-
}
|
|
2310
|
-
return resolved;
|
|
2311
|
-
}
|
|
1424
|
+
};
|
|
2312
1425
|
function anonymizeResults(rows) {
|
|
2313
1426
|
if (!rows?.length) return [];
|
|
2314
1427
|
return rows.map((row) => {
|
|
@@ -2321,144 +1434,6 @@ function anonymizeResults(rows) {
|
|
|
2321
1434
|
return masked;
|
|
2322
1435
|
});
|
|
2323
1436
|
}
|
|
2324
|
-
|
|
2325
|
-
// src/index.ts
|
|
2326
|
-
var QueryPanelSdkAPI = class {
|
|
2327
|
-
client;
|
|
2328
|
-
queryEngine;
|
|
2329
|
-
constructor(baseUrl, privateKey, organizationId, options) {
|
|
2330
|
-
this.client = new ApiClient(baseUrl, privateKey, organizationId, options);
|
|
2331
|
-
this.queryEngine = new QueryEngine();
|
|
2332
|
-
}
|
|
2333
|
-
// Database attachment methods
|
|
2334
|
-
attachClickhouse(name, clientFn, options) {
|
|
2335
|
-
const adapter = new ClickHouseAdapter(clientFn, options);
|
|
2336
|
-
const metadata = {
|
|
2337
|
-
name,
|
|
2338
|
-
dialect: "clickhouse",
|
|
2339
|
-
description: options?.description,
|
|
2340
|
-
tags: options?.tags,
|
|
2341
|
-
tenantFieldName: options?.tenantFieldName,
|
|
2342
|
-
tenantFieldType: options?.tenantFieldType ?? "String",
|
|
2343
|
-
enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
|
|
2344
|
-
};
|
|
2345
|
-
this.queryEngine.attachDatabase(name, adapter, metadata);
|
|
2346
|
-
}
|
|
2347
|
-
attachPostgres(name, clientFn, options) {
|
|
2348
|
-
const adapter = new PostgresAdapter(clientFn, options);
|
|
2349
|
-
const metadata = {
|
|
2350
|
-
name,
|
|
2351
|
-
dialect: "postgres",
|
|
2352
|
-
description: options?.description,
|
|
2353
|
-
tags: options?.tags,
|
|
2354
|
-
tenantFieldName: options?.tenantFieldName,
|
|
2355
|
-
enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
|
|
2356
|
-
};
|
|
2357
|
-
this.queryEngine.attachDatabase(name, adapter, metadata);
|
|
2358
|
-
}
|
|
2359
|
-
attachDatabase(name, adapter) {
|
|
2360
|
-
const metadata = {
|
|
2361
|
-
name,
|
|
2362
|
-
dialect: adapter.getDialect()
|
|
2363
|
-
};
|
|
2364
|
-
this.queryEngine.attachDatabase(name, adapter, metadata);
|
|
2365
|
-
}
|
|
2366
|
-
// Schema introspection and sync
|
|
2367
|
-
async introspect(databaseName, tables) {
|
|
2368
|
-
const adapter = this.queryEngine.getDatabase(databaseName);
|
|
2369
|
-
return await adapter.introspect(tables ? { tables } : void 0);
|
|
2370
|
-
}
|
|
2371
|
-
async syncSchema(databaseName, options, signal) {
|
|
2372
|
-
return await syncSchema(
|
|
2373
|
-
this.client,
|
|
2374
|
-
this.queryEngine,
|
|
2375
|
-
databaseName,
|
|
2376
|
-
options,
|
|
2377
|
-
signal
|
|
2378
|
-
);
|
|
2379
|
-
}
|
|
2380
|
-
// Natural language query
|
|
2381
|
-
async ask(question, options, signal) {
|
|
2382
|
-
return await ask(
|
|
2383
|
-
this.client,
|
|
2384
|
-
this.queryEngine,
|
|
2385
|
-
question,
|
|
2386
|
-
options,
|
|
2387
|
-
signal
|
|
2388
|
-
);
|
|
2389
|
-
}
|
|
2390
|
-
// Chart CRUD operations
|
|
2391
|
-
async createChart(body, options, signal) {
|
|
2392
|
-
return await createChart(this.client, body, options, signal);
|
|
2393
|
-
}
|
|
2394
|
-
async listCharts(options, signal) {
|
|
2395
|
-
return await listCharts(
|
|
2396
|
-
this.client,
|
|
2397
|
-
this.queryEngine,
|
|
2398
|
-
options,
|
|
2399
|
-
signal
|
|
2400
|
-
);
|
|
2401
|
-
}
|
|
2402
|
-
async getChart(id, options, signal) {
|
|
2403
|
-
return await getChart(
|
|
2404
|
-
this.client,
|
|
2405
|
-
this.queryEngine,
|
|
2406
|
-
id,
|
|
2407
|
-
options,
|
|
2408
|
-
signal
|
|
2409
|
-
);
|
|
2410
|
-
}
|
|
2411
|
-
async updateChart(id, body, options, signal) {
|
|
2412
|
-
return await updateChart(
|
|
2413
|
-
this.client,
|
|
2414
|
-
id,
|
|
2415
|
-
body,
|
|
2416
|
-
options,
|
|
2417
|
-
signal
|
|
2418
|
-
);
|
|
2419
|
-
}
|
|
2420
|
-
async deleteChart(id, options, signal) {
|
|
2421
|
-
await deleteChart(this.client, id, options, signal);
|
|
2422
|
-
}
|
|
2423
|
-
// Active Chart CRUD operations
|
|
2424
|
-
async createActiveChart(body, options, signal) {
|
|
2425
|
-
return await createActiveChart(
|
|
2426
|
-
this.client,
|
|
2427
|
-
body,
|
|
2428
|
-
options,
|
|
2429
|
-
signal
|
|
2430
|
-
);
|
|
2431
|
-
}
|
|
2432
|
-
async listActiveCharts(options, signal) {
|
|
2433
|
-
return await listActiveCharts(
|
|
2434
|
-
this.client,
|
|
2435
|
-
this.queryEngine,
|
|
2436
|
-
options,
|
|
2437
|
-
signal
|
|
2438
|
-
);
|
|
2439
|
-
}
|
|
2440
|
-
async getActiveChart(id, options, signal) {
|
|
2441
|
-
return await getActiveChart(
|
|
2442
|
-
this.client,
|
|
2443
|
-
this.queryEngine,
|
|
2444
|
-
id,
|
|
2445
|
-
options,
|
|
2446
|
-
signal
|
|
2447
|
-
);
|
|
2448
|
-
}
|
|
2449
|
-
async updateActiveChart(id, body, options, signal) {
|
|
2450
|
-
return await updateActiveChart(
|
|
2451
|
-
this.client,
|
|
2452
|
-
id,
|
|
2453
|
-
body,
|
|
2454
|
-
options,
|
|
2455
|
-
signal
|
|
2456
|
-
);
|
|
2457
|
-
}
|
|
2458
|
-
async deleteActiveChart(id, options, signal) {
|
|
2459
|
-
await deleteActiveChart(this.client, id, options, signal);
|
|
2460
|
-
}
|
|
2461
|
-
};
|
|
2462
1437
|
export {
|
|
2463
1438
|
ClickHouseAdapter,
|
|
2464
1439
|
PostgresAdapter,
|