@querypanel/node-sdk 1.0.41 → 1.0.43
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 +143 -8
- package/dist/index.cjs +565 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +476 -1
- package/dist/index.d.ts +476 -1
- package/dist/index.js +565 -11
- package/dist/index.js.map +1 -1
- package/package.json +71 -71
package/README.md
CHANGED
|
@@ -42,18 +42,26 @@ const createPostgresClient = () => async (sql: string, params?: unknown[]) => {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
// Attach PostgreSQL database using the SDK's PostgresAdapter
|
|
46
|
+
// The SDK will automatically handle tenant isolation when tenantFieldName is provided
|
|
47
|
+
qp.attachPostgres(
|
|
48
|
+
"pg_demo", // a uniq identifier for QueryPanel
|
|
49
|
+
createPostgresClientFn(),
|
|
50
|
+
{
|
|
51
|
+
database: "pg_demo", // database name
|
|
52
|
+
description: "PostgreSQL demo database", // some description that QueryPanel can use
|
|
53
|
+
tenantFieldName: "tenant_id", // SDK will automatically filter by tenant_id
|
|
54
|
+
enforceTenantIsolation: true, // Ensures all queries include tenant_id filter
|
|
55
|
+
allowedTables: ["orders"], // Only sync 'orders' table - 'users' will be excluded
|
|
56
|
+
});
|
|
49
57
|
|
|
50
58
|
qp.attachClickhouse(
|
|
51
|
-
"clicks",
|
|
59
|
+
"clicks", // uniq identifier for QueryPanel
|
|
52
60
|
(params) => clickhouse.query(params),
|
|
53
61
|
{
|
|
54
|
-
database: "analytics",
|
|
55
|
-
tenantFieldName: "customer_id",
|
|
56
|
-
tenantFieldType: "String",
|
|
62
|
+
database: "analytics", // database name
|
|
63
|
+
tenantFieldName: "customer_id", // SDK will automatically filter by tenant_id
|
|
64
|
+
tenantFieldType: "String", // SDK will use it in the clickhouse query as {customer_id::String}
|
|
57
65
|
},
|
|
58
66
|
);
|
|
59
67
|
|
|
@@ -106,6 +114,133 @@ if (response.chart.vegaLiteSpec) {
|
|
|
106
114
|
const charts = await qp.listCharts({ tenantId: "tenant_123" });
|
|
107
115
|
```
|
|
108
116
|
|
|
117
|
+
## Modifying Charts
|
|
118
|
+
|
|
119
|
+
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.
|
|
120
|
+
|
|
121
|
+
### Changing Visualization Settings
|
|
122
|
+
|
|
123
|
+
Modify chart type, axes, or series without regenerating SQL:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
// Start with an ask() response
|
|
127
|
+
const response = await qp.ask("revenue by country", {
|
|
128
|
+
tenantId: "tenant_123",
|
|
129
|
+
database: "analytics",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Change to a bar chart with specific axis configuration
|
|
133
|
+
const modified = await qp.modifyChart({
|
|
134
|
+
sql: response.sql,
|
|
135
|
+
question: "revenue by country",
|
|
136
|
+
database: "analytics",
|
|
137
|
+
vizModifications: {
|
|
138
|
+
chartType: "bar",
|
|
139
|
+
xAxis: { field: "country", label: "Country" },
|
|
140
|
+
yAxis: { field: "revenue", label: "Total Revenue", aggregate: "sum" },
|
|
141
|
+
},
|
|
142
|
+
}, { tenantId: "tenant_123" });
|
|
143
|
+
|
|
144
|
+
console.log(modified.chart); // New chart spec with bar visualization
|
|
145
|
+
console.log(modified.modified.vizChanged); // true
|
|
146
|
+
console.log(modified.modified.sqlChanged); // false
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Changing Time Granularity and Date Range
|
|
150
|
+
|
|
151
|
+
These modifications trigger SQL regeneration:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// Change from daily to monthly aggregation
|
|
155
|
+
const monthly = await qp.modifyChart({
|
|
156
|
+
sql: response.sql,
|
|
157
|
+
question: "revenue over time",
|
|
158
|
+
database: "analytics",
|
|
159
|
+
sqlModifications: {
|
|
160
|
+
timeGranularity: "month",
|
|
161
|
+
dateRange: { from: "2024-01-01", to: "2024-12-31" },
|
|
162
|
+
},
|
|
163
|
+
}, { tenantId: "tenant_123" });
|
|
164
|
+
|
|
165
|
+
console.log(monthly.sql); // New SQL with monthly GROUP BY
|
|
166
|
+
console.log(monthly.modified.sqlChanged); // true
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Direct SQL Editing
|
|
170
|
+
|
|
171
|
+
Provide custom SQL that will be executed directly:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const customized = await qp.modifyChart({
|
|
175
|
+
sql: response.sql,
|
|
176
|
+
question: "revenue by country",
|
|
177
|
+
database: "analytics",
|
|
178
|
+
sqlModifications: {
|
|
179
|
+
customSql: `
|
|
180
|
+
SELECT country, SUM(revenue) as total_revenue
|
|
181
|
+
FROM orders
|
|
182
|
+
WHERE status = 'completed' AND created_at > '2024-01-01'
|
|
183
|
+
GROUP BY country
|
|
184
|
+
ORDER BY total_revenue DESC
|
|
185
|
+
LIMIT 10
|
|
186
|
+
`,
|
|
187
|
+
},
|
|
188
|
+
}, { tenantId: "tenant_123" });
|
|
189
|
+
|
|
190
|
+
// Optionally save the modified chart
|
|
191
|
+
if (customized.chart.vegaLiteSpec) {
|
|
192
|
+
await qp.createChart({
|
|
193
|
+
title: "Top 10 Countries by Revenue (Completed Orders)",
|
|
194
|
+
sql: customized.sql,
|
|
195
|
+
sql_params: customized.params,
|
|
196
|
+
vega_lite_spec: customized.chart.vegaLiteSpec,
|
|
197
|
+
target_db: customized.target_db,
|
|
198
|
+
}, { tenantId: "tenant_123" });
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Combining SQL and Visualization Changes
|
|
203
|
+
|
|
204
|
+
Apply both types of modifications in a single call:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
const combined = await qp.modifyChart({
|
|
208
|
+
sql: response.sql,
|
|
209
|
+
question: "revenue over time",
|
|
210
|
+
database: "analytics",
|
|
211
|
+
sqlModifications: {
|
|
212
|
+
timeGranularity: "week",
|
|
213
|
+
additionalInstructions: "exclude refunded orders",
|
|
214
|
+
},
|
|
215
|
+
vizModifications: {
|
|
216
|
+
chartType: "area",
|
|
217
|
+
stacking: "stacked",
|
|
218
|
+
},
|
|
219
|
+
}, { tenantId: "tenant_123" });
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Modifying Saved Charts
|
|
223
|
+
|
|
224
|
+
Load a saved chart and modify it:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
// Load a saved chart
|
|
228
|
+
const savedChart = await qp.getChart("chart_id_123", {
|
|
229
|
+
tenantId: "tenant_123",
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Modify it
|
|
233
|
+
const modified = await qp.modifyChart({
|
|
234
|
+
sql: savedChart.sql,
|
|
235
|
+
question: "original question", // Store this when saving charts
|
|
236
|
+
database: savedChart.target_db ?? "analytics",
|
|
237
|
+
params: savedChart.sql_params as Record<string, unknown>,
|
|
238
|
+
vizModifications: {
|
|
239
|
+
chartType: "line",
|
|
240
|
+
},
|
|
241
|
+
}, { tenantId: "tenant_123" });
|
|
242
|
+
```
|
|
243
|
+
|
|
109
244
|
## Building a Dashboard (Active Charts)
|
|
110
245
|
|
|
111
246
|
While `createChart` and `listCharts` manage your **history** of saved queries, "Active Charts" are designed for building **dashboards**. You can "pin" a saved chart to a dashboard, control its order, and fetch it with live data in a single call.
|