@querypanel/node-sdk 1.0.41 → 1.0.42
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 +16 -8
- package/dist/index.cjs +21 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/package.json +71 -71
package/README.md
CHANGED
|
@@ -42,18 +42,26 @@ const createPostgresClient = () => async (sql: string, params?: unknown[]) => {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
// Attach PostgreSQL database using the SDK's PostgresAdapter
|
|
46
|
+
// The SDK will automatically handle tenant isolation when tenantFieldName is provided
|
|
47
|
+
qp.attachPostgres(
|
|
48
|
+
"pg_demo", // a uniq identifier for QueryPanel
|
|
49
|
+
createPostgresClientFn(),
|
|
50
|
+
{
|
|
51
|
+
database: "pg_demo", // database name
|
|
52
|
+
description: "PostgreSQL demo database", // some description that QueryPanel can use
|
|
53
|
+
tenantFieldName: "tenant_id", // SDK will automatically filter by tenant_id
|
|
54
|
+
enforceTenantIsolation: true, // Ensures all queries include tenant_id filter
|
|
55
|
+
allowedTables: ["orders"], // Only sync 'orders' table - 'users' will be excluded
|
|
56
|
+
});
|
|
49
57
|
|
|
50
58
|
qp.attachClickhouse(
|
|
51
|
-
"clicks",
|
|
59
|
+
"clicks", // uniq identifier for QueryPanel
|
|
52
60
|
(params) => clickhouse.query(params),
|
|
53
61
|
{
|
|
54
|
-
database: "analytics",
|
|
55
|
-
tenantFieldName: "customer_id",
|
|
56
|
-
tenantFieldType: "String",
|
|
62
|
+
database: "analytics", // database name
|
|
63
|
+
tenantFieldName: "customer_id", // SDK will automatically filter by tenant_id
|
|
64
|
+
tenantFieldType: "String", // SDK will use it in the clickhouse query as {customer_id::String}
|
|
57
65
|
},
|
|
58
66
|
);
|
|
59
67
|
|
package/dist/index.cjs
CHANGED
|
@@ -348,8 +348,9 @@ var PostgresAdapter = class {
|
|
|
348
348
|
const allowedSet = new Set(
|
|
349
349
|
this.allowedTables.map((t) => tableKey(t.schema, t.table))
|
|
350
350
|
);
|
|
351
|
+
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*/)");
|
|
351
352
|
const tablePattern = /(?:FROM|JOIN)\s+(?:ONLY\s+)?(?:([a-zA-Z_][a-zA-Z0-9_]*)\.)?(["']?[a-zA-Z_][a-zA-Z0-9_]*["']?)/gi;
|
|
352
|
-
const matches =
|
|
353
|
+
const matches = neutralizedSql.matchAll(tablePattern);
|
|
353
354
|
for (const match of matches) {
|
|
354
355
|
const schema = match[1] ?? this.defaultSchema;
|
|
355
356
|
const table = match[2]?.replace(/['"]/g, "");
|
|
@@ -1174,13 +1175,26 @@ async function ask(client, queryEngine, question, options, signal) {
|
|
|
1174
1175
|
let previousSql = options.previousSql;
|
|
1175
1176
|
while (attempt <= maxRetry) {
|
|
1176
1177
|
console.log({ lastError, previousSql });
|
|
1178
|
+
const databaseName = options.database ?? queryEngine.getDefaultDatabase();
|
|
1179
|
+
const metadata = databaseName ? queryEngine.getDatabaseMetadata(databaseName) : void 0;
|
|
1180
|
+
let tenantSettings;
|
|
1181
|
+
if (metadata?.tenantFieldName) {
|
|
1182
|
+
tenantSettings = {
|
|
1183
|
+
tenantFieldName: metadata.tenantFieldName,
|
|
1184
|
+
tenantFieldType: metadata.tenantFieldType,
|
|
1185
|
+
enforceTenantIsolation: metadata.enforceTenantIsolation
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1177
1188
|
const queryResponse = await client.post(
|
|
1178
1189
|
"/query",
|
|
1179
1190
|
{
|
|
1180
1191
|
question,
|
|
1181
1192
|
...lastError ? { last_error: lastError } : {},
|
|
1182
1193
|
...previousSql ? { previous_sql: previousSql } : {},
|
|
1183
|
-
...options.maxRetry ? { max_retry: options.maxRetry } : {}
|
|
1194
|
+
...options.maxRetry ? { max_retry: options.maxRetry } : {},
|
|
1195
|
+
...tenantSettings ? { tenant_settings: tenantSettings } : {},
|
|
1196
|
+
...databaseName ? { database: databaseName } : {},
|
|
1197
|
+
...metadata?.dialect ? { dialect: metadata.dialect } : {}
|
|
1184
1198
|
},
|
|
1185
1199
|
tenantId,
|
|
1186
1200
|
options.userId,
|
|
@@ -1188,8 +1202,8 @@ async function ask(client, queryEngine, question, options, signal) {
|
|
|
1188
1202
|
signal,
|
|
1189
1203
|
sessionId
|
|
1190
1204
|
);
|
|
1191
|
-
const
|
|
1192
|
-
if (!
|
|
1205
|
+
const dbName = queryResponse.database ?? options.database ?? queryEngine.getDefaultDatabase();
|
|
1206
|
+
if (!dbName) {
|
|
1193
1207
|
throw new Error(
|
|
1194
1208
|
"No database attached. Call attachPostgres/attachClickhouse first."
|
|
1195
1209
|
);
|
|
@@ -1200,7 +1214,7 @@ async function ask(client, queryEngine, question, options, signal) {
|
|
|
1200
1214
|
const execution = await queryEngine.validateAndExecute(
|
|
1201
1215
|
queryResponse.sql,
|
|
1202
1216
|
paramValues,
|
|
1203
|
-
|
|
1217
|
+
dbName,
|
|
1204
1218
|
tenantId
|
|
1205
1219
|
);
|
|
1206
1220
|
const rows = execution.rows ?? [];
|
|
@@ -1273,7 +1287,7 @@ async function ask(client, queryEngine, question, options, signal) {
|
|
|
1273
1287
|
chart,
|
|
1274
1288
|
context: queryResponse.context,
|
|
1275
1289
|
attempts: attempt + 1,
|
|
1276
|
-
target_db:
|
|
1290
|
+
target_db: dbName
|
|
1277
1291
|
};
|
|
1278
1292
|
} catch (error) {
|
|
1279
1293
|
attempt++;
|
|
@@ -1375,6 +1389,7 @@ var QueryPanelSdkAPI = class {
|
|
|
1375
1389
|
description: options?.description,
|
|
1376
1390
|
tags: options?.tags,
|
|
1377
1391
|
tenantFieldName: options?.tenantFieldName,
|
|
1392
|
+
tenantFieldType: options?.tenantFieldType ?? "String",
|
|
1378
1393
|
enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
|
|
1379
1394
|
};
|
|
1380
1395
|
this.queryEngine.attachDatabase(name, adapter, metadata);
|