@querypanel/node-sdk 1.0.52 → 1.0.53
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 +179 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +179 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1414,21 +1414,39 @@ function anonymizeResults(rows) {
|
|
|
1414
1414
|
}
|
|
1415
1415
|
|
|
1416
1416
|
// src/routes/modify.ts
|
|
1417
|
-
function buildModifiedQuestion(originalQuestion, modifications) {
|
|
1417
|
+
function buildModifiedQuestion(originalQuestion, modifications, pipeline) {
|
|
1418
1418
|
const hints = [];
|
|
1419
1419
|
if (modifications.timeGranularity) {
|
|
1420
1420
|
hints.push(`group results by ${modifications.timeGranularity}`);
|
|
1421
1421
|
}
|
|
1422
1422
|
if (modifications.dateRange) {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1423
|
+
if (pipeline === "v2") {
|
|
1424
|
+
const from = normalizeDateInput(modifications.dateRange.from);
|
|
1425
|
+
const to = normalizeDateInput(modifications.dateRange.to);
|
|
1426
|
+
if (from && to) {
|
|
1427
|
+
hints.push(
|
|
1428
|
+
`replace any existing date filters with exact date range from ${from} to ${to} (inclusive, do not add extra days)`
|
|
1429
|
+
);
|
|
1430
|
+
} else if (from) {
|
|
1431
|
+
hints.push(
|
|
1432
|
+
`replace any existing date filters with exact start date ${from} (do not shift this date)`
|
|
1433
|
+
);
|
|
1434
|
+
} else if (to) {
|
|
1435
|
+
hints.push(
|
|
1436
|
+
`replace any existing date filters with exact end date ${to} (inclusive, do not add extra days)`
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
} else {
|
|
1440
|
+
const parts = [];
|
|
1441
|
+
if (modifications.dateRange.from) {
|
|
1442
|
+
parts.push(`from ${modifications.dateRange.from}`);
|
|
1443
|
+
}
|
|
1444
|
+
if (modifications.dateRange.to) {
|
|
1445
|
+
parts.push(`to ${modifications.dateRange.to}`);
|
|
1446
|
+
}
|
|
1447
|
+
if (parts.length > 0) {
|
|
1448
|
+
hints.push(`filter date range ${parts.join(" ")}`);
|
|
1449
|
+
}
|
|
1432
1450
|
}
|
|
1433
1451
|
}
|
|
1434
1452
|
if (modifications.additionalInstructions) {
|
|
@@ -1439,6 +1457,67 @@ function buildModifiedQuestion(originalQuestion, modifications) {
|
|
|
1439
1457
|
}
|
|
1440
1458
|
return `${originalQuestion} (${hints.join(", ")})`;
|
|
1441
1459
|
}
|
|
1460
|
+
var START_PARAM_KEY_REGEX = /(^|_)(start|from)(_|$)/i;
|
|
1461
|
+
var END_PARAM_KEY_REGEX = /(^|_)(end|to)(_|$)/i;
|
|
1462
|
+
var ISO_DATETIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z?$/;
|
|
1463
|
+
var SQL_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
1464
|
+
var SQL_DATETIME_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
|
1465
|
+
function normalizeDateInput(value) {
|
|
1466
|
+
if (!value) return void 0;
|
|
1467
|
+
const trimmed = value.trim();
|
|
1468
|
+
if (!trimmed) return void 0;
|
|
1469
|
+
if (ISO_DATETIME_RE.test(trimmed)) {
|
|
1470
|
+
return trimmed.replace("T", " ").replace(/\.\d+Z?$/, "").replace(/Z$/, "");
|
|
1471
|
+
}
|
|
1472
|
+
return trimmed;
|
|
1473
|
+
}
|
|
1474
|
+
function keyLooksLikeDateBoundary(key, boundary) {
|
|
1475
|
+
return boundary === "start" ? START_PARAM_KEY_REGEX.test(key) : END_PARAM_KEY_REGEX.test(key);
|
|
1476
|
+
}
|
|
1477
|
+
function hasTimeComponent(value) {
|
|
1478
|
+
return typeof value === "string" && /\d{2}:\d{2}:\d{2}/.test(value);
|
|
1479
|
+
}
|
|
1480
|
+
function formatDateOverride(dateValue, boundary, existingValue) {
|
|
1481
|
+
if (SQL_DATE_RE.test(dateValue) && !hasTimeComponent(existingValue)) {
|
|
1482
|
+
return dateValue;
|
|
1483
|
+
}
|
|
1484
|
+
if (SQL_DATE_RE.test(dateValue)) {
|
|
1485
|
+
return `${dateValue} ${boundary === "start" ? "00:00:00" : "23:59:59"}`;
|
|
1486
|
+
}
|
|
1487
|
+
if (SQL_DATETIME_RE.test(dateValue)) {
|
|
1488
|
+
return dateValue;
|
|
1489
|
+
}
|
|
1490
|
+
return dateValue;
|
|
1491
|
+
}
|
|
1492
|
+
function normalizeGeneratedParamKey(param, index) {
|
|
1493
|
+
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);
|
|
1494
|
+
return nameCandidate.replace(/[{}]/g, "").replace(/(.+):.*$/, "$1").replace(/^[:$]/, "").trim();
|
|
1495
|
+
}
|
|
1496
|
+
function applyDateRangeOverrides(dateRange, params, paramMetadata) {
|
|
1497
|
+
if (!dateRange) return;
|
|
1498
|
+
const from = normalizeDateInput(dateRange.from);
|
|
1499
|
+
const to = normalizeDateInput(dateRange.to);
|
|
1500
|
+
if (!from && !to) return;
|
|
1501
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1502
|
+
if (from && keyLooksLikeDateBoundary(key, "start")) {
|
|
1503
|
+
params[key] = formatDateOverride(from, "start", value);
|
|
1504
|
+
}
|
|
1505
|
+
if (to && keyLooksLikeDateBoundary(key, "end")) {
|
|
1506
|
+
params[key] = formatDateOverride(to, "end", value);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
for (let i = 0; i < paramMetadata.length; i++) {
|
|
1510
|
+
const param = paramMetadata[i];
|
|
1511
|
+
if (!param) continue;
|
|
1512
|
+
const key = normalizeGeneratedParamKey(param, i);
|
|
1513
|
+
if (from && keyLooksLikeDateBoundary(key, "start")) {
|
|
1514
|
+
param.value = formatDateOverride(from, "start", param.value);
|
|
1515
|
+
}
|
|
1516
|
+
if (to && keyLooksLikeDateBoundary(key, "end")) {
|
|
1517
|
+
param.value = formatDateOverride(to, "end", param.value);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1442
1521
|
function buildVizHints(modifications) {
|
|
1443
1522
|
const hints = {};
|
|
1444
1523
|
if (modifications.kind) {
|
|
@@ -1471,6 +1550,9 @@ function stripVizSpecOnlyHints(hints) {
|
|
|
1471
1550
|
const { kind: _kind, ...rest } = hints;
|
|
1472
1551
|
return rest;
|
|
1473
1552
|
}
|
|
1553
|
+
function isDateRangeOnly(mods) {
|
|
1554
|
+
return !!mods.dateRange && !mods.timeGranularity && !mods.additionalInstructions && !mods.customSql;
|
|
1555
|
+
}
|
|
1474
1556
|
function resolveTenantId5(client, tenantId) {
|
|
1475
1557
|
const resolved = tenantId ?? client.getDefaultTenantId();
|
|
1476
1558
|
if (!resolved) {
|
|
@@ -1494,6 +1576,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1494
1576
|
let rationale;
|
|
1495
1577
|
let queryId;
|
|
1496
1578
|
let sqlChanged = false;
|
|
1579
|
+
let finalQuestion = input.question;
|
|
1497
1580
|
const databaseName = input.database ?? queryEngine.getDefaultDatabase();
|
|
1498
1581
|
if (!databaseName) {
|
|
1499
1582
|
throw new Error(
|
|
@@ -1514,11 +1597,87 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1514
1597
|
finalParams = {};
|
|
1515
1598
|
paramMetadata = [];
|
|
1516
1599
|
sqlChanged = true;
|
|
1600
|
+
} else if (hasSqlMods && options?.pipeline === "v2" && isDateRangeOnly(input.sqlModifications)) {
|
|
1601
|
+
let usedFastPath = false;
|
|
1602
|
+
try {
|
|
1603
|
+
const rewriteResponse = await client.post(
|
|
1604
|
+
"/v2/rewrite-datefilter",
|
|
1605
|
+
{
|
|
1606
|
+
previous_sql: input.sql,
|
|
1607
|
+
previous_params: input.params ? Object.entries(input.params).map(([name, value]) => ({
|
|
1608
|
+
name,
|
|
1609
|
+
value
|
|
1610
|
+
})) : [],
|
|
1611
|
+
date_range: input.sqlModifications.dateRange,
|
|
1612
|
+
question: input.question,
|
|
1613
|
+
...tenantSettings ? { tenant_settings: tenantSettings } : {},
|
|
1614
|
+
...databaseName ? { database: databaseName } : {},
|
|
1615
|
+
...metadata?.dialect ? { dialect: metadata.dialect } : {}
|
|
1616
|
+
},
|
|
1617
|
+
tenantId,
|
|
1618
|
+
options?.userId,
|
|
1619
|
+
options?.scopes,
|
|
1620
|
+
signal,
|
|
1621
|
+
sessionId
|
|
1622
|
+
);
|
|
1623
|
+
finalSql = rewriteResponse.sql;
|
|
1624
|
+
paramMetadata = Array.isArray(rewriteResponse.params) ? rewriteResponse.params : [];
|
|
1625
|
+
finalParams = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1626
|
+
applyDateRangeOverrides(
|
|
1627
|
+
input.sqlModifications?.dateRange,
|
|
1628
|
+
finalParams,
|
|
1629
|
+
paramMetadata
|
|
1630
|
+
);
|
|
1631
|
+
rationale = rewriteResponse.rationale;
|
|
1632
|
+
queryId = rewriteResponse.queryId;
|
|
1633
|
+
sqlChanged = finalSql !== input.sql;
|
|
1634
|
+
usedFastPath = true;
|
|
1635
|
+
} catch {
|
|
1636
|
+
}
|
|
1637
|
+
if (!usedFastPath) {
|
|
1638
|
+
const modifiedQuestion = buildModifiedQuestion(
|
|
1639
|
+
input.question,
|
|
1640
|
+
input.sqlModifications,
|
|
1641
|
+
"v2"
|
|
1642
|
+
);
|
|
1643
|
+
finalQuestion = modifiedQuestion;
|
|
1644
|
+
const queryResponse = await client.post(
|
|
1645
|
+
queryEndpoint,
|
|
1646
|
+
{
|
|
1647
|
+
question: modifiedQuestion,
|
|
1648
|
+
previous_sql: input.sql,
|
|
1649
|
+
...options?.maxRetry ? { max_retry: options.maxRetry } : {},
|
|
1650
|
+
...tenantSettings ? { tenant_settings: tenantSettings } : {},
|
|
1651
|
+
...databaseName ? { database: databaseName } : {},
|
|
1652
|
+
...metadata?.dialect ? { dialect: metadata.dialect } : {}
|
|
1653
|
+
},
|
|
1654
|
+
tenantId,
|
|
1655
|
+
options?.userId,
|
|
1656
|
+
options?.scopes,
|
|
1657
|
+
signal,
|
|
1658
|
+
sessionId
|
|
1659
|
+
);
|
|
1660
|
+
finalSql = queryResponse.sql;
|
|
1661
|
+
paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
|
|
1662
|
+
finalParams = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1663
|
+
applyDateRangeOverrides(
|
|
1664
|
+
input.sqlModifications?.dateRange,
|
|
1665
|
+
finalParams,
|
|
1666
|
+
paramMetadata
|
|
1667
|
+
);
|
|
1668
|
+
rationale = queryResponse.rationale;
|
|
1669
|
+
queryId = queryResponse.queryId;
|
|
1670
|
+
sqlChanged = finalSql !== input.sql;
|
|
1671
|
+
}
|
|
1517
1672
|
} else if (hasSqlMods && !hasCustomSql) {
|
|
1518
1673
|
const modifiedQuestion = buildModifiedQuestion(
|
|
1519
1674
|
input.question,
|
|
1520
|
-
input.sqlModifications
|
|
1675
|
+
input.sqlModifications,
|
|
1676
|
+
options?.pipeline
|
|
1521
1677
|
);
|
|
1678
|
+
if (options?.pipeline === "v2") {
|
|
1679
|
+
finalQuestion = modifiedQuestion;
|
|
1680
|
+
}
|
|
1522
1681
|
const queryResponse = await client.post(
|
|
1523
1682
|
queryEndpoint,
|
|
1524
1683
|
{
|
|
@@ -1538,6 +1697,13 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1538
1697
|
finalSql = queryResponse.sql;
|
|
1539
1698
|
paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
|
|
1540
1699
|
finalParams = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1700
|
+
if (options?.pipeline === "v2") {
|
|
1701
|
+
applyDateRangeOverrides(
|
|
1702
|
+
input.sqlModifications?.dateRange,
|
|
1703
|
+
finalParams,
|
|
1704
|
+
paramMetadata
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1541
1707
|
rationale = queryResponse.rationale;
|
|
1542
1708
|
queryId = queryResponse.queryId;
|
|
1543
1709
|
sqlChanged = finalSql !== input.sql;
|
|
@@ -1560,7 +1726,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1560
1726
|
const vizspecResponse = await client.post(
|
|
1561
1727
|
"/vizspec",
|
|
1562
1728
|
{
|
|
1563
|
-
question:
|
|
1729
|
+
question: finalQuestion,
|
|
1564
1730
|
sql: finalSql,
|
|
1565
1731
|
rationale,
|
|
1566
1732
|
fields: execution.fields,
|
|
@@ -1585,7 +1751,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1585
1751
|
const chartResponse = await client.post(
|
|
1586
1752
|
"/chart",
|
|
1587
1753
|
{
|
|
1588
|
-
question:
|
|
1754
|
+
question: finalQuestion,
|
|
1589
1755
|
sql: finalSql,
|
|
1590
1756
|
rationale,
|
|
1591
1757
|
fields: execution.fields,
|