@querypanel/node-sdk 1.3.0-beta.1 → 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/dist/index.d.cts CHANGED
@@ -360,10 +360,15 @@ interface ChartCreateInput {
360
360
  title: string;
361
361
  prompt?: string;
362
362
  description?: string;
363
- sql: string;
363
+ /**
364
+ * Required when `query_id` is not provided. Ignored (with `sql_params`) when
365
+ * `query_id` is present: the server saves the SQL and params it stored for that query.
366
+ */
367
+ sql?: string;
364
368
  sql_params?: Record<string, unknown>;
365
369
  vega_lite_spec: Record<string, unknown>;
366
370
  spec_type?: 'vega-lite' | 'vizspec';
371
+ /** Server-issued query id from ask() / modifyChart(). Preferred over `sql`. */
367
372
  query_id?: string;
368
373
  target_db?: string;
369
374
  }
@@ -373,6 +378,8 @@ interface ChartUpdateInput {
373
378
  description?: string;
374
379
  sql?: string;
375
380
  sql_params?: Record<string, unknown>;
381
+ /** When present, the server replaces sql / sql_params with the stored query. */
382
+ query_id?: string;
376
383
  vega_lite_spec?: Record<string, unknown>;
377
384
  spec_type?: 'vega-lite' | 'vizspec';
378
385
  target_db?: string;
@@ -917,11 +924,22 @@ interface VizModifications {
917
924
  */
918
925
  interface ChartModifyInput {
919
926
  /**
920
- * The SQL query to modify or re-execute.
927
+ * Server-issued id of the query to modify or re-execute.
928
+ * From ask() / modifyChart() response: response.queryId
929
+ * From saved chart: chart.query_id
930
+ *
931
+ * Preferred over `sql`: when present the SQL and params are loaded from the server
932
+ * (scoped to the authenticated tenant) and `sql` / `params` are ignored.
933
+ */
934
+ queryId?: string;
935
+ /**
936
+ * The SQL query to modify or re-execute. Required when `queryId` is not provided.
921
937
  * From ask() response: response.sql
922
938
  * From saved chart: chart.sql
939
+ *
940
+ * Kept for backward compatibility; prefer `queryId`.
923
941
  */
924
- sql: string;
942
+ sql?: string;
925
943
  /**
926
944
  * The original natural language question.
927
945
  * Used when regenerating SQL with modifications.
@@ -1313,7 +1331,13 @@ declare class QueryPanelSdkAPI {
1313
1331
  * to be attached (e.g. via attachPostgres) and options.tenantId.
1314
1332
  */
1315
1333
  runSqlForDashboard(input: {
1316
- sql: string;
1334
+ /**
1335
+ * Server-issued id from ask() / modifyChart(). Takes priority: the stored SQL
1336
+ * and params are executed and `sql` / `params` are ignored.
1337
+ */
1338
+ queryId?: string;
1339
+ /** Required when `queryId` is not provided (backward compatible raw SQL). */
1340
+ sql?: string;
1317
1341
  params?: Record<string, unknown>;
1318
1342
  database?: string;
1319
1343
  }, options: {
package/dist/index.d.ts CHANGED
@@ -360,10 +360,15 @@ interface ChartCreateInput {
360
360
  title: string;
361
361
  prompt?: string;
362
362
  description?: string;
363
- sql: string;
363
+ /**
364
+ * Required when `query_id` is not provided. Ignored (with `sql_params`) when
365
+ * `query_id` is present: the server saves the SQL and params it stored for that query.
366
+ */
367
+ sql?: string;
364
368
  sql_params?: Record<string, unknown>;
365
369
  vega_lite_spec: Record<string, unknown>;
366
370
  spec_type?: 'vega-lite' | 'vizspec';
371
+ /** Server-issued query id from ask() / modifyChart(). Preferred over `sql`. */
367
372
  query_id?: string;
368
373
  target_db?: string;
369
374
  }
@@ -373,6 +378,8 @@ interface ChartUpdateInput {
373
378
  description?: string;
374
379
  sql?: string;
375
380
  sql_params?: Record<string, unknown>;
381
+ /** When present, the server replaces sql / sql_params with the stored query. */
382
+ query_id?: string;
376
383
  vega_lite_spec?: Record<string, unknown>;
377
384
  spec_type?: 'vega-lite' | 'vizspec';
378
385
  target_db?: string;
@@ -917,11 +924,22 @@ interface VizModifications {
917
924
  */
918
925
  interface ChartModifyInput {
919
926
  /**
920
- * The SQL query to modify or re-execute.
927
+ * Server-issued id of the query to modify or re-execute.
928
+ * From ask() / modifyChart() response: response.queryId
929
+ * From saved chart: chart.query_id
930
+ *
931
+ * Preferred over `sql`: when present the SQL and params are loaded from the server
932
+ * (scoped to the authenticated tenant) and `sql` / `params` are ignored.
933
+ */
934
+ queryId?: string;
935
+ /**
936
+ * The SQL query to modify or re-execute. Required when `queryId` is not provided.
921
937
  * From ask() response: response.sql
922
938
  * From saved chart: chart.sql
939
+ *
940
+ * Kept for backward compatibility; prefer `queryId`.
923
941
  */
924
- sql: string;
942
+ sql?: string;
925
943
  /**
926
944
  * The original natural language question.
927
945
  * Used when regenerating SQL with modifications.
@@ -1313,7 +1331,13 @@ declare class QueryPanelSdkAPI {
1313
1331
  * to be attached (e.g. via attachPostgres) and options.tenantId.
1314
1332
  */
1315
1333
  runSqlForDashboard(input: {
1316
- sql: string;
1334
+ /**
1335
+ * Server-issued id from ask() / modifyChart(). Takes priority: the stored SQL
1336
+ * and params are executed and `sql` / `params` are ignored.
1337
+ */
1338
+ queryId?: string;
1339
+ /** Required when `queryId` is not provided (backward compatible raw SQL). */
1340
+ sql?: string;
1317
1341
  params?: Record<string, unknown>;
1318
1342
  database?: string;
1319
1343
  }, options: {
package/dist/index.js CHANGED
@@ -1921,11 +1921,17 @@ function buildSchemaRequest(databaseName, adapter, introspection, metadata) {
1921
1921
  dialect,
1922
1922
  tables
1923
1923
  };
1924
- if (metadata?.tenantFieldName && metadata?.tenantFieldType && metadata?.enforceTenantIsolation !== void 0) {
1924
+ if (metadata?.enforceTenantIsolation === false) {
1925
+ request.tenant_settings = {
1926
+ tenantFieldName: metadata.tenantFieldName ?? "",
1927
+ tenantFieldType: metadata.tenantFieldType ?? "String",
1928
+ enforceTenantIsolation: false
1929
+ };
1930
+ } else if (metadata?.tenantFieldName && metadata?.tenantFieldType) {
1925
1931
  request.tenant_settings = {
1926
1932
  tenantFieldName: metadata.tenantFieldName,
1927
1933
  tenantFieldType: metadata.tenantFieldType,
1928
- enforceTenantIsolation: metadata.enforceTenantIsolation
1934
+ enforceTenantIsolation: true
1929
1935
  };
1930
1936
  }
1931
1937
  return request;
@@ -1953,11 +1959,17 @@ async function ask(client, queryEngine, question, options, signal) {
1953
1959
  const databaseName = options.database ?? queryEngine.getDefaultDatabase();
1954
1960
  const metadata = databaseName ? queryEngine.getDatabaseMetadata(databaseName) : void 0;
1955
1961
  let tenantSettings;
1956
- if (metadata?.tenantFieldName) {
1962
+ if (metadata?.enforceTenantIsolation === false) {
1963
+ tenantSettings = {
1964
+ tenantFieldName: metadata.tenantFieldName ?? "",
1965
+ tenantFieldType: metadata.tenantFieldType ?? "String",
1966
+ enforceTenantIsolation: false
1967
+ };
1968
+ } else if (metadata?.tenantFieldName) {
1957
1969
  tenantSettings = {
1958
1970
  tenantFieldName: metadata.tenantFieldName,
1959
1971
  tenantFieldType: metadata.tenantFieldType,
1960
- enforceTenantIsolation: metadata.enforceTenantIsolation
1972
+ enforceTenantIsolation: true
1961
1973
  };
1962
1974
  }
1963
1975
  const queryResponse = await client.postWithHeaders(
@@ -2135,6 +2147,25 @@ function anonymizeResults(rows) {
2135
2147
  });
2136
2148
  }
2137
2149
 
2150
+ // src/routes/queries.ts
2151
+ async function resolveQuery(client, queryEngine, queryId, options, signal) {
2152
+ const response = await client.get(
2153
+ `/v2/queries/${encodeURIComponent(queryId)}`,
2154
+ options.tenantId,
2155
+ options.userId,
2156
+ options.scopes,
2157
+ signal
2158
+ );
2159
+ const paramMetadata = Array.isArray(response.params) ? response.params : [];
2160
+ return {
2161
+ queryId: response.queryId,
2162
+ sql: response.sql,
2163
+ params: queryEngine.mapGeneratedParams(paramMetadata),
2164
+ paramMetadata,
2165
+ dialect: response.dialect
2166
+ };
2167
+ }
2168
+
2138
2169
  // src/routes/modify.ts
2139
2170
  function buildModifiedQuestion(originalQuestion, modifications, pipeline, hasSessionContext = false) {
2140
2171
  const hints = [];
@@ -2289,11 +2320,28 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2289
2320
  const hasCustomSql = !!input.sqlModifications?.customSql;
2290
2321
  const pipeline = resolveQueryPipeline(options?.pipeline);
2291
2322
  const queryEndpoint = pipeline === "v2" ? "/v2/query" : "/query";
2292
- let finalSql = input.sql;
2323
+ let currentSql = input.sql;
2293
2324
  let finalParams = input.params ?? {};
2294
2325
  let paramMetadata = [];
2295
2326
  let rationale;
2296
2327
  let queryId;
2328
+ if (input.queryId) {
2329
+ const resolved = await resolveQuery(
2330
+ client,
2331
+ queryEngine,
2332
+ input.queryId,
2333
+ { tenantId, userId: options?.userId, scopes: options?.scopes },
2334
+ signal
2335
+ );
2336
+ currentSql = resolved.sql;
2337
+ finalParams = resolved.params;
2338
+ paramMetadata = resolved.paramMetadata;
2339
+ queryId = resolved.queryId;
2340
+ }
2341
+ if (!currentSql) {
2342
+ throw new Error("modifyChart requires either queryId or sql.");
2343
+ }
2344
+ let finalSql = currentSql;
2297
2345
  let sqlChanged = false;
2298
2346
  let finalQuestion = input.question;
2299
2347
  const databaseName = input.database ?? queryEngine.getDefaultDatabase();
@@ -2304,17 +2352,24 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2304
2352
  }
2305
2353
  const metadata = queryEngine.getDatabaseMetadata(databaseName);
2306
2354
  let tenantSettings;
2307
- if (metadata?.tenantFieldName) {
2355
+ if (metadata?.enforceTenantIsolation === false) {
2356
+ tenantSettings = {
2357
+ tenantFieldName: metadata.tenantFieldName ?? "",
2358
+ tenantFieldType: metadata.tenantFieldType ?? "String",
2359
+ enforceTenantIsolation: false
2360
+ };
2361
+ } else if (metadata?.tenantFieldName) {
2308
2362
  tenantSettings = {
2309
2363
  tenantFieldName: metadata.tenantFieldName,
2310
2364
  tenantFieldType: metadata.tenantFieldType,
2311
- enforceTenantIsolation: metadata.enforceTenantIsolation
2365
+ enforceTenantIsolation: true
2312
2366
  };
2313
2367
  }
2314
2368
  if (hasCustomSql) {
2315
2369
  finalSql = input.sqlModifications.customSql;
2316
2370
  finalParams = {};
2317
2371
  paramMetadata = [];
2372
+ queryId = void 0;
2318
2373
  sqlChanged = true;
2319
2374
  } else if (hasSqlMods && !hasCustomSql) {
2320
2375
  const modifiedQuestion = buildModifiedQuestion(
@@ -2331,7 +2386,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2331
2386
  {
2332
2387
  question: modifiedQuestion,
2333
2388
  session_id: querypanelSessionId,
2334
- previous_sql: input.sql,
2389
+ previous_sql: currentSql,
2335
2390
  ...options?.maxRetry ? { max_retry: options.maxRetry } : {},
2336
2391
  ...tenantSettings ? { tenant_settings: tenantSettings } : {},
2337
2392
  ...databaseName ? { database: databaseName } : {},
@@ -2356,7 +2411,7 @@ async function modifyChart(client, queryEngine, input, options, signal) {
2356
2411
  }
2357
2412
  rationale = queryResponse.rationale;
2358
2413
  queryId = queryResponse.queryId;
2359
- sqlChanged = finalSql !== input.sql;
2414
+ sqlChanged = finalSql !== currentSql;
2360
2415
  }
2361
2416
  const execution = await queryEngine.validateAndExecute(
2362
2417
  finalSql,
@@ -2564,6 +2619,12 @@ var ALL_VIZ_CHART_TYPES = [
2564
2619
  ];
2565
2620
 
2566
2621
  // src/index.ts
2622
+ function resolveAttachEnforceTenantIsolation(tenantFieldName, enforceTenantIsolation) {
2623
+ if (enforceTenantIsolation !== void 0) {
2624
+ return enforceTenantIsolation;
2625
+ }
2626
+ return tenantFieldName ? true : void 0;
2627
+ }
2567
2628
  var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2568
2629
  /**
2569
2630
  * @param workspaceId - Workspace UUID (same value as your org in the dashboard). Passed to the API as JWT claim `organizationId`.
@@ -2634,7 +2695,10 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2634
2695
  tags: options?.tags,
2635
2696
  tenantFieldName: options?.tenantFieldName,
2636
2697
  tenantFieldType: options?.tenantFieldType ?? "String",
2637
- enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
2698
+ enforceTenantIsolation: resolveAttachEnforceTenantIsolation(
2699
+ options?.tenantFieldName,
2700
+ options?.enforceTenantIsolation
2701
+ )
2638
2702
  };
2639
2703
  this.queryEngine.attachDatabase(name, adapter, metadata);
2640
2704
  }
@@ -2647,7 +2711,10 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2647
2711
  tags: options?.tags,
2648
2712
  tenantFieldName: options?.tenantFieldName,
2649
2713
  tenantFieldType: options?.tenantFieldType ?? "String",
2650
- enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
2714
+ enforceTenantIsolation: resolveAttachEnforceTenantIsolation(
2715
+ options?.tenantFieldName,
2716
+ options?.enforceTenantIsolation
2717
+ )
2651
2718
  };
2652
2719
  this.queryEngine.attachDatabase(name, adapter, metadata);
2653
2720
  }
@@ -2660,7 +2727,10 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2660
2727
  tags: options?.tags,
2661
2728
  tenantFieldName: options?.tenantFieldName,
2662
2729
  tenantFieldType: options?.tenantFieldType ?? "String",
2663
- enforceTenantIsolation: options?.tenantFieldName ? options?.enforceTenantIsolation ?? true : void 0
2730
+ enforceTenantIsolation: resolveAttachEnforceTenantIsolation(
2731
+ options?.tenantFieldName,
2732
+ options?.enforceTenantIsolation
2733
+ )
2664
2734
  };
2665
2735
  this.queryEngine.attachDatabase(name, adapter, metadata);
2666
2736
  }
@@ -2786,9 +2856,23 @@ var QueryPanelSdkAPI = class _QueryPanelSdkAPI {
2786
2856
  throw new Error("tenantId is required");
2787
2857
  }
2788
2858
  const databaseName = input.database ?? "db";
2789
- const params = input.params ?? {};
2859
+ let sql = input.sql;
2860
+ let params = input.params ?? {};
2861
+ if (input.queryId) {
2862
+ const resolved = await resolveQuery(
2863
+ this.client,
2864
+ this.queryEngine,
2865
+ input.queryId,
2866
+ { tenantId }
2867
+ );
2868
+ sql = resolved.sql;
2869
+ params = resolved.params;
2870
+ }
2871
+ if (!sql) {
2872
+ throw new Error("Either queryId or sql is required");
2873
+ }
2790
2874
  const result = await this.queryEngine.validateAndExecute(
2791
- input.sql,
2875
+ sql,
2792
2876
  params,
2793
2877
  databaseName,
2794
2878
  tenantId