@querypanel/node-sdk 1.0.57 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.cjs +229 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -6
- package/dist/index.d.ts +80 -6
- package/dist/index.js +228 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,183 @@
|
|
|
1
|
+
// src/adapters/bigquery.ts
|
|
2
|
+
var BigQueryAdapter = class {
|
|
3
|
+
constructor(clientFn, options) {
|
|
4
|
+
this.clientFn = clientFn;
|
|
5
|
+
this.projectId = options.projectId;
|
|
6
|
+
this.datasetProjectId = options.datasetProjectId ?? options.projectId;
|
|
7
|
+
this.defaultDataset = options.dataset;
|
|
8
|
+
this.databaseName = options.database ?? options.dataset;
|
|
9
|
+
this.kind = options.kind ?? "bigquery";
|
|
10
|
+
if (options.allowedTables) {
|
|
11
|
+
this.allowedTables = normalizeTableFilter(
|
|
12
|
+
options.allowedTables,
|
|
13
|
+
this.defaultDataset
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
projectId;
|
|
18
|
+
datasetProjectId;
|
|
19
|
+
defaultDataset;
|
|
20
|
+
databaseName;
|
|
21
|
+
kind;
|
|
22
|
+
allowedTables;
|
|
23
|
+
async execute(sql, params) {
|
|
24
|
+
if (this.allowedTables) {
|
|
25
|
+
this.validateQueryTables(sql);
|
|
26
|
+
}
|
|
27
|
+
const result = await this.clientFn({
|
|
28
|
+
query: sql,
|
|
29
|
+
params,
|
|
30
|
+
dryRun: false
|
|
31
|
+
});
|
|
32
|
+
return { fields: result.fields, rows: result.rows };
|
|
33
|
+
}
|
|
34
|
+
async validate(sql, params) {
|
|
35
|
+
await this.clientFn({
|
|
36
|
+
query: sql,
|
|
37
|
+
params,
|
|
38
|
+
dryRun: true
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
getDialect() {
|
|
42
|
+
return "bigquery";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Introspect using BigQuery INFORMATION_SCHEMA (TABLES and COLUMNS).
|
|
46
|
+
* Restricts to the default dataset (or allowedTables) and returns tables/columns only.
|
|
47
|
+
*/
|
|
48
|
+
async introspect(options) {
|
|
49
|
+
const tablesToIntrospect = options?.tables ? normalizeTableFilter(options.tables, this.defaultDataset) : this.allowedTables;
|
|
50
|
+
const normalizedTables = tablesToIntrospect ?? [];
|
|
51
|
+
const tablesSql = buildTablesQuery(
|
|
52
|
+
this.datasetProjectId,
|
|
53
|
+
this.defaultDataset,
|
|
54
|
+
normalizedTables
|
|
55
|
+
);
|
|
56
|
+
const tablesResult = await this.clientFn({
|
|
57
|
+
query: tablesSql,
|
|
58
|
+
dryRun: false
|
|
59
|
+
});
|
|
60
|
+
const tableRows = tablesResult.rows;
|
|
61
|
+
const columnsSql = buildColumnsQuery(
|
|
62
|
+
this.datasetProjectId,
|
|
63
|
+
this.defaultDataset,
|
|
64
|
+
normalizedTables
|
|
65
|
+
);
|
|
66
|
+
const columnsResult = await this.clientFn({
|
|
67
|
+
query: columnsSql,
|
|
68
|
+
dryRun: false
|
|
69
|
+
});
|
|
70
|
+
const columnRows = columnsResult.rows;
|
|
71
|
+
const tablesByKey = /* @__PURE__ */ new Map();
|
|
72
|
+
for (const row of tableRows) {
|
|
73
|
+
const key = tableKey(row.table_schema, row.table_name);
|
|
74
|
+
const table = {
|
|
75
|
+
name: row.table_name,
|
|
76
|
+
schema: row.table_schema,
|
|
77
|
+
type: asTableType(row.table_type),
|
|
78
|
+
columns: []
|
|
79
|
+
};
|
|
80
|
+
tablesByKey.set(key, table);
|
|
81
|
+
}
|
|
82
|
+
for (const row of columnRows) {
|
|
83
|
+
const key = tableKey(row.table_schema, row.table_name);
|
|
84
|
+
const table = tablesByKey.get(key);
|
|
85
|
+
if (!table) continue;
|
|
86
|
+
const column = {
|
|
87
|
+
name: row.column_name,
|
|
88
|
+
type: row.data_type,
|
|
89
|
+
isPrimaryKey: false
|
|
90
|
+
};
|
|
91
|
+
table.columns.push(column);
|
|
92
|
+
}
|
|
93
|
+
const tables = Array.from(tablesByKey.values()).sort((a, b) => {
|
|
94
|
+
if (a.schema === b.schema) {
|
|
95
|
+
return a.name.localeCompare(b.name);
|
|
96
|
+
}
|
|
97
|
+
return a.schema.localeCompare(b.schema);
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
db: {
|
|
101
|
+
kind: this.kind,
|
|
102
|
+
name: this.databaseName
|
|
103
|
+
},
|
|
104
|
+
tables,
|
|
105
|
+
introspectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
validateQueryTables(sql) {
|
|
109
|
+
if (!this.allowedTables || this.allowedTables.length === 0) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const allowedSet = new Set(
|
|
113
|
+
this.allowedTables.map((t) => tableKey(t.dataset, t.table))
|
|
114
|
+
);
|
|
115
|
+
const tablePattern = /(?:FROM|JOIN)\s+`?(?:[\w-]+\.)?([\w-]+)\.([\w-]+)`?|(?:FROM|JOIN)\s+`?([\w-]+)`?/gi;
|
|
116
|
+
const matches = sql.matchAll(tablePattern);
|
|
117
|
+
for (const match of matches) {
|
|
118
|
+
const dataset = match[1] ?? match[3] ?? this.defaultDataset;
|
|
119
|
+
const table = match[2] ?? match[3];
|
|
120
|
+
if (table) {
|
|
121
|
+
const key = tableKey(dataset, table);
|
|
122
|
+
if (!allowedSet.has(key)) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Query references table "${dataset}.${table}" which is not in the allowed tables list`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
function normalizeTableFilter(tables, defaultDataset) {
|
|
132
|
+
if (!tables?.length) return [];
|
|
133
|
+
const normalized = [];
|
|
134
|
+
const seen = /* @__PURE__ */ new Set();
|
|
135
|
+
for (const raw of tables) {
|
|
136
|
+
if (!raw?.trim()) continue;
|
|
137
|
+
const trimmed = raw.trim();
|
|
138
|
+
const parts = trimmed.split(".");
|
|
139
|
+
const table = parts.pop() ?? "";
|
|
140
|
+
const dataset = parts.pop() ?? defaultDataset;
|
|
141
|
+
const key = tableKey(dataset, table);
|
|
142
|
+
if (seen.has(key)) continue;
|
|
143
|
+
seen.add(key);
|
|
144
|
+
normalized.push({ dataset, table });
|
|
145
|
+
}
|
|
146
|
+
return normalized;
|
|
147
|
+
}
|
|
148
|
+
function tableKey(dataset, table) {
|
|
149
|
+
return `${dataset}.${table}`;
|
|
150
|
+
}
|
|
151
|
+
function buildTablesQuery(datasetProjectId, dataset, tables) {
|
|
152
|
+
const qualifier = `\`${datasetProjectId}.${dataset}.INFORMATION_SCHEMA.TABLES\``;
|
|
153
|
+
const filter = tables.length > 0 ? ` AND table_name IN (${tables.map((t) => `'${escapeSql(t.table)}'`).join(", ")})` : "";
|
|
154
|
+
return `SELECT table_name, table_schema, table_type
|
|
155
|
+
FROM ${qualifier}
|
|
156
|
+
WHERE table_schema = '${escapeSql(dataset)}'${filter}
|
|
157
|
+
ORDER BY table_schema, table_name`;
|
|
158
|
+
}
|
|
159
|
+
function buildColumnsQuery(datasetProjectId, dataset, tables) {
|
|
160
|
+
const qualifier = `\`${datasetProjectId}.${dataset}.INFORMATION_SCHEMA.COLUMNS\``;
|
|
161
|
+
const filter = tables.length > 0 ? ` AND table_name IN (${tables.map((t) => `'${escapeSql(t.table)}'`).join(", ")})` : "";
|
|
162
|
+
return `SELECT table_name, table_schema, column_name, data_type, ordinal_position, is_nullable
|
|
163
|
+
FROM ${qualifier}
|
|
164
|
+
WHERE table_schema = '${escapeSql(dataset)}'${filter}
|
|
165
|
+
ORDER BY table_schema, table_name, ordinal_position`;
|
|
166
|
+
}
|
|
167
|
+
function escapeSql(value) {
|
|
168
|
+
return value.replace(/\\/g, "\\\\").replace(/'/g, "''");
|
|
169
|
+
}
|
|
170
|
+
function asTableType(tableType) {
|
|
171
|
+
const normalized = tableType?.toLowerCase() ?? "";
|
|
172
|
+
if (normalized.includes("view")) {
|
|
173
|
+
return normalized.includes("materialized") ? "materialized_view" : "view";
|
|
174
|
+
}
|
|
175
|
+
if (normalized.includes("external") || normalized.includes("snapshot") || normalized.includes("clone")) {
|
|
176
|
+
return "table";
|
|
177
|
+
}
|
|
178
|
+
return "table";
|
|
179
|
+
}
|
|
180
|
+
|
|
1
181
|
// src/utils/clickhouse.ts
|
|
2
182
|
var WRAPPER_REGEX = /^(Nullable|LowCardinality|SimpleAggregateFunction)\((.+)\)$/i;
|
|
3
183
|
function unwrapTypeModifiers(type) {
|
|
@@ -67,7 +247,7 @@ var ClickHouseAdapter = class {
|
|
|
67
247
|
this.defaultFormat = options.defaultFormat ?? "JSONEachRow";
|
|
68
248
|
this.kind = options.kind ?? "clickhouse";
|
|
69
249
|
if (options.allowedTables) {
|
|
70
|
-
this.allowedTables =
|
|
250
|
+
this.allowedTables = normalizeTableFilter2(options.allowedTables);
|
|
71
251
|
}
|
|
72
252
|
}
|
|
73
253
|
databaseName;
|
|
@@ -105,7 +285,7 @@ var ClickHouseAdapter = class {
|
|
|
105
285
|
* No indexes, constraints, or statistics
|
|
106
286
|
*/
|
|
107
287
|
async introspect(options) {
|
|
108
|
-
const tablesToIntrospect = options?.tables ?
|
|
288
|
+
const tablesToIntrospect = options?.tables ? normalizeTableFilter2(options.tables) : this.allowedTables;
|
|
109
289
|
const allowTables = tablesToIntrospect ?? [];
|
|
110
290
|
const hasFilter = allowTables.length > 0;
|
|
111
291
|
const queryParams = {
|
|
@@ -145,7 +325,7 @@ var ClickHouseAdapter = class {
|
|
|
145
325
|
const base = {
|
|
146
326
|
name: table.name,
|
|
147
327
|
schema: this.databaseName,
|
|
148
|
-
type:
|
|
328
|
+
type: asTableType2(table.engine),
|
|
149
329
|
columns: tableColumns
|
|
150
330
|
};
|
|
151
331
|
const comment = sanitize(table.comment);
|
|
@@ -223,7 +403,7 @@ function normalizePayload(payload) {
|
|
|
223
403
|
}
|
|
224
404
|
return [];
|
|
225
405
|
}
|
|
226
|
-
function
|
|
406
|
+
function normalizeTableFilter2(tables) {
|
|
227
407
|
if (!tables?.length) return [];
|
|
228
408
|
const seen = /* @__PURE__ */ new Set();
|
|
229
409
|
const normalized = [];
|
|
@@ -251,7 +431,7 @@ function transformColumnRow(row) {
|
|
|
251
431
|
if (comment !== void 0) column.comment = comment;
|
|
252
432
|
return column;
|
|
253
433
|
}
|
|
254
|
-
function
|
|
434
|
+
function asTableType2(engine) {
|
|
255
435
|
if (typeof engine === "string") {
|
|
256
436
|
const normalized = engine.toLowerCase();
|
|
257
437
|
if (normalized.includes("view")) {
|
|
@@ -280,7 +460,7 @@ var PostgresAdapter = class {
|
|
|
280
460
|
this.defaultSchema = options.defaultSchema ?? "public";
|
|
281
461
|
this.kind = options.kind ?? "postgres";
|
|
282
462
|
if (options.allowedTables) {
|
|
283
|
-
this.allowedTables =
|
|
463
|
+
this.allowedTables = normalizeTableFilter3(
|
|
284
464
|
options.allowedTables,
|
|
285
465
|
this.defaultSchema
|
|
286
466
|
);
|
|
@@ -307,7 +487,7 @@ var PostgresAdapter = class {
|
|
|
307
487
|
return;
|
|
308
488
|
}
|
|
309
489
|
const allowedSet = new Set(
|
|
310
|
-
this.allowedTables.map((t) =>
|
|
490
|
+
this.allowedTables.map((t) => tableKey2(t.schema, t.table))
|
|
311
491
|
);
|
|
312
492
|
const neutralizedSql = sql.replace(/EXTRACT\s*\([^)]*FROM\s+[^)]+\)/gi, "EXTRACT(/*neutralized*/)").replace(/SUBSTRING\s*\([^)]*FROM\s+[^)]+\)/gi, "SUBSTRING(/*neutralized*/)").replace(/TRIM\s*\([^)]*FROM\s+[^)]+\)/gi, "TRIM(/*neutralized*/)").replace(/POSITION\s*\([^)]*FROM\s+[^)]+\)/gi, "POSITION(/*neutralized*/)");
|
|
313
493
|
const tablePattern = /(?:FROM|JOIN)\s+(?:ONLY\s+)?(?:([a-zA-Z_][a-zA-Z0-9_]*)\.)?(["']?[a-zA-Z_][a-zA-Z0-9_]*["']?)/gi;
|
|
@@ -316,7 +496,7 @@ var PostgresAdapter = class {
|
|
|
316
496
|
const schema = match[1] ?? this.defaultSchema;
|
|
317
497
|
const table = match[2]?.replace(/['"]/g, "");
|
|
318
498
|
if (table) {
|
|
319
|
-
const key =
|
|
499
|
+
const key = tableKey2(schema, table);
|
|
320
500
|
if (!allowedSet.has(key)) {
|
|
321
501
|
throw new Error(
|
|
322
502
|
`Query references table "${schema}.${table}" which is not in the allowed tables list`
|
|
@@ -367,23 +547,23 @@ var PostgresAdapter = class {
|
|
|
367
547
|
* No indexes, constraints, or statistics
|
|
368
548
|
*/
|
|
369
549
|
async introspect(options) {
|
|
370
|
-
const tablesToIntrospect = options?.tables ?
|
|
550
|
+
const tablesToIntrospect = options?.tables ? normalizeTableFilter3(options.tables, this.defaultSchema) : this.allowedTables;
|
|
371
551
|
const normalizedTables = tablesToIntrospect ?? [];
|
|
372
552
|
const tablesResult = await this.clientFn(
|
|
373
|
-
|
|
553
|
+
buildTablesQuery2(normalizedTables)
|
|
374
554
|
);
|
|
375
555
|
const tableRows = tablesResult.rows;
|
|
376
556
|
const columnsResult = await this.clientFn(
|
|
377
|
-
|
|
557
|
+
buildColumnsQuery2(normalizedTables)
|
|
378
558
|
);
|
|
379
559
|
const columnRows = columnsResult.rows;
|
|
380
560
|
const tablesByKey = /* @__PURE__ */ new Map();
|
|
381
561
|
for (const row of tableRows) {
|
|
382
|
-
const key =
|
|
562
|
+
const key = tableKey2(row.schema_name, row.table_name);
|
|
383
563
|
const table = {
|
|
384
564
|
name: row.table_name,
|
|
385
565
|
schema: row.schema_name,
|
|
386
|
-
type:
|
|
566
|
+
type: asTableType3(row.table_type),
|
|
387
567
|
columns: []
|
|
388
568
|
};
|
|
389
569
|
const comment = sanitize2(row.comment);
|
|
@@ -393,7 +573,7 @@ var PostgresAdapter = class {
|
|
|
393
573
|
tablesByKey.set(key, table);
|
|
394
574
|
}
|
|
395
575
|
for (const row of columnRows) {
|
|
396
|
-
const key =
|
|
576
|
+
const key = tableKey2(row.table_schema, row.table_name);
|
|
397
577
|
const table = tablesByKey.get(key);
|
|
398
578
|
if (!table) continue;
|
|
399
579
|
const column = {
|
|
@@ -423,7 +603,7 @@ var PostgresAdapter = class {
|
|
|
423
603
|
};
|
|
424
604
|
}
|
|
425
605
|
};
|
|
426
|
-
function
|
|
606
|
+
function normalizeTableFilter3(tables, defaultSchema) {
|
|
427
607
|
if (!tables?.length) return [];
|
|
428
608
|
const normalized = [];
|
|
429
609
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -437,14 +617,14 @@ function normalizeTableFilter2(tables, defaultSchema) {
|
|
|
437
617
|
if (!isSafeIdentifier(schema) || !isSafeIdentifier(table)) {
|
|
438
618
|
continue;
|
|
439
619
|
}
|
|
440
|
-
const key =
|
|
620
|
+
const key = tableKey2(schema, table);
|
|
441
621
|
if (seen.has(key)) continue;
|
|
442
622
|
seen.add(key);
|
|
443
623
|
normalized.push({ schema, table });
|
|
444
624
|
}
|
|
445
625
|
return normalized;
|
|
446
626
|
}
|
|
447
|
-
function
|
|
627
|
+
function buildTablesQuery2(tables) {
|
|
448
628
|
const filter = buildFilterClause(tables, "n.nspname", "c.relname");
|
|
449
629
|
return `SELECT
|
|
450
630
|
c.relname AS table_name,
|
|
@@ -463,7 +643,7 @@ function buildTablesQuery(tables) {
|
|
|
463
643
|
${filter}
|
|
464
644
|
ORDER BY n.nspname, c.relname;`;
|
|
465
645
|
}
|
|
466
|
-
function
|
|
646
|
+
function buildColumnsQuery2(tables) {
|
|
467
647
|
const filter = buildFilterClause(
|
|
468
648
|
tables,
|
|
469
649
|
"cols.table_schema",
|
|
@@ -508,13 +688,13 @@ function buildFilterClause(tables, schemaExpr, tableExpr) {
|
|
|
508
688
|
});
|
|
509
689
|
return `AND (${clauses.join(" OR ")})`;
|
|
510
690
|
}
|
|
511
|
-
function
|
|
691
|
+
function tableKey2(schema, table) {
|
|
512
692
|
return `${schema}.${table}`;
|
|
513
693
|
}
|
|
514
694
|
function isSafeIdentifier(value) {
|
|
515
695
|
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(value);
|
|
516
696
|
}
|
|
517
|
-
function
|
|
697
|
+
function asTableType3(value) {
|
|
518
698
|
const normalized = value.toLowerCase();
|
|
519
699
|
if (normalized.includes("view")) {
|
|
520
700
|
return normalized.includes("materialized") ? "materialized_view" : "view";
|
|
@@ -982,6 +1162,9 @@ var QueryEngine = class {
|
|
|
982
1162
|
const paramKey = tenantField;
|
|
983
1163
|
params[paramKey] = tenantId;
|
|
984
1164
|
tenantPredicate = `${tenantField} = {${tenantField}:${metadata.tenantFieldType ?? "String"}}`;
|
|
1165
|
+
} else if (metadata.dialect === "bigquery") {
|
|
1166
|
+
params[tenantField] = tenantId;
|
|
1167
|
+
tenantPredicate = `${tenantField} = @${tenantField}`;
|
|
985
1168
|
} else {
|
|
986
1169
|
const escapedId = tenantId.replace(/'/g, "''");
|
|
987
1170
|
tenantPredicate = `${tenantField} = '${escapedId}'`;
|
|
@@ -1562,7 +1745,7 @@ async function ask(client, queryEngine, question, options, signal) {
|
|
|
1562
1745
|
const dbName = queryResponse.data.database ?? options.database ?? queryEngine.getDefaultDatabase();
|
|
1563
1746
|
if (!dbName) {
|
|
1564
1747
|
throw new Error(
|
|
1565
|
-
"No database attached. Call attachPostgres
|
|
1748
|
+
"No database attached. Call attachPostgres, attachClickhouse, or attachBigQuery first."
|
|
1566
1749
|
);
|
|
1567
1750
|
}
|
|
1568
1751
|
const paramMetadata = Array.isArray(queryResponse.data.params) ? queryResponse.data.params : [];
|
|
@@ -2103,20 +2286,22 @@ function resolveTenantId8(client, tenantId) {
|
|
|
2103
2286
|
var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
2104
2287
|
client;
|
|
2105
2288
|
queryEngine;
|
|
2106
|
-
|
|
2289
|
+
/**
|
|
2290
|
+
* @param workspaceId - Workspace UUID (same value as your org in the dashboard). Passed to the API as JWT claim `organizationId`.
|
|
2291
|
+
*/
|
|
2292
|
+
constructor(baseUrl, privateKey, workspaceId, options) {
|
|
2107
2293
|
if (options?.api) {
|
|
2108
2294
|
this.client = options.api;
|
|
2109
2295
|
} else {
|
|
2110
2296
|
if (!baseUrl) throw new Error("Base URL is required");
|
|
2111
2297
|
if (!privateKey) throw new Error("Private key is required");
|
|
2112
|
-
if (!
|
|
2113
|
-
this.client = new ApiClient(baseUrl, privateKey,
|
|
2298
|
+
if (!workspaceId) throw new Error("Workspace ID is required");
|
|
2299
|
+
this.client = new ApiClient(baseUrl, privateKey, workspaceId, {
|
|
2114
2300
|
defaultTenantId: options?.defaultTenantId,
|
|
2115
2301
|
additionalHeaders: options?.additionalHeaders,
|
|
2116
2302
|
fetch: options?.fetch
|
|
2117
2303
|
});
|
|
2118
2304
|
}
|
|
2119
|
-
if (!organizationId) throw new Error("Organization ID is required");
|
|
2120
2305
|
this.queryEngine = new QueryEngine();
|
|
2121
2306
|
}
|
|
2122
2307
|
/**
|
|
@@ -2125,7 +2310,7 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
2125
2310
|
* are handled in-process (e.g. by invoking querypanel-sdk services directly)
|
|
2126
2311
|
* and do not cause recursion.
|
|
2127
2312
|
*
|
|
2128
|
-
* @param
|
|
2313
|
+
* @param workspaceId - Workspace identifier (sent as `organizationId` in JWTs and API auth)
|
|
2129
2314
|
* @param requestHandler - Callback invoked for each logical API request (method, path, body, tenantId, etc.)
|
|
2130
2315
|
* @param options - Optional defaultTenantId
|
|
2131
2316
|
* @returns QueryPanelSdkAPI instance; attach databases and call ask(), syncSchema(), etc. as usual
|
|
@@ -2133,7 +2318,7 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
2133
2318
|
* @example
|
|
2134
2319
|
* ```ts
|
|
2135
2320
|
* const qp = QueryPanelSdkAPI.withCallbacks(
|
|
2136
|
-
* process.env.
|
|
2321
|
+
* process.env.QUERYPANEL_WORKSPACE_ID!,
|
|
2137
2322
|
* async (opts) => {
|
|
2138
2323
|
* // Call your in-process services (e.g. querypanel-sdk logic) instead of HTTP
|
|
2139
2324
|
* if (opts.path === '/query' || opts.path === '/v2/query') {
|
|
@@ -2150,11 +2335,11 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
2150
2335
|
* const result = await qp.ask('Top 10 orders', { tenantId: 't1', database: 'db' });
|
|
2151
2336
|
* ```
|
|
2152
2337
|
*/
|
|
2153
|
-
static withCallbacks(
|
|
2338
|
+
static withCallbacks(workspaceId, requestHandler, options) {
|
|
2154
2339
|
const api = new CallbackApiClient(requestHandler, {
|
|
2155
2340
|
defaultTenantId: options?.defaultTenantId
|
|
2156
2341
|
});
|
|
2157
|
-
return new _QueryPanelSdkAPI("", "",
|
|
2342
|
+
return new _QueryPanelSdkAPI("", "", workspaceId, { api });
|
|
2158
2343
|
}
|
|
2159
2344
|
// Database attachment methods
|
|
2160
2345
|
attachClickhouse(name, clientFn, options) {
|
|
@@ -2183,6 +2368,19 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
2183
2368
|
};
|
|
2184
2369
|
this.queryEngine.attachDatabase(name, adapter, metadata);
|
|
2185
2370
|
}
|
|
2371
|
+
attachBigQuery(name, clientFn, options) {
|
|
2372
|
+
const adapter = new BigQueryAdapter(clientFn, options);
|
|
2373
|
+
const metadata = {
|
|
2374
|
+
name,
|
|
2375
|
+
dialect: "bigquery",
|
|
2376
|
+
description: options?.description,
|
|
2377
|
+
tags: options?.tags,
|
|
2378
|
+
tenantFieldName: options?.tenantFieldName,
|
|
2379
|
+
tenantFieldType: options?.tenantFieldType ?? "String",
|
|
2380
|
+
enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
|
|
2381
|
+
};
|
|
2382
|
+
this.queryEngine.attachDatabase(name, adapter, metadata);
|
|
2383
|
+
}
|
|
2186
2384
|
attachDatabase(name, adapter) {
|
|
2187
2385
|
const metadata = {
|
|
2188
2386
|
name,
|
|
@@ -3043,6 +3241,7 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
3043
3241
|
}
|
|
3044
3242
|
};
|
|
3045
3243
|
export {
|
|
3244
|
+
BigQueryAdapter,
|
|
3046
3245
|
CallbackApiClient,
|
|
3047
3246
|
ClickHouseAdapter,
|
|
3048
3247
|
PostgresAdapter,
|