@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.cjs
CHANGED
|
@@ -1455,21 +1455,39 @@ function anonymizeResults(rows) {
|
|
|
1455
1455
|
}
|
|
1456
1456
|
|
|
1457
1457
|
// src/routes/modify.ts
|
|
1458
|
-
function buildModifiedQuestion(originalQuestion, modifications) {
|
|
1458
|
+
function buildModifiedQuestion(originalQuestion, modifications, pipeline) {
|
|
1459
1459
|
const hints = [];
|
|
1460
1460
|
if (modifications.timeGranularity) {
|
|
1461
1461
|
hints.push(`group results by ${modifications.timeGranularity}`);
|
|
1462
1462
|
}
|
|
1463
1463
|
if (modifications.dateRange) {
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1464
|
+
if (pipeline === "v2") {
|
|
1465
|
+
const from = normalizeDateInput(modifications.dateRange.from);
|
|
1466
|
+
const to = normalizeDateInput(modifications.dateRange.to);
|
|
1467
|
+
if (from && to) {
|
|
1468
|
+
hints.push(
|
|
1469
|
+
`replace any existing date filters with exact date range from ${from} to ${to} (inclusive, do not add extra days)`
|
|
1470
|
+
);
|
|
1471
|
+
} else if (from) {
|
|
1472
|
+
hints.push(
|
|
1473
|
+
`replace any existing date filters with exact start date ${from} (do not shift this date)`
|
|
1474
|
+
);
|
|
1475
|
+
} else if (to) {
|
|
1476
|
+
hints.push(
|
|
1477
|
+
`replace any existing date filters with exact end date ${to} (inclusive, do not add extra days)`
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
} else {
|
|
1481
|
+
const parts = [];
|
|
1482
|
+
if (modifications.dateRange.from) {
|
|
1483
|
+
parts.push(`from ${modifications.dateRange.from}`);
|
|
1484
|
+
}
|
|
1485
|
+
if (modifications.dateRange.to) {
|
|
1486
|
+
parts.push(`to ${modifications.dateRange.to}`);
|
|
1487
|
+
}
|
|
1488
|
+
if (parts.length > 0) {
|
|
1489
|
+
hints.push(`filter date range ${parts.join(" ")}`);
|
|
1490
|
+
}
|
|
1473
1491
|
}
|
|
1474
1492
|
}
|
|
1475
1493
|
if (modifications.additionalInstructions) {
|
|
@@ -1480,6 +1498,67 @@ function buildModifiedQuestion(originalQuestion, modifications) {
|
|
|
1480
1498
|
}
|
|
1481
1499
|
return `${originalQuestion} (${hints.join(", ")})`;
|
|
1482
1500
|
}
|
|
1501
|
+
var START_PARAM_KEY_REGEX = /(^|_)(start|from)(_|$)/i;
|
|
1502
|
+
var END_PARAM_KEY_REGEX = /(^|_)(end|to)(_|$)/i;
|
|
1503
|
+
var ISO_DATETIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z?$/;
|
|
1504
|
+
var SQL_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
1505
|
+
var SQL_DATETIME_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
|
1506
|
+
function normalizeDateInput(value) {
|
|
1507
|
+
if (!value) return void 0;
|
|
1508
|
+
const trimmed = value.trim();
|
|
1509
|
+
if (!trimmed) return void 0;
|
|
1510
|
+
if (ISO_DATETIME_RE.test(trimmed)) {
|
|
1511
|
+
return trimmed.replace("T", " ").replace(/\.\d+Z?$/, "").replace(/Z$/, "");
|
|
1512
|
+
}
|
|
1513
|
+
return trimmed;
|
|
1514
|
+
}
|
|
1515
|
+
function keyLooksLikeDateBoundary(key, boundary) {
|
|
1516
|
+
return boundary === "start" ? START_PARAM_KEY_REGEX.test(key) : END_PARAM_KEY_REGEX.test(key);
|
|
1517
|
+
}
|
|
1518
|
+
function hasTimeComponent(value) {
|
|
1519
|
+
return typeof value === "string" && /\d{2}:\d{2}:\d{2}/.test(value);
|
|
1520
|
+
}
|
|
1521
|
+
function formatDateOverride(dateValue, boundary, existingValue) {
|
|
1522
|
+
if (SQL_DATE_RE.test(dateValue) && !hasTimeComponent(existingValue)) {
|
|
1523
|
+
return dateValue;
|
|
1524
|
+
}
|
|
1525
|
+
if (SQL_DATE_RE.test(dateValue)) {
|
|
1526
|
+
return `${dateValue} ${boundary === "start" ? "00:00:00" : "23:59:59"}`;
|
|
1527
|
+
}
|
|
1528
|
+
if (SQL_DATETIME_RE.test(dateValue)) {
|
|
1529
|
+
return dateValue;
|
|
1530
|
+
}
|
|
1531
|
+
return dateValue;
|
|
1532
|
+
}
|
|
1533
|
+
function normalizeGeneratedParamKey(param, index) {
|
|
1534
|
+
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);
|
|
1535
|
+
return nameCandidate.replace(/[{}]/g, "").replace(/(.+):.*$/, "$1").replace(/^[:$]/, "").trim();
|
|
1536
|
+
}
|
|
1537
|
+
function applyDateRangeOverrides(dateRange, params, paramMetadata) {
|
|
1538
|
+
if (!dateRange) return;
|
|
1539
|
+
const from = normalizeDateInput(dateRange.from);
|
|
1540
|
+
const to = normalizeDateInput(dateRange.to);
|
|
1541
|
+
if (!from && !to) return;
|
|
1542
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1543
|
+
if (from && keyLooksLikeDateBoundary(key, "start")) {
|
|
1544
|
+
params[key] = formatDateOverride(from, "start", value);
|
|
1545
|
+
}
|
|
1546
|
+
if (to && keyLooksLikeDateBoundary(key, "end")) {
|
|
1547
|
+
params[key] = formatDateOverride(to, "end", value);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
for (let i = 0; i < paramMetadata.length; i++) {
|
|
1551
|
+
const param = paramMetadata[i];
|
|
1552
|
+
if (!param) continue;
|
|
1553
|
+
const key = normalizeGeneratedParamKey(param, i);
|
|
1554
|
+
if (from && keyLooksLikeDateBoundary(key, "start")) {
|
|
1555
|
+
param.value = formatDateOverride(from, "start", param.value);
|
|
1556
|
+
}
|
|
1557
|
+
if (to && keyLooksLikeDateBoundary(key, "end")) {
|
|
1558
|
+
param.value = formatDateOverride(to, "end", param.value);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1483
1562
|
function buildVizHints(modifications) {
|
|
1484
1563
|
const hints = {};
|
|
1485
1564
|
if (modifications.kind) {
|
|
@@ -1512,6 +1591,9 @@ function stripVizSpecOnlyHints(hints) {
|
|
|
1512
1591
|
const { kind: _kind, ...rest } = hints;
|
|
1513
1592
|
return rest;
|
|
1514
1593
|
}
|
|
1594
|
+
function isDateRangeOnly(mods) {
|
|
1595
|
+
return !!mods.dateRange && !mods.timeGranularity && !mods.additionalInstructions && !mods.customSql;
|
|
1596
|
+
}
|
|
1515
1597
|
function resolveTenantId5(client, tenantId) {
|
|
1516
1598
|
const resolved = tenantId ?? client.getDefaultTenantId();
|
|
1517
1599
|
if (!resolved) {
|
|
@@ -1535,6 +1617,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1535
1617
|
let rationale;
|
|
1536
1618
|
let queryId;
|
|
1537
1619
|
let sqlChanged = false;
|
|
1620
|
+
let finalQuestion = input.question;
|
|
1538
1621
|
const databaseName = input.database ?? queryEngine.getDefaultDatabase();
|
|
1539
1622
|
if (!databaseName) {
|
|
1540
1623
|
throw new Error(
|
|
@@ -1555,11 +1638,87 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1555
1638
|
finalParams = {};
|
|
1556
1639
|
paramMetadata = [];
|
|
1557
1640
|
sqlChanged = true;
|
|
1641
|
+
} else if (hasSqlMods && options?.pipeline === "v2" && isDateRangeOnly(input.sqlModifications)) {
|
|
1642
|
+
let usedFastPath = false;
|
|
1643
|
+
try {
|
|
1644
|
+
const rewriteResponse = await client.post(
|
|
1645
|
+
"/v2/rewrite-datefilter",
|
|
1646
|
+
{
|
|
1647
|
+
previous_sql: input.sql,
|
|
1648
|
+
previous_params: input.params ? Object.entries(input.params).map(([name, value]) => ({
|
|
1649
|
+
name,
|
|
1650
|
+
value
|
|
1651
|
+
})) : [],
|
|
1652
|
+
date_range: input.sqlModifications.dateRange,
|
|
1653
|
+
question: input.question,
|
|
1654
|
+
...tenantSettings ? { tenant_settings: tenantSettings } : {},
|
|
1655
|
+
...databaseName ? { database: databaseName } : {},
|
|
1656
|
+
...metadata?.dialect ? { dialect: metadata.dialect } : {}
|
|
1657
|
+
},
|
|
1658
|
+
tenantId,
|
|
1659
|
+
options?.userId,
|
|
1660
|
+
options?.scopes,
|
|
1661
|
+
signal,
|
|
1662
|
+
sessionId
|
|
1663
|
+
);
|
|
1664
|
+
finalSql = rewriteResponse.sql;
|
|
1665
|
+
paramMetadata = Array.isArray(rewriteResponse.params) ? rewriteResponse.params : [];
|
|
1666
|
+
finalParams = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1667
|
+
applyDateRangeOverrides(
|
|
1668
|
+
input.sqlModifications?.dateRange,
|
|
1669
|
+
finalParams,
|
|
1670
|
+
paramMetadata
|
|
1671
|
+
);
|
|
1672
|
+
rationale = rewriteResponse.rationale;
|
|
1673
|
+
queryId = rewriteResponse.queryId;
|
|
1674
|
+
sqlChanged = finalSql !== input.sql;
|
|
1675
|
+
usedFastPath = true;
|
|
1676
|
+
} catch {
|
|
1677
|
+
}
|
|
1678
|
+
if (!usedFastPath) {
|
|
1679
|
+
const modifiedQuestion = buildModifiedQuestion(
|
|
1680
|
+
input.question,
|
|
1681
|
+
input.sqlModifications,
|
|
1682
|
+
"v2"
|
|
1683
|
+
);
|
|
1684
|
+
finalQuestion = modifiedQuestion;
|
|
1685
|
+
const queryResponse = await client.post(
|
|
1686
|
+
queryEndpoint,
|
|
1687
|
+
{
|
|
1688
|
+
question: modifiedQuestion,
|
|
1689
|
+
previous_sql: input.sql,
|
|
1690
|
+
...options?.maxRetry ? { max_retry: options.maxRetry } : {},
|
|
1691
|
+
...tenantSettings ? { tenant_settings: tenantSettings } : {},
|
|
1692
|
+
...databaseName ? { database: databaseName } : {},
|
|
1693
|
+
...metadata?.dialect ? { dialect: metadata.dialect } : {}
|
|
1694
|
+
},
|
|
1695
|
+
tenantId,
|
|
1696
|
+
options?.userId,
|
|
1697
|
+
options?.scopes,
|
|
1698
|
+
signal,
|
|
1699
|
+
sessionId
|
|
1700
|
+
);
|
|
1701
|
+
finalSql = queryResponse.sql;
|
|
1702
|
+
paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
|
|
1703
|
+
finalParams = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1704
|
+
applyDateRangeOverrides(
|
|
1705
|
+
input.sqlModifications?.dateRange,
|
|
1706
|
+
finalParams,
|
|
1707
|
+
paramMetadata
|
|
1708
|
+
);
|
|
1709
|
+
rationale = queryResponse.rationale;
|
|
1710
|
+
queryId = queryResponse.queryId;
|
|
1711
|
+
sqlChanged = finalSql !== input.sql;
|
|
1712
|
+
}
|
|
1558
1713
|
} else if (hasSqlMods && !hasCustomSql) {
|
|
1559
1714
|
const modifiedQuestion = buildModifiedQuestion(
|
|
1560
1715
|
input.question,
|
|
1561
|
-
input.sqlModifications
|
|
1716
|
+
input.sqlModifications,
|
|
1717
|
+
options?.pipeline
|
|
1562
1718
|
);
|
|
1719
|
+
if (options?.pipeline === "v2") {
|
|
1720
|
+
finalQuestion = modifiedQuestion;
|
|
1721
|
+
}
|
|
1563
1722
|
const queryResponse = await client.post(
|
|
1564
1723
|
queryEndpoint,
|
|
1565
1724
|
{
|
|
@@ -1579,6 +1738,13 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1579
1738
|
finalSql = queryResponse.sql;
|
|
1580
1739
|
paramMetadata = Array.isArray(queryResponse.params) ? queryResponse.params : [];
|
|
1581
1740
|
finalParams = queryEngine.mapGeneratedParams(paramMetadata);
|
|
1741
|
+
if (options?.pipeline === "v2") {
|
|
1742
|
+
applyDateRangeOverrides(
|
|
1743
|
+
input.sqlModifications?.dateRange,
|
|
1744
|
+
finalParams,
|
|
1745
|
+
paramMetadata
|
|
1746
|
+
);
|
|
1747
|
+
}
|
|
1582
1748
|
rationale = queryResponse.rationale;
|
|
1583
1749
|
queryId = queryResponse.queryId;
|
|
1584
1750
|
sqlChanged = finalSql !== input.sql;
|
|
@@ -1601,7 +1767,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1601
1767
|
const vizspecResponse = await client.post(
|
|
1602
1768
|
"/vizspec",
|
|
1603
1769
|
{
|
|
1604
|
-
question:
|
|
1770
|
+
question: finalQuestion,
|
|
1605
1771
|
sql: finalSql,
|
|
1606
1772
|
rationale,
|
|
1607
1773
|
fields: execution.fields,
|
|
@@ -1626,7 +1792,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
1626
1792
|
const chartResponse = await client.post(
|
|
1627
1793
|
"/chart",
|
|
1628
1794
|
{
|
|
1629
|
-
question:
|
|
1795
|
+
question: finalQuestion,
|
|
1630
1796
|
sql: finalSql,
|
|
1631
1797
|
rationale,
|
|
1632
1798
|
fields: execution.fields,
|