@pythia-software/query-table-react 0.9.3 → 0.9.4
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.js +138 -59
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -312,9 +312,9 @@ import {
|
|
|
312
312
|
createGroupingModel,
|
|
313
313
|
prepareGrouping,
|
|
314
314
|
withoutGrouping as withoutGrouping2,
|
|
315
|
-
sourceExecutionSchema,
|
|
316
|
-
toQueryRequestV3,
|
|
317
|
-
validateQueryResultV3,
|
|
315
|
+
sourceExecutionSchema as sourceExecutionSchema2,
|
|
316
|
+
toQueryRequestV3 as toQueryRequestV32,
|
|
317
|
+
validateQueryResultV3 as validateQueryResultV32,
|
|
318
318
|
metricPopulationError as metricPopulationError2
|
|
319
319
|
} from "@pythia-software/query-table-core";
|
|
320
320
|
import { ITEM_DETAILS_COLUMN, itemPageFields } from "@pythia-software/query-table-core";
|
|
@@ -688,7 +688,8 @@ function validateComputedResponse(request, result, schema) {
|
|
|
688
688
|
);
|
|
689
689
|
const executed = /* @__PURE__ */ new Set([
|
|
690
690
|
...request.select.filter(isComputedField),
|
|
691
|
-
...request.orderBy.map((term) => term.field).filter(isComputedField)
|
|
691
|
+
...request.orderBy.map((term) => term.field).filter(isComputedField),
|
|
692
|
+
...request.where.flatMap((term) => ("any" in term ? term.any : [term]).map((predicate) => predicate.field)).filter(isComputedField)
|
|
692
693
|
]);
|
|
693
694
|
for (const [name, revision] of Object.entries(request.expectedRevisions)) {
|
|
694
695
|
const id = name.replace(/^@computed\//, "");
|
|
@@ -721,6 +722,53 @@ function validateComputedResponse(request, result, schema) {
|
|
|
721
722
|
}
|
|
722
723
|
}
|
|
723
724
|
|
|
725
|
+
// src/previewRows.ts
|
|
726
|
+
import {
|
|
727
|
+
sourceExecutionSchema,
|
|
728
|
+
toQueryRequestV3,
|
|
729
|
+
toServerQuery,
|
|
730
|
+
toServerQueryV2,
|
|
731
|
+
validateQueryResultV3
|
|
732
|
+
} from "@pythia-software/query-table-core";
|
|
733
|
+
async function fetchPreviewRows(transport, query, schema, execution, definitions, now, signal, baseSchema = schema) {
|
|
734
|
+
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
735
|
+
const sourceSchema = sourceExecutionSchema(baseSchema, execution, definitions);
|
|
736
|
+
let result;
|
|
737
|
+
const computedFilter = query.where.some((term) => ("any" in term ? term.any : [term]).some((predicate) => predicate.field.startsWith("@computed/")));
|
|
738
|
+
if (transport.fetchRowsV2 && execution && !query.grouping && !computedFilter) {
|
|
739
|
+
const request = toServerQueryV2(query, sourceSchema, execution);
|
|
740
|
+
if (request.diagnostics.length)
|
|
741
|
+
throw Error(request.diagnostics.map((issue) => issue.message).join(" "));
|
|
742
|
+
for (const definition of definitions) {
|
|
743
|
+
if (executionRevision(execution, definition.id) !== definition.revision && (request.select.includes(`@computed/${definition.id}`) || request.orderBy.some((term) => term.field === `@computed/${definition.id}`) || request.where.some((term) => ("any" in term ? term.any : [term]).some((predicate) => predicate.field === `@computed/${definition.id}`))))
|
|
744
|
+
throw Error("Computed definitions changed. Refresh the server execution handshake.");
|
|
745
|
+
}
|
|
746
|
+
const response = await transport.fetchRowsV2(request, signal);
|
|
747
|
+
validateComputedResponse(request, response, sourceSchema);
|
|
748
|
+
result = response;
|
|
749
|
+
} else if (transport.fetchQueryV3 && transport.queryCapabilities?.version === 3) {
|
|
750
|
+
const request = toQueryRequestV3(
|
|
751
|
+
{ ...query, aggregations: [] },
|
|
752
|
+
sourceSchema,
|
|
753
|
+
transport.queryCapabilities,
|
|
754
|
+
execution,
|
|
755
|
+
{ now }
|
|
756
|
+
);
|
|
757
|
+
if (request.diagnostics.length) throw Error(request.diagnostics.join(" "));
|
|
758
|
+
const response = await transport.fetchQueryV3(request, signal);
|
|
759
|
+
validateQueryResultV3(response, request, query.grouping ? schema : sourceSchema);
|
|
760
|
+
result = { rows: response.rows, total: response.total };
|
|
761
|
+
} else if (transport.fetchRows && !query.grouping && !(computedFilter && transport.fetchRowsV2 && execution)) {
|
|
762
|
+
result = await transport.fetchRows(toServerQuery(query, schema), signal);
|
|
763
|
+
} else {
|
|
764
|
+
throw Error("Row execution requires fetchRows, negotiated fetchRowsV2, or negotiated fetchQueryV3.");
|
|
765
|
+
}
|
|
766
|
+
if (signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
767
|
+
if (!Number.isSafeInteger(result.total) || result.total < 0 || !Array.isArray(result.rows) || result.rows.length > query.limit)
|
|
768
|
+
throw Error("Invalid preview row response.");
|
|
769
|
+
return result;
|
|
770
|
+
}
|
|
771
|
+
|
|
724
772
|
// src/useComputedColumns.ts
|
|
725
773
|
import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
|
|
726
774
|
import {
|
|
@@ -732,7 +780,6 @@ import {
|
|
|
732
780
|
isComputedField as isComputedField2,
|
|
733
781
|
memoryComputedColumnStore,
|
|
734
782
|
readFieldValue as readFieldValue2,
|
|
735
|
-
toServerQuery,
|
|
736
783
|
validateComputedColumn,
|
|
737
784
|
isSelectable,
|
|
738
785
|
hasRegex
|
|
@@ -1101,59 +1148,80 @@ function useComputedColumns(options) {
|
|
|
1101
1148
|
},
|
|
1102
1149
|
[compile, store, schema.name]
|
|
1103
1150
|
);
|
|
1151
|
+
const previewRequest = useRef4(null);
|
|
1104
1152
|
const preview = useCallback4(
|
|
1105
1153
|
async (source, count, signal, editingId, includeInputs = true) => {
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1154
|
+
previewRequest.current?.abort();
|
|
1155
|
+
const controller = new AbortController();
|
|
1156
|
+
previewRequest.current = controller;
|
|
1157
|
+
const abort2 = () => controller.abort();
|
|
1158
|
+
signal?.addEventListener("abort", abort2, { once: true });
|
|
1159
|
+
if (signal?.aborted) controller.abort();
|
|
1160
|
+
try {
|
|
1161
|
+
if (!Number.isInteger(count) || count < 1 || count > 1e4)
|
|
1162
|
+
throw new Error("Choose between 1 and 10,000 rows.");
|
|
1163
|
+
const plan = compile(source, editingId);
|
|
1164
|
+
let batch = [], total = 0;
|
|
1165
|
+
if (transport) {
|
|
1166
|
+
const request = {
|
|
1113
1167
|
...query,
|
|
1168
|
+
...options.previewQuery?.grouping ? { grouping: options.previewQuery.grouping } : {},
|
|
1114
1169
|
select: [
|
|
1115
1170
|
.../* @__PURE__ */ new Set([schema.idField, ...backendDependencies(plan)])
|
|
1116
1171
|
].map((field) => ({ field })),
|
|
1117
1172
|
limit: Math.min(count, 500),
|
|
1118
1173
|
offset: 0
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1174
|
+
};
|
|
1175
|
+
const now = options.now ?? Date.now();
|
|
1176
|
+
const computedFilter = request.where.some((term) => ("any" in term ? term.any : [term]).some((predicate) => isComputedField2(predicate.field)));
|
|
1177
|
+
const v3 = !(transport.fetchRowsV2 && options.execution && !request.grouping && !computedFilter) && transport.fetchQueryV3 && transport.queryCapabilities?.version === 3;
|
|
1178
|
+
const pageSize = Math.min(500, v3 ? transport.queryCapabilities.maxRows : 500);
|
|
1179
|
+
if (!Number.isInteger(pageSize) || pageSize < 1) throw Error("Invalid negotiated preview row limit.");
|
|
1180
|
+
while (batch.length < count) {
|
|
1181
|
+
const res = await fetchPreviewRows(
|
|
1182
|
+
transport,
|
|
1183
|
+
{
|
|
1184
|
+
...request,
|
|
1185
|
+
offset: batch.length,
|
|
1186
|
+
limit: Math.min(pageSize, count - batch.length)
|
|
1187
|
+
},
|
|
1188
|
+
schema,
|
|
1189
|
+
options.execution,
|
|
1190
|
+
definitions,
|
|
1191
|
+
now,
|
|
1192
|
+
controller.signal,
|
|
1193
|
+
options.sourceSchema
|
|
1194
|
+
);
|
|
1195
|
+
total = res.total;
|
|
1196
|
+
batch.push(...res.rows.slice(0, count - batch.length));
|
|
1197
|
+
if (!res.rows.length || batch.length >= total) break;
|
|
1198
|
+
}
|
|
1199
|
+
} else {
|
|
1200
|
+
const result = applyQuery(
|
|
1201
|
+
clientRows ?? [],
|
|
1202
|
+
{ ...query, limit: count, offset: 0 },
|
|
1203
|
+
schema
|
|
1131
1204
|
);
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
if (!res.rows.length || batch.length >= total) break;
|
|
1205
|
+
batch = result.rows;
|
|
1206
|
+
total = result.total;
|
|
1135
1207
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1208
|
+
const inputs = inputsFor(plan, batch), results = await evaluateFormulaRows(
|
|
1209
|
+
plan.ast,
|
|
1210
|
+
inputs,
|
|
1211
|
+
controller.signal,
|
|
1212
|
+
workerFactory
|
|
1213
|
+
);
|
|
1214
|
+
if (controller.signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
1215
|
+
return groupPreview(
|
|
1216
|
+
includeInputs ? plan.dependencies : [],
|
|
1217
|
+
inputs,
|
|
1218
|
+
results,
|
|
1219
|
+
total
|
|
1141
1220
|
);
|
|
1142
|
-
|
|
1143
|
-
|
|
1221
|
+
} finally {
|
|
1222
|
+
signal?.removeEventListener("abort", abort2);
|
|
1223
|
+
if (previewRequest.current === controller) previewRequest.current = null;
|
|
1144
1224
|
}
|
|
1145
|
-
const inputs = inputsFor(plan, batch), results = await evaluateFormulaRows(
|
|
1146
|
-
plan.ast,
|
|
1147
|
-
inputs,
|
|
1148
|
-
signal,
|
|
1149
|
-
workerFactory
|
|
1150
|
-
);
|
|
1151
|
-
return groupPreview(
|
|
1152
|
-
includeInputs ? plan.dependencies : [],
|
|
1153
|
-
inputs,
|
|
1154
|
-
results,
|
|
1155
|
-
total
|
|
1156
|
-
);
|
|
1157
1225
|
},
|
|
1158
1226
|
[
|
|
1159
1227
|
compile,
|
|
@@ -1163,9 +1231,15 @@ function useComputedColumns(options) {
|
|
|
1163
1231
|
backendDependencies,
|
|
1164
1232
|
clientRows,
|
|
1165
1233
|
inputsFor,
|
|
1166
|
-
workerFactory
|
|
1234
|
+
workerFactory,
|
|
1235
|
+
options.execution,
|
|
1236
|
+
definitions,
|
|
1237
|
+
options.sourceSchema,
|
|
1238
|
+
options.previewQuery?.grouping,
|
|
1239
|
+
options.now
|
|
1167
1240
|
]
|
|
1168
1241
|
);
|
|
1242
|
+
useEffect4(() => () => previewRequest.current?.abort(), [preview]);
|
|
1169
1243
|
return {
|
|
1170
1244
|
displaySchema,
|
|
1171
1245
|
api: {
|
|
@@ -1198,7 +1272,7 @@ import {
|
|
|
1198
1272
|
metricDependencies,
|
|
1199
1273
|
isComputedField as isComputedField4,
|
|
1200
1274
|
computedFieldName as computedFieldName2,
|
|
1201
|
-
toServerQueryV2
|
|
1275
|
+
toServerQueryV2 as toServerQueryV22
|
|
1202
1276
|
} from "@pythia-software/query-table-core";
|
|
1203
1277
|
|
|
1204
1278
|
// src/useRequestActivity.ts
|
|
@@ -2318,7 +2392,7 @@ function useQueryTable(opts) {
|
|
|
2318
2392
|
() => opts.canonicalizeQuery?.(storedQuery) ?? storedQuery,
|
|
2319
2393
|
[storedQuery, opts.canonicalizeQuery]
|
|
2320
2394
|
);
|
|
2321
|
-
const sourceCatalogue = useMemo9(() =>
|
|
2395
|
+
const sourceCatalogue = useMemo9(() => sourceExecutionSchema2(sourceSchema, opts.computedExecution), [sourceSchema, opts.computedExecution]);
|
|
2322
2396
|
const sourceRows = providedRows;
|
|
2323
2397
|
const groupingModel = useMemo9(() => createGroupingModel(sourceCatalogue), [sourceCatalogue]);
|
|
2324
2398
|
const remoteGrouping = !!transport?.fetchQueryV3 && transport.queryCapabilities?.version === 3 && transport.queryCapabilities.groupedRows;
|
|
@@ -2493,6 +2567,9 @@ function useQueryTable(opts) {
|
|
|
2493
2567
|
const { api: computed, displaySchema } = useComputedColumns({
|
|
2494
2568
|
schema,
|
|
2495
2569
|
query: executionQuery,
|
|
2570
|
+
sourceSchema,
|
|
2571
|
+
previewQuery: query,
|
|
2572
|
+
...groupingNow !== void 0 ? { now: groupingNow } : {},
|
|
2496
2573
|
rows,
|
|
2497
2574
|
serverComputed,
|
|
2498
2575
|
...serverExecution ? { serverExecution } : {},
|
|
@@ -2508,7 +2585,7 @@ function useQueryTable(opts) {
|
|
|
2508
2585
|
(name) => isComputedField4(name) ? computed.compile(`[${name.replace(/]/g, "]] ".trim())}]`) : void 0,
|
|
2509
2586
|
[computed.compile]
|
|
2510
2587
|
);
|
|
2511
|
-
const metricCompileSchema = useMemo9(() => opts.metricExecution ?
|
|
2588
|
+
const metricCompileSchema = useMemo9(() => opts.metricExecution ? sourceExecutionSchema2(displaySchema, opts.metricExecution, computed.definitions) : displaySchema, [displaySchema, opts.metricExecution, computed.definitions]);
|
|
2512
2589
|
const metricCompile = useCallback12(
|
|
2513
2590
|
(clause) => {
|
|
2514
2591
|
const diagnostics = validateMetric2(
|
|
@@ -2538,7 +2615,7 @@ function useQueryTable(opts) {
|
|
|
2538
2615
|
...query.select.length ? query.select : defaults.select,
|
|
2539
2616
|
...pageFields.filter((name) => displaySchema.fields.some((field) => field.name === name)).map((field) => ({ field }))
|
|
2540
2617
|
] } : executionQuery;
|
|
2541
|
-
const v2Request = execution && transport?.fetchRowsV2 ?
|
|
2618
|
+
const v2Request = execution && transport?.fetchRowsV2 ? toServerQueryV22(requestQuery, displaySchema, execution) : void 0;
|
|
2542
2619
|
const request = v2Request ?? toServerQuery2(requestQuery, displaySchema);
|
|
2543
2620
|
if (v2Request)
|
|
2544
2621
|
for (const definition of computed.definitions) {
|
|
@@ -2622,8 +2699,8 @@ function useQueryTable(opts) {
|
|
|
2622
2699
|
try {
|
|
2623
2700
|
validateExecution(query);
|
|
2624
2701
|
if (transport) {
|
|
2625
|
-
if (transport.fetchQueryV3 && transport.queryCapabilities?.version === 3 && (query.grouping || query.select.some((column) => isComputedField4(column.field)) || query.orderBy.some((term) => isComputedField4(term.field)) || query.where.some((term) => ("any" in term ? term.any : [term]).some((predicate) => isComputedField4(predicate.field))))) {
|
|
2626
|
-
const request =
|
|
2702
|
+
if (transport.fetchQueryV3 && transport.queryCapabilities?.version === 3 && (query.grouping || query.select.some((column) => isComputedField4(column.field)) || query.orderBy.some((term) => isComputedField4(term.field)) || query.where.some((term) => ("any" in term ? term.any : [term]).some((predicate) => isComputedField4(predicate.field))) || !transport.fetchRows && !(transport.fetchRowsV2 && opts.computedExecution))) {
|
|
2703
|
+
const request = toQueryRequestV32(
|
|
2627
2704
|
{ ...query, aggregations: [], select: [
|
|
2628
2705
|
...query.select.filter((column) => isComputedField4(column.field)),
|
|
2629
2706
|
...serverRowQuery.select.map((field) => ({ field }))
|
|
@@ -2635,7 +2712,7 @@ function useQueryTable(opts) {
|
|
|
2635
2712
|
);
|
|
2636
2713
|
if (request.diagnostics.length) throw Error(request.diagnostics.join(" "));
|
|
2637
2714
|
const result = await transport.fetchQueryV3(request, ac.signal);
|
|
2638
|
-
|
|
2715
|
+
validateQueryResultV32(result, request, query.grouping ? schema : sourceCatalogue);
|
|
2639
2716
|
if (!cancelled) {
|
|
2640
2717
|
setCommittedFields(request.result.select);
|
|
2641
2718
|
setServerExecution(result.execution);
|
|
@@ -2651,6 +2728,8 @@ function useQueryTable(opts) {
|
|
|
2651
2728
|
return;
|
|
2652
2729
|
}
|
|
2653
2730
|
const useV2 = "version" in serverRowQuery && transport.fetchRowsV2;
|
|
2731
|
+
if (!useV2 && !transport.fetchRows)
|
|
2732
|
+
throw Error("Row execution requires fetchRows, negotiated fetchRowsV2, or negotiated fetchQueryV3.");
|
|
2654
2733
|
if ("diagnostics" in serverRowQuery && Array.isArray(serverRowQuery.diagnostics) && serverRowQuery.diagnostics.length)
|
|
2655
2734
|
throw Error(
|
|
2656
2735
|
serverRowQuery.diagnostics.map((d) => d.message).join(" ")
|
|
@@ -2787,7 +2866,7 @@ function useQueryTable(opts) {
|
|
|
2787
2866
|
const metricExecution = opts.metricExecution ?? (opts.computedExecution ? pageReady && serverExecution ? serverExecution : opts.computedExecution : void 0);
|
|
2788
2867
|
const v3MetricExecution = opts.metricExecution ?? opts.computedExecution;
|
|
2789
2868
|
const metricSourceCatalogue = useMemo9(
|
|
2790
|
-
() =>
|
|
2869
|
+
() => sourceExecutionSchema2(sourceSchema, v3MetricExecution),
|
|
2791
2870
|
[sourceSchema, v3MetricExecution]
|
|
2792
2871
|
);
|
|
2793
2872
|
const executeV3Metrics = useCallback12(async (metricQuery, signal) => {
|
|
@@ -2802,7 +2881,7 @@ function useQueryTable(opts) {
|
|
|
2802
2881
|
let metrics = [];
|
|
2803
2882
|
if (runnable.length) {
|
|
2804
2883
|
const scoped = { ...metricQuery, aggregations: runnable };
|
|
2805
|
-
const request =
|
|
2884
|
+
const request = toQueryRequestV32(
|
|
2806
2885
|
query.grouping ? { ...scoped, grouping: query.grouping } : scoped,
|
|
2807
2886
|
sourceSchema,
|
|
2808
2887
|
capabilities,
|
|
@@ -2811,7 +2890,7 @@ function useQueryTable(opts) {
|
|
|
2811
2890
|
);
|
|
2812
2891
|
if (request.diagnostics.length) throw Error(request.diagnostics.join(" "));
|
|
2813
2892
|
const result = await metricTransport.fetchQueryV3(request, signal);
|
|
2814
|
-
|
|
2893
|
+
validateQueryResultV32(result, request, query.grouping ? schema : metricSourceCatalogue);
|
|
2815
2894
|
metrics = result.metrics;
|
|
2816
2895
|
}
|
|
2817
2896
|
if (!refused.size) return { metrics };
|
|
@@ -2826,7 +2905,7 @@ function useQueryTable(opts) {
|
|
|
2826
2905
|
const previewGrouping = useCallback12(async (draft, signal) => {
|
|
2827
2906
|
if (!active || !storageReady || restoration.loading || restoration.error) throw Error("Wait for query restoration before previewing groups.");
|
|
2828
2907
|
if (!transport?.fetchQueryV3 || !transport.queryCapabilities?.groupedRows || !draft.grouping) throw Error("The server group preview is unavailable.");
|
|
2829
|
-
const request =
|
|
2908
|
+
const request = toQueryRequestV32(
|
|
2830
2909
|
{ ...draft, aggregations: [] },
|
|
2831
2910
|
sourceSchema,
|
|
2832
2911
|
transport.queryCapabilities,
|
|
@@ -2835,7 +2914,7 @@ function useQueryTable(opts) {
|
|
|
2835
2914
|
);
|
|
2836
2915
|
if (request.diagnostics.length) throw Error(request.diagnostics.join(" "));
|
|
2837
2916
|
const result = await transport.fetchQueryV3(request, signal);
|
|
2838
|
-
|
|
2917
|
+
validateQueryResultV32(result, request, groupingModel.resultSchema(draft.grouping.keys, draft.grouping.summaries));
|
|
2839
2918
|
return { rows: result.rows, total: result.total, sourceTotal: result.sourceTotal };
|
|
2840
2919
|
}, [transport, sourceSchema, opts.computedExecution, groupingModel, groupingNow, opts.evaluationNow, active, storageReady, restoration.loading, restoration.error]);
|
|
2841
2920
|
const aggState = useAggregations(
|