@querypanel/node-sdk 1.2.10 → 1.3.0-beta.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/dist/index.cjs +132 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -7
- package/dist/index.d.ts +14 -7
- package/dist/index.js +129 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,9 @@ __export(index_exports, {
|
|
|
38
38
|
QueryErrorCode: () => QueryErrorCode,
|
|
39
39
|
QueryPanelSdkAPI: () => QueryPanelSdkAPI,
|
|
40
40
|
QueryPipelineError: () => QueryPipelineError,
|
|
41
|
-
anonymizeResults: () => anonymizeResults
|
|
41
|
+
anonymizeResults: () => anonymizeResults,
|
|
42
|
+
mapGeneratedParams: () => mapGeneratedParams,
|
|
43
|
+
normalizeSqlParamsInput: () => normalizeSqlParamsInput
|
|
42
44
|
});
|
|
43
45
|
module.exports = __toCommonJS(index_exports);
|
|
44
46
|
|
|
@@ -497,6 +499,37 @@ function toNumber(value) {
|
|
|
497
499
|
}
|
|
498
500
|
|
|
499
501
|
// src/adapters/postgres.ts
|
|
502
|
+
function maxPostgresPlaceholderIndex(sql) {
|
|
503
|
+
let max = 0;
|
|
504
|
+
for (const match of sql.matchAll(/\$(\d+)\b/g)) {
|
|
505
|
+
const index = Number.parseInt(match[1], 10);
|
|
506
|
+
if (Number.isFinite(index) && index > max) {
|
|
507
|
+
max = index;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return max;
|
|
511
|
+
}
|
|
512
|
+
function filterParamsForPostgresSql(sql, params) {
|
|
513
|
+
if (!params || Object.keys(params).length === 0) {
|
|
514
|
+
return void 0;
|
|
515
|
+
}
|
|
516
|
+
const placeholderCount = maxPostgresPlaceholderIndex(sql);
|
|
517
|
+
if (placeholderCount === 0) {
|
|
518
|
+
return void 0;
|
|
519
|
+
}
|
|
520
|
+
const hasNumericKeys = Object.keys(params).some((key) => /^\d+$/.test(key));
|
|
521
|
+
if (hasNumericKeys) {
|
|
522
|
+
const filtered = {};
|
|
523
|
+
for (let index = 1; index <= placeholderCount; index += 1) {
|
|
524
|
+
const key = String(index);
|
|
525
|
+
if (key in params) {
|
|
526
|
+
filtered[key] = params[key];
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return Object.keys(filtered).length > 0 ? filtered : void 0;
|
|
530
|
+
}
|
|
531
|
+
return params;
|
|
532
|
+
}
|
|
500
533
|
var PostgresAdapter = class {
|
|
501
534
|
constructor(clientFn, options = {}) {
|
|
502
535
|
this.clientFn = clientFn;
|
|
@@ -514,9 +547,10 @@ var PostgresAdapter = class {
|
|
|
514
547
|
if (this.allowedTables) {
|
|
515
548
|
this.validateQueryTables(sql);
|
|
516
549
|
}
|
|
550
|
+
const boundParams = filterParamsForPostgresSql(sql, params);
|
|
517
551
|
let paramArray;
|
|
518
|
-
if (
|
|
519
|
-
paramArray = this.convertNamedToPositionalParams(
|
|
552
|
+
if (boundParams) {
|
|
553
|
+
paramArray = this.convertNamedToPositionalParams(sql, boundParams);
|
|
520
554
|
}
|
|
521
555
|
const result = await this.clientFn(sql, paramArray);
|
|
522
556
|
const fields = result.fields.map((f) => f.name);
|
|
@@ -546,36 +580,43 @@ var PostgresAdapter = class {
|
|
|
546
580
|
}
|
|
547
581
|
}
|
|
548
582
|
/**
|
|
549
|
-
* Convert params to positional array for PostgreSQL.
|
|
550
|
-
*
|
|
551
|
-
* When the record has numeric keys ("1", "2", "3") — e.g. from mapGeneratedParams —
|
|
552
|
-
* use only those in order so placeholder order matches SQL. Otherwise fall back to
|
|
553
|
-
* named keys in alphabetical order for backward compatibility.
|
|
583
|
+
* Convert params to positional array for PostgreSQL ($1, $2, …).
|
|
584
|
+
* Values must align with v2 generation order via numeric keys from mapGeneratedParams.
|
|
554
585
|
*/
|
|
555
|
-
convertNamedToPositionalParams(params) {
|
|
556
|
-
const
|
|
557
|
-
if (
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
586
|
+
convertNamedToPositionalParams(sql, params) {
|
|
587
|
+
const placeholderCount = maxPostgresPlaceholderIndex(sql);
|
|
588
|
+
if (placeholderCount === 0) {
|
|
589
|
+
return [];
|
|
590
|
+
}
|
|
591
|
+
const positionalParams = [];
|
|
592
|
+
for (let index = 1; index <= placeholderCount; index += 1) {
|
|
593
|
+
const key = String(index);
|
|
594
|
+
let val = params[key];
|
|
595
|
+
if (val === void 0 && placeholderCount === 1) {
|
|
596
|
+
const namedKeys = Object.keys(params).filter((k) => !/^\d+$/.test(k));
|
|
597
|
+
if (namedKeys.length === 1) {
|
|
598
|
+
val = params[namedKeys[0]];
|
|
567
599
|
}
|
|
568
|
-
positionalParams.push(val);
|
|
569
600
|
}
|
|
570
|
-
|
|
601
|
+
if (val === void 0) {
|
|
602
|
+
throw new Error(`Missing value for PostgreSQL parameter $${index}`);
|
|
603
|
+
}
|
|
604
|
+
if (typeof val === "string") {
|
|
605
|
+
const match = val.match(/^<([a-zA-Z0-9_]+)>$/);
|
|
606
|
+
const namedKey = match?.[1];
|
|
607
|
+
if (namedKey && namedKey in params) {
|
|
608
|
+
val = params[namedKey];
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
positionalParams.push(val);
|
|
571
612
|
}
|
|
572
|
-
|
|
573
|
-
return namedKeys.map((key) => params[key]);
|
|
613
|
+
return positionalParams;
|
|
574
614
|
}
|
|
575
615
|
async validate(sql, params) {
|
|
616
|
+
const boundParams = filterParamsForPostgresSql(sql, params);
|
|
576
617
|
let paramArray;
|
|
577
|
-
if (
|
|
578
|
-
paramArray = this.convertNamedToPositionalParams(
|
|
618
|
+
if (boundParams) {
|
|
619
|
+
paramArray = this.convertNamedToPositionalParams(sql, boundParams);
|
|
579
620
|
}
|
|
580
621
|
await this.clientFn(`EXPLAIN ${sql}`, paramArray);
|
|
581
622
|
}
|
|
@@ -1218,6 +1259,45 @@ var CallbackApiClient = class {
|
|
|
1218
1259
|
}
|
|
1219
1260
|
};
|
|
1220
1261
|
|
|
1262
|
+
// src/core/map-generated-params.ts
|
|
1263
|
+
function mapGeneratedParams(params) {
|
|
1264
|
+
const record = {};
|
|
1265
|
+
params.forEach((param, index) => {
|
|
1266
|
+
const value = param.value;
|
|
1267
|
+
if (value === void 0) {
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
record[String(index + 1)] = value;
|
|
1271
|
+
const nameCandidate = typeof param.name === "string" && param.name.trim() || typeof param.placeholder === "string" && param.placeholder.trim() || typeof param.position === "number" && String(param.position) || String(index + 1);
|
|
1272
|
+
const key = nameCandidate.replace(/[{}:$]/g, "").trim();
|
|
1273
|
+
record[key] = value;
|
|
1274
|
+
});
|
|
1275
|
+
return record;
|
|
1276
|
+
}
|
|
1277
|
+
function normalizeSqlParamsInput(params) {
|
|
1278
|
+
if (params == null) {
|
|
1279
|
+
return {};
|
|
1280
|
+
}
|
|
1281
|
+
if (Array.isArray(params)) {
|
|
1282
|
+
if (params.length === 0) {
|
|
1283
|
+
return {};
|
|
1284
|
+
}
|
|
1285
|
+
const first = params[0];
|
|
1286
|
+
if (first && typeof first === "object" && "value" in first) {
|
|
1287
|
+
return mapGeneratedParams(params);
|
|
1288
|
+
}
|
|
1289
|
+
const positional = {};
|
|
1290
|
+
params.forEach((value, index) => {
|
|
1291
|
+
positional[String(index + 1)] = value;
|
|
1292
|
+
});
|
|
1293
|
+
return positional;
|
|
1294
|
+
}
|
|
1295
|
+
if (typeof params === "object") {
|
|
1296
|
+
return params;
|
|
1297
|
+
}
|
|
1298
|
+
return {};
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1221
1301
|
// src/core/query-engine.ts
|
|
1222
1302
|
var QueryEngine = class {
|
|
1223
1303
|
constructor() {
|
|
@@ -1288,18 +1368,7 @@ var QueryEngine = class {
|
|
|
1288
1368
|
* - Named keys remain for tenant isolation / other lookups.
|
|
1289
1369
|
*/
|
|
1290
1370
|
mapGeneratedParams(params) {
|
|
1291
|
-
|
|
1292
|
-
params.forEach((param, index) => {
|
|
1293
|
-
const value = param.value;
|
|
1294
|
-
if (value === void 0) {
|
|
1295
|
-
return;
|
|
1296
|
-
}
|
|
1297
|
-
record[String(index + 1)] = value;
|
|
1298
|
-
const nameCandidate = typeof param.name === "string" && param.name.trim() || typeof param.placeholder === "string" && param.placeholder.trim() || typeof param.position === "number" && String(param.position) || String(index + 1);
|
|
1299
|
-
const key = nameCandidate.replace(/[{}:$]/g, "").trim();
|
|
1300
|
-
record[key] = value;
|
|
1301
|
-
});
|
|
1302
|
-
return record;
|
|
1371
|
+
return mapGeneratedParams(params);
|
|
1303
1372
|
}
|
|
1304
1373
|
ensureTenantIsolation(sql, params, metadata, tenantId) {
|
|
1305
1374
|
if (!metadata.tenantFieldName || metadata.enforceTenantIsolation === false) {
|
|
@@ -1319,8 +1388,10 @@ var QueryEngine = class {
|
|
|
1319
1388
|
params[tenantField] = tenantId;
|
|
1320
1389
|
tenantPredicate = `${tenantField} = @${tenantField}`;
|
|
1321
1390
|
} else {
|
|
1322
|
-
const
|
|
1323
|
-
|
|
1391
|
+
const paramIndex = this.nextPostgresPlaceholderIndex(sql, params);
|
|
1392
|
+
params[String(paramIndex)] = tenantId;
|
|
1393
|
+
params[tenantField] = tenantId;
|
|
1394
|
+
tenantPredicate = `${tenantField} = $${paramIndex}`;
|
|
1324
1395
|
}
|
|
1325
1396
|
if (/\bwhere\b/i.test(sql)) {
|
|
1326
1397
|
return sql.replace(
|
|
@@ -1330,6 +1401,23 @@ var QueryEngine = class {
|
|
|
1330
1401
|
}
|
|
1331
1402
|
return `${sql} WHERE ${tenantPredicate}`;
|
|
1332
1403
|
}
|
|
1404
|
+
nextPostgresPlaceholderIndex(sql, params) {
|
|
1405
|
+
let max = 0;
|
|
1406
|
+
for (const match of sql.matchAll(/\$(\d+)\b/g)) {
|
|
1407
|
+
const index = Number.parseInt(match[1], 10);
|
|
1408
|
+
if (Number.isFinite(index) && index > max) {
|
|
1409
|
+
max = index;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
if (max > 0) {
|
|
1413
|
+
return max + 1;
|
|
1414
|
+
}
|
|
1415
|
+
const numericKeys = Object.keys(params).filter((key) => /^\d+$/.test(key)).map((key) => Number.parseInt(key, 10)).filter((index) => Number.isFinite(index));
|
|
1416
|
+
if (numericKeys.length > 0) {
|
|
1417
|
+
return Math.max(...numericKeys) + 1;
|
|
1418
|
+
}
|
|
1419
|
+
return 1;
|
|
1420
|
+
}
|
|
1333
1421
|
};
|
|
1334
1422
|
|
|
1335
1423
|
// src/routes/charts.ts
|
|
@@ -1864,6 +1952,7 @@ function resolveTenantId4(client, tenantId) {
|
|
|
1864
1952
|
function buildSchemaRequest(databaseName, adapter, introspection, metadata) {
|
|
1865
1953
|
const dialect = adapter.getDialect();
|
|
1866
1954
|
const tables = introspection.tables.map((table) => ({
|
|
1955
|
+
schema_name: table.schema,
|
|
1867
1956
|
table_name: table.name,
|
|
1868
1957
|
description: table.comment ?? `Table ${table.name}`,
|
|
1869
1958
|
columns: table.columns.map((column) => ({
|
|
@@ -3540,6 +3629,8 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
3540
3629
|
QueryErrorCode,
|
|
3541
3630
|
QueryPanelSdkAPI,
|
|
3542
3631
|
QueryPipelineError,
|
|
3543
|
-
anonymizeResults
|
|
3632
|
+
anonymizeResults,
|
|
3633
|
+
mapGeneratedParams,
|
|
3634
|
+
normalizeSqlParamsInput
|
|
3544
3635
|
});
|
|
3545
3636
|
//# sourceMappingURL=index.cjs.map
|