@querypanel/node-sdk 1.3.0-beta.2 → 1.3.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 +29 -1
- package/dist/index.cjs +56 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -4
- package/dist/index.d.ts +28 -4
- package/dist/index.js +56 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -286,9 +286,37 @@ const { data, missingIds } = await qp.getChartsByIds(
|
|
|
286
286
|
Saved charts now include the original `prompt` so you can show the question
|
|
287
287
|
alongside chart history or reuse it in follow-up workflows.
|
|
288
288
|
|
|
289
|
+
## Referencing Queries by `queryId` (recommended)
|
|
290
|
+
|
|
291
|
+
`ask()` and `modifyChart()` return a server-issued `queryId`. The server stores the generated SQL and bind params for that id, scoped to the authenticated workspace and tenant. **Pass the id instead of SQL** so your clients never send executable SQL or bind params:
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
const response = await qp.ask("revenue by country", { tenantId, database: "analytics" });
|
|
295
|
+
|
|
296
|
+
// Modify: SQL and params are loaded from the server, client `sql` / `params` are ignored
|
|
297
|
+
const modified = await qp.modifyChart(
|
|
298
|
+
{ queryId: response.queryId, question: "revenue by country", database: "analytics",
|
|
299
|
+
vizModifications: { chartType: "bar" } },
|
|
300
|
+
{ tenantId },
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
// Run a stored query (e.g. in a dashboard)
|
|
304
|
+
await qp.runSqlForDashboard({ queryId: response.queryId, database: "analytics" }, { tenantId });
|
|
305
|
+
|
|
306
|
+
// Save a chart: the server stores the SQL and params it holds for `query_id`
|
|
307
|
+
await qp.createChart({ title: "Revenue", query_id: modified.queryId, vega_lite_spec: spec }, { tenantId });
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
- When `queryId` / `query_id` is present it **takes priority**: any `sql` / `sql_params` you also send is ignored.
|
|
311
|
+
- An id that belongs to another tenant, or does not exist, is rejected (`404`).
|
|
312
|
+
- `sql` is still accepted when no id is sent, for backward compatibility. Charts saved without a `query_id` (for example older charts) keep using their stored SQL.
|
|
313
|
+
- `modifyChart()` returns the input `queryId` when only visualization changes, and a new `queryId` when SQL is regenerated. Custom SQL (`customSql`) has no id.
|
|
314
|
+
- Generation fails if the server cannot record the query, so a successful `ask()` always returns a `queryId`.
|
|
315
|
+
- Requires an API that supports `GET /v2/queries/:id`; upgrade the API before the SDK.
|
|
316
|
+
|
|
289
317
|
## Modifying Charts
|
|
290
318
|
|
|
291
|
-
The `modifyChart()` method allows you to edit SQL and/or visualization settings, then re-execute and regenerate charts. It works with both fresh `ask()` responses and saved charts.
|
|
319
|
+
The `modifyChart()` method allows you to edit SQL and/or visualization settings, then re-execute and regenerate charts. It works with both fresh `ask()` responses and saved charts. Prefer `queryId` over `sql` (see above).
|
|
292
320
|
|
|
293
321
|
### Changing Visualization Settings
|
|
294
322
|
|
package/dist/index.cjs
CHANGED
|
@@ -2194,6 +2194,25 @@ function anonymizeResults(rows) {
|
|
|
2194
2194
|
});
|
|
2195
2195
|
}
|
|
2196
2196
|
|
|
2197
|
+
// src/routes/queries.ts
|
|
2198
|
+
async function resolveQuery(client, queryEngine, queryId, options, signal) {
|
|
2199
|
+
const response = await client.get(
|
|
2200
|
+
`/v2/queries/${encodeURIComponent(queryId)}`,
|
|
2201
|
+
options.tenantId,
|
|
2202
|
+
options.userId,
|
|
2203
|
+
options.scopes,
|
|
2204
|
+
signal
|
|
2205
|
+
);
|
|
2206
|
+
const paramMetadata = Array.isArray(response.params) ? response.params : [];
|
|
2207
|
+
return {
|
|
2208
|
+
queryId: response.queryId,
|
|
2209
|
+
sql: response.sql,
|
|
2210
|
+
params: queryEngine.mapGeneratedParams(paramMetadata),
|
|
2211
|
+
paramMetadata,
|
|
2212
|
+
dialect: response.dialect
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2197
2216
|
// src/routes/modify.ts
|
|
2198
2217
|
function buildModifiedQuestion(originalQuestion, modifications, pipeline, hasSessionContext = false) {
|
|
2199
2218
|
const hints = [];
|
|
@@ -2348,11 +2367,28 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
2348
2367
|
const hasCustomSql = !!input.sqlModifications?.customSql;
|
|
2349
2368
|
const pipeline = resolveQueryPipeline(options?.pipeline);
|
|
2350
2369
|
const queryEndpoint = pipeline === "v2" ? "/v2/query" : "/query";
|
|
2351
|
-
let
|
|
2370
|
+
let currentSql = input.sql;
|
|
2352
2371
|
let finalParams = input.params ?? {};
|
|
2353
2372
|
let paramMetadata = [];
|
|
2354
2373
|
let rationale;
|
|
2355
2374
|
let queryId;
|
|
2375
|
+
if (input.queryId) {
|
|
2376
|
+
const resolved = await resolveQuery(
|
|
2377
|
+
client,
|
|
2378
|
+
queryEngine,
|
|
2379
|
+
input.queryId,
|
|
2380
|
+
{ tenantId, userId: options?.userId, scopes: options?.scopes },
|
|
2381
|
+
signal
|
|
2382
|
+
);
|
|
2383
|
+
currentSql = resolved.sql;
|
|
2384
|
+
finalParams = resolved.params;
|
|
2385
|
+
paramMetadata = resolved.paramMetadata;
|
|
2386
|
+
queryId = resolved.queryId;
|
|
2387
|
+
}
|
|
2388
|
+
if (!currentSql) {
|
|
2389
|
+
throw new Error("modifyChart requires either queryId or sql.");
|
|
2390
|
+
}
|
|
2391
|
+
let finalSql = currentSql;
|
|
2356
2392
|
let sqlChanged = false;
|
|
2357
2393
|
let finalQuestion = input.question;
|
|
2358
2394
|
const databaseName = input.database ?? queryEngine.getDefaultDatabase();
|
|
@@ -2380,6 +2416,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
2380
2416
|
finalSql = input.sqlModifications.customSql;
|
|
2381
2417
|
finalParams = {};
|
|
2382
2418
|
paramMetadata = [];
|
|
2419
|
+
queryId = void 0;
|
|
2383
2420
|
sqlChanged = true;
|
|
2384
2421
|
} else if (hasSqlMods && !hasCustomSql) {
|
|
2385
2422
|
const modifiedQuestion = buildModifiedQuestion(
|
|
@@ -2396,7 +2433,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
2396
2433
|
{
|
|
2397
2434
|
question: modifiedQuestion,
|
|
2398
2435
|
session_id: querypanelSessionId,
|
|
2399
|
-
previous_sql:
|
|
2436
|
+
previous_sql: currentSql,
|
|
2400
2437
|
...options?.maxRetry ? { max_retry: options.maxRetry } : {},
|
|
2401
2438
|
...tenantSettings ? { tenant_settings: tenantSettings } : {},
|
|
2402
2439
|
...databaseName ? { database: databaseName } : {},
|
|
@@ -2421,7 +2458,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
|
|
|
2421
2458
|
}
|
|
2422
2459
|
rationale = queryResponse.rationale;
|
|
2423
2460
|
queryId = queryResponse.queryId;
|
|
2424
|
-
sqlChanged = finalSql !==
|
|
2461
|
+
sqlChanged = finalSql !== currentSql;
|
|
2425
2462
|
}
|
|
2426
2463
|
const execution = await queryEngine.validateAndExecute(
|
|
2427
2464
|
finalSql,
|
|
@@ -2866,9 +2903,23 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
|
|
|
2866
2903
|
throw new Error("tenantId is required");
|
|
2867
2904
|
}
|
|
2868
2905
|
const databaseName = input.database ?? "db";
|
|
2869
|
-
|
|
2906
|
+
let sql = input.sql;
|
|
2907
|
+
let params = input.params ?? {};
|
|
2908
|
+
if (input.queryId) {
|
|
2909
|
+
const resolved = await resolveQuery(
|
|
2910
|
+
this.client,
|
|
2911
|
+
this.queryEngine,
|
|
2912
|
+
input.queryId,
|
|
2913
|
+
{ tenantId }
|
|
2914
|
+
);
|
|
2915
|
+
sql = resolved.sql;
|
|
2916
|
+
params = resolved.params;
|
|
2917
|
+
}
|
|
2918
|
+
if (!sql) {
|
|
2919
|
+
throw new Error("Either queryId or sql is required");
|
|
2920
|
+
}
|
|
2870
2921
|
const result = await this.queryEngine.validateAndExecute(
|
|
2871
|
-
|
|
2922
|
+
sql,
|
|
2872
2923
|
params,
|
|
2873
2924
|
databaseName,
|
|
2874
2925
|
tenantId
|