gscdump 0.25.14 → 0.26.1
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/core/result.d.mts +29 -0
- package/dist/core/result.mjs +32 -0
- package/dist/index.d.mts +118 -69
- package/dist/index.mjs +215 -30
- package/dist/query/index.d.mts +120 -4
- package/dist/query/index.mjs +201 -54
- package/dist/query/plan.d.mts +79 -12
- package/dist/query/plan.mjs +164 -39
- package/package.json +7 -2
package/dist/query/index.d.mts
CHANGED
|
@@ -169,6 +169,87 @@ declare const impressions: MetricColumn<"impressions">;
|
|
|
169
169
|
declare const ctr: MetricColumn<"ctr">;
|
|
170
170
|
declare const position: MetricColumn<"position">;
|
|
171
171
|
declare const searchType: QueryParam<"searchType">;
|
|
172
|
+
type QueryErrorKind = 'missing-date-range' | 'invalid-row-limit' | 'invalid-start-row' | 'invalid-data-state' | 'invalid-aggregation-type' | 'invalid-builder-state' | 'unsupported-capability' | 'unresolvable-dataset';
|
|
173
|
+
type QueryError = {
|
|
174
|
+
kind: 'missing-date-range';
|
|
175
|
+
message: string;
|
|
176
|
+
} | {
|
|
177
|
+
kind: 'invalid-row-limit';
|
|
178
|
+
value: unknown;
|
|
179
|
+
message: string;
|
|
180
|
+
} | {
|
|
181
|
+
kind: 'invalid-start-row';
|
|
182
|
+
value: unknown;
|
|
183
|
+
message: string;
|
|
184
|
+
} | {
|
|
185
|
+
kind: 'invalid-data-state';
|
|
186
|
+
message: string;
|
|
187
|
+
} | {
|
|
188
|
+
kind: 'invalid-aggregation-type';
|
|
189
|
+
message: string;
|
|
190
|
+
} | {
|
|
191
|
+
kind: 'invalid-builder-state';
|
|
192
|
+
message: string;
|
|
193
|
+
cause?: unknown;
|
|
194
|
+
} | {
|
|
195
|
+
kind: 'unsupported-capability';
|
|
196
|
+
capability: string;
|
|
197
|
+
context: string;
|
|
198
|
+
message: string;
|
|
199
|
+
} | {
|
|
200
|
+
kind: 'unresolvable-dataset';
|
|
201
|
+
dimensions: readonly Dimension[];
|
|
202
|
+
filterDims: readonly Dimension[];
|
|
203
|
+
message: string;
|
|
204
|
+
};
|
|
205
|
+
declare const queryErrors: {
|
|
206
|
+
readonly missingDateRange: () => QueryError;
|
|
207
|
+
readonly invalidRowLimit: (value: unknown) => QueryError;
|
|
208
|
+
readonly invalidStartRow: (value: unknown) => QueryError;
|
|
209
|
+
readonly hourDimensionRequiresHourlyState: () => QueryError;
|
|
210
|
+
readonly hourlyStateRequiresHourDimension: () => QueryError;
|
|
211
|
+
readonly byPropertyUnsupportedSearchType: () => QueryError;
|
|
212
|
+
readonly byPropertyNotAllowedWithPage: () => QueryError;
|
|
213
|
+
readonly byNewsShowcaseRequiresSearchType: () => QueryError;
|
|
214
|
+
readonly byNewsShowcaseNotAllowedWithPage: () => QueryError;
|
|
215
|
+
readonly byNewsShowcaseRequiresShowcaseFilter: () => QueryError;
|
|
216
|
+
readonly invalidBuilderState: (cause?: unknown) => QueryError;
|
|
217
|
+
readonly unsupportedCapability: (capability: string, context: string) => QueryError;
|
|
218
|
+
readonly unresolvableDataset: (dimensions: readonly Dimension[], filterDims?: readonly Dimension[]) => QueryError;
|
|
219
|
+
};
|
|
220
|
+
declare function isQueryError(value: unknown): value is QueryError;
|
|
221
|
+
/** The human-readable rendering of a `QueryError`, for logs and string sinks. */
|
|
222
|
+
declare function formatQueryError(error: QueryError): string;
|
|
223
|
+
/**
|
|
224
|
+
* Thrown when a query needs a planner capability (regex pushdown, comparison
|
|
225
|
+
* joins, multi-dataset reads) the target engine lacks. Engines catch it to fall
|
|
226
|
+
* back to the live GSC API. Carries the typed `queryError` value so a caller can
|
|
227
|
+
* read the modelled failure instead of parsing the message.
|
|
228
|
+
*/
|
|
229
|
+
declare class UnsupportedLogicalCapabilityError extends Error {
|
|
230
|
+
readonly queryError: Extract<QueryError, {
|
|
231
|
+
kind: 'unsupported-capability';
|
|
232
|
+
}>;
|
|
233
|
+
constructor(capability: string, context: string);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Thrown when a query's grouped + filtered dimensions span more than one stored
|
|
237
|
+
* dataset. Replaces the resolver's raw "unknown column" error so hosts can map
|
|
238
|
+
* it to a 4xx instead of leaking an opaque 500. Carries the typed `queryError`.
|
|
239
|
+
*/
|
|
240
|
+
declare class UnresolvableDatasetError extends Error {
|
|
241
|
+
readonly queryError: Extract<QueryError, {
|
|
242
|
+
kind: 'unresolvable-dataset';
|
|
243
|
+
}>;
|
|
244
|
+
constructor(dimensions: readonly Dimension[], filterDims?: readonly Dimension[]);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Re-raises a `QueryError` value as an `Error`, preserving the historical class
|
|
248
|
+
* identity for the two errors engines match on by name (`UnresolvableDatasetError`,
|
|
249
|
+
* `UnsupportedLogicalCapabilityError`). Pairs with `unwrapResult` so a
|
|
250
|
+
* `fooResult(): Result<A, QueryError>` core can back a throwing `foo()`.
|
|
251
|
+
*/
|
|
252
|
+
declare function queryErrorToException(error: QueryError): Error;
|
|
172
253
|
declare function eq<D extends Dimension, V extends DimensionValueMap[D]>(column: Column<D>, value: V): Filter<Record<D, V>>;
|
|
173
254
|
declare function eq<P extends QueryParamName, V extends QueryParamValueMap[P]>(param: QueryParam<P>, value: V): Filter<Record<P, V>>;
|
|
174
255
|
declare function ne<D extends Dimension>(column: Column<D>, value: DimensionValueMap[D]): Filter<object>;
|
|
@@ -191,6 +272,15 @@ declare function lt(column: Column<'date'>, value: string): Filter<object>;
|
|
|
191
272
|
declare function between<M extends Metric>(column: MetricColumn<M>, start: number, end: number): Filter<object>;
|
|
192
273
|
declare function between(column: Column<'date'>, start: string, end: string): Filter<object>;
|
|
193
274
|
declare function topLevel(column: Column<'page'>): Filter<object>;
|
|
275
|
+
interface Ok<A> {
|
|
276
|
+
readonly ok: true;
|
|
277
|
+
readonly value: A;
|
|
278
|
+
}
|
|
279
|
+
interface Err<E> {
|
|
280
|
+
readonly ok: false;
|
|
281
|
+
readonly error: E;
|
|
282
|
+
}
|
|
283
|
+
type Result<A, E> = Ok<A> | Err<E>;
|
|
194
284
|
type LogicalDataset = TableName;
|
|
195
285
|
type ComparisonFilter = 'new' | 'lost' | 'improving' | 'declining';
|
|
196
286
|
interface PlannerCapabilities {
|
|
@@ -248,14 +338,31 @@ interface LogicalComparisonPlan {
|
|
|
248
338
|
previous: LogicalQueryPlan;
|
|
249
339
|
comparisonFilter?: ComparisonFilter;
|
|
250
340
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
341
|
+
/**
|
|
342
|
+
* Errors-as-values core: builds the logical plan or returns a typed `QueryError`
|
|
343
|
+
* for every modelled failure (missing date range, a regex filter on an engine
|
|
344
|
+
* without regex pushdown, a cross-dimension query with no stored home).
|
|
345
|
+
* `buildLogicalPlan` is the throwing wrapper for call sites that prefer exceptions.
|
|
346
|
+
*/
|
|
347
|
+
declare function buildLogicalPlanResult(state: BuilderState, capabilities?: PlannerCapabilities): Result<LogicalQueryPlan, QueryError>;
|
|
254
348
|
declare function buildLogicalPlan(state: BuilderState, capabilities?: PlannerCapabilities): LogicalQueryPlan;
|
|
349
|
+
/**
|
|
350
|
+
* Errors-as-values core for the comparison plan: returns a typed `QueryError`
|
|
351
|
+
* when the engine lacks the comparison-join or multi-dataset capability the
|
|
352
|
+
* paired queries need, or when either side fails to plan.
|
|
353
|
+
*/
|
|
354
|
+
declare function buildLogicalComparisonPlanResult(current: BuilderState, previous: BuilderState, capabilities?: PlannerCapabilities, comparisonFilter?: ComparisonFilter): Result<LogicalComparisonPlan, QueryError>;
|
|
255
355
|
declare function buildLogicalComparisonPlan(current: BuilderState, previous: BuilderState, capabilities?: PlannerCapabilities, comparisonFilter?: ComparisonFilter): LogicalComparisonPlan;
|
|
256
356
|
declare function isJsonFilter(value: unknown): value is JsonFilter;
|
|
257
357
|
declare function parseJsonFilter(json: JsonFilter): Filter<any>;
|
|
258
358
|
declare function normalizeFilter(input?: FilterInput): Filter<any> | undefined;
|
|
359
|
+
/**
|
|
360
|
+
* Errors-as-values core for {@link normalizeBuilderState}: returns an
|
|
361
|
+
* `invalid-builder-state` `QueryError` when the untrusted partner-API body is
|
|
362
|
+
* not an object, instead of throwing. Receive-edge parse, so hosts can map a bad
|
|
363
|
+
* body to a 4xx.
|
|
364
|
+
*/
|
|
365
|
+
declare function normalizeBuilderStateResult(state: unknown): Result<BuilderState, QueryError>;
|
|
259
366
|
declare function normalizeBuilderState(state: unknown): BuilderState;
|
|
260
367
|
declare function extractDateRange(input?: FilterInput): {
|
|
261
368
|
startDate?: string;
|
|
@@ -270,7 +377,16 @@ declare function extractSpecialOperatorFilters(input?: FilterInput): InternalFil
|
|
|
270
377
|
* don't reach the engine.
|
|
271
378
|
*/
|
|
272
379
|
declare function extractSearchType(state: BuilderState | undefined | null): SearchType | undefined;
|
|
380
|
+
/**
|
|
381
|
+
* Errors-as-values core: turns a `BuilderState` into a GSC API request body or
|
|
382
|
+
* returns a typed `QueryError` for every modelled bad-query case (missing date
|
|
383
|
+
* range, out-of-range row limit / start row, hour/dataState mismatch, illegal
|
|
384
|
+
* aggregationType combination). `resolveToBody` is the throwing wrapper over this
|
|
385
|
+
* for `.toBody()` and the live-API client paths.
|
|
386
|
+
*/
|
|
387
|
+
declare function resolveToBodyResult(state: BuilderState): Result<GscSearchAnalyticsRequest, QueryError>;
|
|
388
|
+
declare function resolveToBody(state: BuilderState): GscSearchAnalyticsRequest;
|
|
273
389
|
declare function currentPstDate(): string;
|
|
274
390
|
declare function today(): string;
|
|
275
391
|
declare function daysAgo(n: number): string;
|
|
276
|
-
export { type BuilderState, type Column, type ComparisonFilter, Countries, type Country, type Device, Devices, type Dimension, type DimensionValueMap, type Filter, type FilterInput, type GSCQueryBuilder, type GSCResult, type GSCRow, type InternalFilter, type JsonFilter, type JsonInternalFilter, type LogicalComparisonPlan, type LogicalDataset, type LogicalDimensionFilter, type LogicalMetricFilter, type LogicalQueryPlan, type Metric, type MetricColumn, type PlannerCapabilities, type QueryParam, type QueryParamName, type QueryParamValueMap, type SearchType, SearchTypes, UnsupportedLogicalCapabilityError, and, between, buildLogicalComparisonPlan, buildLogicalPlan, clicks, contains, country, ctr, currentPstDate, date, daysAgo, device, eq, extractDateRange, extractMetricFilters, extractSearchType, extractSpecialOperatorFilters, gsc, gt, gte, hour, impressions, inArray, isJsonFilter, like, lt, lte, ne, normalizeBuilderState, normalizeFilter, not, notRegex, or, page, parseJsonFilter, position, query, queryCanonical, regex, searchAppearance, searchType, today, topLevel };
|
|
392
|
+
export { type BuilderState, type Column, type ComparisonFilter, Countries, type Country, type Device, Devices, type Dimension, type DimensionValueMap, type Filter, type FilterInput, type GSCQueryBuilder, type GSCResult, type GSCRow, type InternalFilter, type JsonFilter, type JsonInternalFilter, type LogicalComparisonPlan, type LogicalDataset, type LogicalDimensionFilter, type LogicalMetricFilter, type LogicalQueryPlan, type Metric, type MetricColumn, type PlannerCapabilities, QueryError, QueryErrorKind, type QueryParam, type QueryParamName, type QueryParamValueMap, type SearchType, SearchTypes, UnresolvableDatasetError, UnsupportedLogicalCapabilityError, and, between, buildLogicalComparisonPlan, buildLogicalComparisonPlanResult, buildLogicalPlan, buildLogicalPlanResult, clicks, contains, country, ctr, currentPstDate, date, daysAgo, device, eq, extractDateRange, extractMetricFilters, extractSearchType, extractSpecialOperatorFilters, formatQueryError, gsc, gt, gte, hour, impressions, inArray, isJsonFilter, isQueryError, like, lt, lte, ne, normalizeBuilderState, normalizeBuilderStateResult, normalizeFilter, not, notRegex, or, page, parseJsonFilter, position, query, queryCanonical, queryErrorToException, queryErrors, regex, resolveToBody, resolveToBodyResult, searchAppearance, searchType, today, topLevel };
|
package/dist/query/index.mjs
CHANGED
|
@@ -29,6 +29,22 @@ function toIsoDate(d) {
|
|
|
29
29
|
function addDays(dateStr, n) {
|
|
30
30
|
return toIsoDate(new Date(Date.parse(`${dateStr}T00:00:00Z`) + n * MS_PER_DAY));
|
|
31
31
|
}
|
|
32
|
+
function ok(value) {
|
|
33
|
+
return {
|
|
34
|
+
ok: true,
|
|
35
|
+
value
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function err(error) {
|
|
39
|
+
return {
|
|
40
|
+
ok: false,
|
|
41
|
+
error
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function unwrapResult(result, toError) {
|
|
45
|
+
if (result.ok) return result.value;
|
|
46
|
+
throw toError(result.error);
|
|
47
|
+
}
|
|
32
48
|
var countries_default = [
|
|
33
49
|
{
|
|
34
50
|
"name": "Afghanistan",
|
|
@@ -1539,6 +1555,142 @@ const SearchTypes = {
|
|
|
1539
1555
|
GOOGLE_NEWS: "googleNews"
|
|
1540
1556
|
};
|
|
1541
1557
|
const Countries = Object.fromEntries(countries_default.map((c) => [c["alpha-3"], c["alpha-3"].toLowerCase()]));
|
|
1558
|
+
const TIME_AXIS_DIMENSIONS$1 = new Set(["date", "hour"]);
|
|
1559
|
+
const queryErrors = {
|
|
1560
|
+
missingDateRange() {
|
|
1561
|
+
return {
|
|
1562
|
+
kind: "missing-date-range",
|
|
1563
|
+
message: "Date range required: use .where(between(date, start, end)) or .where(and(gte(date, start), lte(date, end)))"
|
|
1564
|
+
};
|
|
1565
|
+
},
|
|
1566
|
+
invalidRowLimit(value) {
|
|
1567
|
+
return {
|
|
1568
|
+
kind: "invalid-row-limit",
|
|
1569
|
+
value,
|
|
1570
|
+
message: `rowLimit must be a positive integer, got ${value}`
|
|
1571
|
+
};
|
|
1572
|
+
},
|
|
1573
|
+
invalidStartRow(value) {
|
|
1574
|
+
return {
|
|
1575
|
+
kind: "invalid-start-row",
|
|
1576
|
+
value,
|
|
1577
|
+
message: `startRow must be a non-negative integer, got ${value}`
|
|
1578
|
+
};
|
|
1579
|
+
},
|
|
1580
|
+
hourDimensionRequiresHourlyState() {
|
|
1581
|
+
return {
|
|
1582
|
+
kind: "invalid-data-state",
|
|
1583
|
+
message: "hour dimension requires dataState: \"hourly_all\""
|
|
1584
|
+
};
|
|
1585
|
+
},
|
|
1586
|
+
hourlyStateRequiresHourDimension() {
|
|
1587
|
+
return {
|
|
1588
|
+
kind: "invalid-data-state",
|
|
1589
|
+
message: "dataState: \"hourly_all\" requires grouping by hour dimension"
|
|
1590
|
+
};
|
|
1591
|
+
},
|
|
1592
|
+
byPropertyUnsupportedSearchType() {
|
|
1593
|
+
return {
|
|
1594
|
+
kind: "invalid-aggregation-type",
|
|
1595
|
+
message: "aggregationType: \"byProperty\" is not supported for type \"discover\" or \"googleNews\""
|
|
1596
|
+
};
|
|
1597
|
+
},
|
|
1598
|
+
byPropertyNotAllowedWithPage() {
|
|
1599
|
+
return {
|
|
1600
|
+
kind: "invalid-aggregation-type",
|
|
1601
|
+
message: "aggregationType: \"byProperty\" is not allowed when grouping or filtering by page"
|
|
1602
|
+
};
|
|
1603
|
+
},
|
|
1604
|
+
byNewsShowcaseRequiresSearchType() {
|
|
1605
|
+
return {
|
|
1606
|
+
kind: "invalid-aggregation-type",
|
|
1607
|
+
message: "aggregationType: \"byNewsShowcasePanel\" requires type \"discover\" or \"googleNews\""
|
|
1608
|
+
};
|
|
1609
|
+
},
|
|
1610
|
+
byNewsShowcaseNotAllowedWithPage() {
|
|
1611
|
+
return {
|
|
1612
|
+
kind: "invalid-aggregation-type",
|
|
1613
|
+
message: "aggregationType: \"byNewsShowcasePanel\" is not allowed when grouping or filtering by page"
|
|
1614
|
+
};
|
|
1615
|
+
},
|
|
1616
|
+
byNewsShowcaseRequiresShowcaseFilter() {
|
|
1617
|
+
return {
|
|
1618
|
+
kind: "invalid-aggregation-type",
|
|
1619
|
+
message: "aggregationType: \"byNewsShowcasePanel\" requires a searchAppearance equals \"NEWS_SHOWCASE\" filter and no other searchAppearance filter"
|
|
1620
|
+
};
|
|
1621
|
+
},
|
|
1622
|
+
invalidBuilderState(cause) {
|
|
1623
|
+
return {
|
|
1624
|
+
kind: "invalid-builder-state",
|
|
1625
|
+
cause,
|
|
1626
|
+
message: "Invalid state"
|
|
1627
|
+
};
|
|
1628
|
+
},
|
|
1629
|
+
unsupportedCapability(capability, context) {
|
|
1630
|
+
return {
|
|
1631
|
+
kind: "unsupported-capability",
|
|
1632
|
+
capability,
|
|
1633
|
+
context,
|
|
1634
|
+
message: `${context} requires ${capability} capability`
|
|
1635
|
+
};
|
|
1636
|
+
},
|
|
1637
|
+
unresolvableDataset(dimensions, filterDims = []) {
|
|
1638
|
+
const grouped = dimensions.filter((d) => !TIME_AXIS_DIMENSIONS$1.has(d));
|
|
1639
|
+
const filtered = filterDims.filter((d) => !TIME_AXIS_DIMENSIONS$1.has(d));
|
|
1640
|
+
return {
|
|
1641
|
+
kind: "unresolvable-dataset",
|
|
1642
|
+
dimensions,
|
|
1643
|
+
filterDims,
|
|
1644
|
+
message: `Cannot resolve a [${grouped.join(", ")}] breakdown filtered by [${filtered.join(", ")}] from stored data: these dimensions live in separate per-dimension tables. Only the live GSC API computes cross-dimension aggregates.`
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
};
|
|
1648
|
+
const QUERY_ERROR_KINDS = new Set([
|
|
1649
|
+
"missing-date-range",
|
|
1650
|
+
"invalid-row-limit",
|
|
1651
|
+
"invalid-start-row",
|
|
1652
|
+
"invalid-data-state",
|
|
1653
|
+
"invalid-aggregation-type",
|
|
1654
|
+
"invalid-builder-state",
|
|
1655
|
+
"unsupported-capability",
|
|
1656
|
+
"unresolvable-dataset"
|
|
1657
|
+
]);
|
|
1658
|
+
function isQueryError(value) {
|
|
1659
|
+
return typeof value === "object" && value !== null && QUERY_ERROR_KINDS.has(value.kind) && typeof value.message === "string";
|
|
1660
|
+
}
|
|
1661
|
+
function formatQueryError(error) {
|
|
1662
|
+
return error.message;
|
|
1663
|
+
}
|
|
1664
|
+
var UnsupportedLogicalCapabilityError = class extends Error {
|
|
1665
|
+
queryError;
|
|
1666
|
+
constructor(capability, context) {
|
|
1667
|
+
const error = queryErrors.unsupportedCapability(capability, context);
|
|
1668
|
+
super(error.message);
|
|
1669
|
+
this.name = "UnsupportedLogicalCapabilityError";
|
|
1670
|
+
this.queryError = error;
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
var UnresolvableDatasetError = class extends Error {
|
|
1674
|
+
queryError;
|
|
1675
|
+
constructor(dimensions, filterDims = []) {
|
|
1676
|
+
const error = queryErrors.unresolvableDataset(dimensions, filterDims);
|
|
1677
|
+
super(error.message);
|
|
1678
|
+
this.name = "UnresolvableDatasetError";
|
|
1679
|
+
this.queryError = error;
|
|
1680
|
+
}
|
|
1681
|
+
};
|
|
1682
|
+
function queryErrorToException(error) {
|
|
1683
|
+
switch (error.kind) {
|
|
1684
|
+
case "unsupported-capability": return new UnsupportedLogicalCapabilityError(error.capability, error.context);
|
|
1685
|
+
case "unresolvable-dataset": return new UnresolvableDatasetError(error.dimensions, error.filterDims);
|
|
1686
|
+
default: {
|
|
1687
|
+
const exception = new Error(error.message);
|
|
1688
|
+
if ("cause" in error && error.cause !== void 0) exception.cause = error.cause;
|
|
1689
|
+
exception.queryError = error;
|
|
1690
|
+
return exception;
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1542
1694
|
const DATE_OPERATORS = [
|
|
1543
1695
|
"gte",
|
|
1544
1696
|
"gt",
|
|
@@ -1641,8 +1793,8 @@ function normalizeFilter(input) {
|
|
|
1641
1793
|
if (isWireFilter(input)) return convertWireGroup(input) ?? void 0;
|
|
1642
1794
|
return input;
|
|
1643
1795
|
}
|
|
1644
|
-
function
|
|
1645
|
-
if (!state || typeof state !== "object")
|
|
1796
|
+
function normalizeBuilderStateResult(state) {
|
|
1797
|
+
if (!state || typeof state !== "object") return err(queryErrors.invalidBuilderState(state));
|
|
1646
1798
|
const s = state;
|
|
1647
1799
|
const normalized = {
|
|
1648
1800
|
dimensions: s.dimensions,
|
|
@@ -1655,7 +1807,10 @@ function normalizeBuilderState(state) {
|
|
|
1655
1807
|
aggregationType: s.aggregationType
|
|
1656
1808
|
};
|
|
1657
1809
|
if (typeof s.searchType === "string" && KNOWN_SEARCH_TYPES.has(s.searchType)) normalized.searchType = s.searchType;
|
|
1658
|
-
return normalized;
|
|
1810
|
+
return ok(normalized);
|
|
1811
|
+
}
|
|
1812
|
+
function normalizeBuilderState(state) {
|
|
1813
|
+
return unwrapResult(normalizeBuilderStateResult(state), queryErrorToException);
|
|
1659
1814
|
}
|
|
1660
1815
|
function extractSpecialFilters(filter) {
|
|
1661
1816
|
if (!filter) return {};
|
|
@@ -1735,9 +1890,9 @@ function extractSearchType(state) {
|
|
|
1735
1890
|
if (typeof raw !== "string" || raw.length === 0) return void 0;
|
|
1736
1891
|
return KNOWN_SEARCH_TYPES.has(raw) ? raw : void 0;
|
|
1737
1892
|
}
|
|
1738
|
-
function
|
|
1893
|
+
function resolveToBodyResult(state) {
|
|
1739
1894
|
const { startDate, endDate, searchType, dimensionFilter } = extractSpecialFilters(state.filter);
|
|
1740
|
-
if (!startDate || !endDate)
|
|
1895
|
+
if (!startDate || !endDate) return err(queryErrors.missingDateRange());
|
|
1741
1896
|
const body = {
|
|
1742
1897
|
dimensions: state.dimensions,
|
|
1743
1898
|
startDate,
|
|
@@ -1746,16 +1901,16 @@ function resolveToBody(state) {
|
|
|
1746
1901
|
const resolvedType = state.searchType ?? searchType;
|
|
1747
1902
|
if (resolvedType) body.type = resolvedType;
|
|
1748
1903
|
if (state.rowLimit !== void 0) {
|
|
1749
|
-
if (!Number.isInteger(state.rowLimit) || state.rowLimit < 1)
|
|
1904
|
+
if (!Number.isInteger(state.rowLimit) || state.rowLimit < 1) return err(queryErrors.invalidRowLimit(state.rowLimit));
|
|
1750
1905
|
body.rowLimit = state.rowLimit;
|
|
1751
1906
|
}
|
|
1752
1907
|
if (state.startRow !== void 0) {
|
|
1753
|
-
if (!Number.isInteger(state.startRow) || state.startRow < 0)
|
|
1908
|
+
if (!Number.isInteger(state.startRow) || state.startRow < 0) return err(queryErrors.invalidStartRow(state.startRow));
|
|
1754
1909
|
if (state.startRow > 0) body.startRow = state.startRow;
|
|
1755
1910
|
}
|
|
1756
1911
|
const hasHour = state.dimensions?.includes("hour");
|
|
1757
|
-
if (hasHour && state.dataState !== "hourly_all")
|
|
1758
|
-
if (state.dataState === "hourly_all" && !hasHour)
|
|
1912
|
+
if (hasHour && state.dataState !== "hourly_all") return err(queryErrors.hourDimensionRequiresHourlyState());
|
|
1913
|
+
if (state.dataState === "hourly_all" && !hasHour) return err(queryErrors.hourlyStateRequiresHourDimension());
|
|
1759
1914
|
if (state.dataState) body.dataState = state.dataState;
|
|
1760
1915
|
const filterGroups = resolveFilter(dimensionFilter);
|
|
1761
1916
|
if (filterGroups.length > 0) body.dimensionFilterGroups = filterGroups;
|
|
@@ -1764,20 +1919,23 @@ function resolveToBody(state) {
|
|
|
1764
1919
|
const apiLeafFilters = filterGroups.flatMap((g) => g.filters ?? []);
|
|
1765
1920
|
const filtersByPage = apiLeafFilters.some((f) => f.dimension === "page");
|
|
1766
1921
|
if (state.aggregationType === "byProperty") {
|
|
1767
|
-
if (body.type === "discover" || body.type === "googleNews")
|
|
1768
|
-
if (groupsByPage || filtersByPage)
|
|
1922
|
+
if (body.type === "discover" || body.type === "googleNews") return err(queryErrors.byPropertyUnsupportedSearchType());
|
|
1923
|
+
if (groupsByPage || filtersByPage) return err(queryErrors.byPropertyNotAllowedWithPage());
|
|
1769
1924
|
}
|
|
1770
1925
|
if (state.aggregationType === "byNewsShowcasePanel") {
|
|
1771
|
-
if (body.type !== "discover" && body.type !== "googleNews")
|
|
1772
|
-
if (groupsByPage || filtersByPage)
|
|
1926
|
+
if (body.type !== "discover" && body.type !== "googleNews") return err(queryErrors.byNewsShowcaseRequiresSearchType());
|
|
1927
|
+
if (groupsByPage || filtersByPage) return err(queryErrors.byNewsShowcaseNotAllowedWithPage());
|
|
1773
1928
|
const saFilters = apiLeafFilters.filter((f) => f.dimension === "searchAppearance");
|
|
1774
1929
|
const hasNewsShowcase = saFilters.some((f) => f.operator === "equals" && f.expression === "NEWS_SHOWCASE");
|
|
1775
1930
|
const hasOther = saFilters.some((f) => !(f.operator === "equals" && f.expression === "NEWS_SHOWCASE"));
|
|
1776
|
-
if (!hasNewsShowcase || hasOther)
|
|
1931
|
+
if (!hasNewsShowcase || hasOther) return err(queryErrors.byNewsShowcaseRequiresShowcaseFilter());
|
|
1777
1932
|
}
|
|
1778
1933
|
body.aggregationType = state.aggregationType;
|
|
1779
1934
|
}
|
|
1780
|
-
return body;
|
|
1935
|
+
return ok(body);
|
|
1936
|
+
}
|
|
1937
|
+
function resolveToBody(state) {
|
|
1938
|
+
return unwrapResult(resolveToBodyResult(state), queryErrorToException);
|
|
1781
1939
|
}
|
|
1782
1940
|
function isApiFilter(f) {
|
|
1783
1941
|
return !isMetricOperator(f.operator) && !isSpecialOperator(f.operator);
|
|
@@ -2031,12 +2189,6 @@ function between(column, start, end) {
|
|
|
2031
2189
|
function topLevel(column) {
|
|
2032
2190
|
return leafFilter(column.dimension, "topLevel", "");
|
|
2033
2191
|
}
|
|
2034
|
-
var UnsupportedLogicalCapabilityError = class extends Error {
|
|
2035
|
-
constructor(capability, context) {
|
|
2036
|
-
super(`${context} requires ${capability} capability`);
|
|
2037
|
-
this.name = "UnsupportedLogicalCapabilityError";
|
|
2038
|
-
}
|
|
2039
|
-
};
|
|
2040
2192
|
function collectInternalFilters(filter) {
|
|
2041
2193
|
if (!filter || !("_filters" in filter)) return [];
|
|
2042
2194
|
const flat = filter._filters;
|
|
@@ -2079,17 +2231,6 @@ function isDatasetResolvable(dimensions, filterDims = []) {
|
|
|
2079
2231
|
if (needed.size === 0) return true;
|
|
2080
2232
|
return RESOLVABLE_DIMENSION_FAMILIES.some((family) => [...needed].every((d) => family.has(d)));
|
|
2081
2233
|
}
|
|
2082
|
-
var UnresolvableDatasetError = class extends Error {
|
|
2083
|
-
constructor(dimensions, filterDims = []) {
|
|
2084
|
-
const grouped = dimensions.filter((d) => !TIME_AXIS_DIMENSIONS.has(d));
|
|
2085
|
-
const filtered = filterDims.filter((d) => !TIME_AXIS_DIMENSIONS.has(d));
|
|
2086
|
-
super(`Cannot resolve a [${grouped.join(", ")}] breakdown filtered by [${filtered.join(", ")}] from stored data: these dimensions live in separate per-dimension tables. Only the live GSC API computes cross-dimension aggregates.`);
|
|
2087
|
-
this.name = "UnresolvableDatasetError";
|
|
2088
|
-
}
|
|
2089
|
-
};
|
|
2090
|
-
function requireCapability(capabilities, capability, enabled, context) {
|
|
2091
|
-
if (enabled && !capabilities?.[capability]) throw new UnsupportedLogicalCapabilityError(capability, context);
|
|
2092
|
-
}
|
|
2093
2234
|
function isDimensionLeaf(filter) {
|
|
2094
2235
|
if (isMetric(filter.dimension)) return false;
|
|
2095
2236
|
if (filter.dimension === "date" && isDateOperator(filter.operator)) return false;
|
|
@@ -2105,20 +2246,19 @@ function toLogicalDimensionFilter(filter) {
|
|
|
2105
2246
|
expression2: filter.expression2
|
|
2106
2247
|
};
|
|
2107
2248
|
}
|
|
2108
|
-
function buildDimensionFilterTree(filter
|
|
2249
|
+
function buildDimensionFilterTree(filter) {
|
|
2109
2250
|
if (!filter || !("_filters" in filter)) return void 0;
|
|
2110
2251
|
const groupType = filter._groupType ?? "and";
|
|
2111
2252
|
const children = [];
|
|
2112
2253
|
for (const f of filter._filters) {
|
|
2113
2254
|
if (!isDimensionLeaf(f)) continue;
|
|
2114
|
-
requireCapability(capabilities, "regex", isRegexOperator(f.operator), "logical plan");
|
|
2115
2255
|
children.push({
|
|
2116
2256
|
kind: "leaf",
|
|
2117
2257
|
filter: toLogicalDimensionFilter(f)
|
|
2118
2258
|
});
|
|
2119
2259
|
}
|
|
2120
2260
|
for (const g of filter._nestedGroups ?? []) {
|
|
2121
|
-
const sub = buildDimensionFilterTree(g
|
|
2261
|
+
const sub = buildDimensionFilterTree(g);
|
|
2122
2262
|
if (sub) children.push(sub);
|
|
2123
2263
|
}
|
|
2124
2264
|
if (children.length === 0) return void 0;
|
|
@@ -2129,11 +2269,12 @@ function buildDimensionFilterTree(filter, capabilities) {
|
|
|
2129
2269
|
children
|
|
2130
2270
|
};
|
|
2131
2271
|
}
|
|
2132
|
-
function
|
|
2272
|
+
function buildLogicalPlanResult(state, capabilities = {}) {
|
|
2133
2273
|
const normalizedFilter = normalizeFilter(state.filter);
|
|
2134
2274
|
const { startDate, endDate } = extractDateRange(normalizedFilter);
|
|
2135
|
-
if (!startDate || !endDate)
|
|
2275
|
+
if (!startDate || !endDate) return err(queryErrors.missingDateRange());
|
|
2136
2276
|
const allFilters = collectInternalFilters(normalizedFilter);
|
|
2277
|
+
if (!capabilities.regex && allFilters.some((f) => isDimensionLeaf(f) && isRegexOperator(f.operator))) return err(queryErrors.unsupportedCapability("regex", "logical plan"));
|
|
2137
2278
|
const metricFilters = extractMetricFilters(normalizedFilter);
|
|
2138
2279
|
const specialFilters = extractSpecialOperatorFilters(normalizedFilter);
|
|
2139
2280
|
const prefilters = extractMetricFilters(normalizeFilter(state.prefilter));
|
|
@@ -2147,19 +2288,17 @@ function buildLogicalPlan(state, capabilities = {}) {
|
|
|
2147
2288
|
queryParams[filter.dimension] = filter.expression;
|
|
2148
2289
|
continue;
|
|
2149
2290
|
}
|
|
2150
|
-
const operator = filter.operator;
|
|
2151
|
-
requireCapability(capabilities, "regex", isRegexOperator(operator), "logical plan");
|
|
2152
2291
|
dimensionFilters.push({
|
|
2153
2292
|
dimension: filter.dimension,
|
|
2154
|
-
operator,
|
|
2293
|
+
operator: filter.operator,
|
|
2155
2294
|
expression: filter.expression,
|
|
2156
2295
|
expression2: filter.expression2
|
|
2157
2296
|
});
|
|
2158
2297
|
}
|
|
2159
|
-
const dimensionFilterTree = buildDimensionFilterTree(normalizedFilter
|
|
2298
|
+
const dimensionFilterTree = buildDimensionFilterTree(normalizedFilter);
|
|
2160
2299
|
const filterDims = dimensionFilters.map((filter) => filter.dimension);
|
|
2161
|
-
if (!isDatasetResolvable(state.dimensions, filterDims))
|
|
2162
|
-
return {
|
|
2300
|
+
if (!isDatasetResolvable(state.dimensions, filterDims)) return err(queryErrors.unresolvableDataset(state.dimensions, filterDims));
|
|
2301
|
+
return ok({
|
|
2163
2302
|
dataset: inferDataset(state.dimensions, filterDims),
|
|
2164
2303
|
dimensions: [...state.dimensions],
|
|
2165
2304
|
groupByDimensions: state.dimensions.filter((d) => d !== "date"),
|
|
@@ -2193,18 +2332,26 @@ function buildLogicalPlan(state, capabilities = {}) {
|
|
|
2193
2332
|
orderBy: state.orderBy,
|
|
2194
2333
|
rowLimit: state.rowLimit,
|
|
2195
2334
|
startRow: state.startRow
|
|
2196
|
-
};
|
|
2335
|
+
});
|
|
2197
2336
|
}
|
|
2198
|
-
function
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2337
|
+
function buildLogicalPlan(state, capabilities = {}) {
|
|
2338
|
+
return unwrapResult(buildLogicalPlanResult(state, capabilities), queryErrorToException);
|
|
2339
|
+
}
|
|
2340
|
+
function buildLogicalComparisonPlanResult(current, previous, capabilities = {}, comparisonFilter) {
|
|
2341
|
+
if (!capabilities.comparisonJoin) return err(queryErrors.unsupportedCapability("comparisonJoin", "logical comparison plan"));
|
|
2342
|
+
const currentResult = buildLogicalPlanResult(current, capabilities);
|
|
2343
|
+
if (!currentResult.ok) return currentResult;
|
|
2344
|
+
const previousResult = buildLogicalPlanResult(previous, capabilities);
|
|
2345
|
+
if (!previousResult.ok) return previousResult;
|
|
2346
|
+
if (currentResult.value.dataset !== previousResult.value.dataset && !capabilities.multiDataset) return err(queryErrors.unsupportedCapability("multiDataset", "logical comparison plan"));
|
|
2347
|
+
return ok({
|
|
2348
|
+
current: currentResult.value,
|
|
2349
|
+
previous: previousResult.value,
|
|
2206
2350
|
comparisonFilter
|
|
2207
|
-
};
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
function buildLogicalComparisonPlan(current, previous, capabilities = {}, comparisonFilter) {
|
|
2354
|
+
return unwrapResult(buildLogicalComparisonPlanResult(current, previous, capabilities, comparisonFilter), queryErrorToException);
|
|
2208
2355
|
}
|
|
2209
2356
|
function today() {
|
|
2210
2357
|
return currentPstDate();
|
|
@@ -2212,4 +2359,4 @@ function today() {
|
|
|
2212
2359
|
function daysAgo(n) {
|
|
2213
2360
|
return daysAgoPst(n);
|
|
2214
2361
|
}
|
|
2215
|
-
export { Countries, Devices, SearchTypes, UnsupportedLogicalCapabilityError, and, between, buildLogicalComparisonPlan, buildLogicalPlan, clicks, contains, country, ctr, currentPstDate, date, daysAgo, device, eq, extractDateRange, extractMetricFilters, extractSearchType, extractSpecialOperatorFilters, gsc, gt, gte, hour, impressions, inArray, isJsonFilter, like, lt, lte, ne, normalizeBuilderState, normalizeFilter, not, notRegex, or, page, parseJsonFilter, position, query, queryCanonical, regex, searchAppearance, searchType, today, topLevel };
|
|
2362
|
+
export { Countries, Devices, SearchTypes, UnresolvableDatasetError, UnsupportedLogicalCapabilityError, and, between, buildLogicalComparisonPlan, buildLogicalComparisonPlanResult, buildLogicalPlan, buildLogicalPlanResult, clicks, contains, country, ctr, currentPstDate, date, daysAgo, device, eq, extractDateRange, extractMetricFilters, extractSearchType, extractSpecialOperatorFilters, formatQueryError, gsc, gt, gte, hour, impressions, inArray, isJsonFilter, isQueryError, like, lt, lte, ne, normalizeBuilderState, normalizeBuilderStateResult, normalizeFilter, not, notRegex, or, page, parseJsonFilter, position, query, queryCanonical, queryErrorToException, queryErrors, regex, resolveToBody, resolveToBodyResult, searchAppearance, searchType, today, topLevel };
|
package/dist/query/plan.d.mts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { TableName } from "@gscdump/contracts";
|
|
2
2
|
type GscDataState = 'final' | 'all' | 'hourly_all';
|
|
3
3
|
type GscAggregationType = 'auto' | 'byPage' | 'byProperty' | 'byNewsShowcasePanel';
|
|
4
|
+
interface Ok<A> {
|
|
5
|
+
readonly ok: true;
|
|
6
|
+
readonly value: A;
|
|
7
|
+
}
|
|
8
|
+
interface Err<E> {
|
|
9
|
+
readonly ok: false;
|
|
10
|
+
readonly error: E;
|
|
11
|
+
}
|
|
12
|
+
type Result<A, E> = Ok<A> | Err<E>;
|
|
4
13
|
declare const _default: {
|
|
5
14
|
name: string;
|
|
6
15
|
'alpha-2': string;
|
|
@@ -76,6 +85,62 @@ interface BuilderState {
|
|
|
76
85
|
/** GSC search corpus. Wins over any `searchType` filter when both are set. */
|
|
77
86
|
searchType?: SearchType;
|
|
78
87
|
}
|
|
88
|
+
type QueryErrorKind = 'missing-date-range' | 'invalid-row-limit' | 'invalid-start-row' | 'invalid-data-state' | 'invalid-aggregation-type' | 'invalid-builder-state' | 'unsupported-capability' | 'unresolvable-dataset';
|
|
89
|
+
type QueryError = {
|
|
90
|
+
kind: 'missing-date-range';
|
|
91
|
+
message: string;
|
|
92
|
+
} | {
|
|
93
|
+
kind: 'invalid-row-limit';
|
|
94
|
+
value: unknown;
|
|
95
|
+
message: string;
|
|
96
|
+
} | {
|
|
97
|
+
kind: 'invalid-start-row';
|
|
98
|
+
value: unknown;
|
|
99
|
+
message: string;
|
|
100
|
+
} | {
|
|
101
|
+
kind: 'invalid-data-state';
|
|
102
|
+
message: string;
|
|
103
|
+
} | {
|
|
104
|
+
kind: 'invalid-aggregation-type';
|
|
105
|
+
message: string;
|
|
106
|
+
} | {
|
|
107
|
+
kind: 'invalid-builder-state';
|
|
108
|
+
message: string;
|
|
109
|
+
cause?: unknown;
|
|
110
|
+
} | {
|
|
111
|
+
kind: 'unsupported-capability';
|
|
112
|
+
capability: string;
|
|
113
|
+
context: string;
|
|
114
|
+
message: string;
|
|
115
|
+
} | {
|
|
116
|
+
kind: 'unresolvable-dataset';
|
|
117
|
+
dimensions: readonly Dimension[];
|
|
118
|
+
filterDims: readonly Dimension[];
|
|
119
|
+
message: string;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Thrown when a query needs a planner capability (regex pushdown, comparison
|
|
123
|
+
* joins, multi-dataset reads) the target engine lacks. Engines catch it to fall
|
|
124
|
+
* back to the live GSC API. Carries the typed `queryError` value so a caller can
|
|
125
|
+
* read the modelled failure instead of parsing the message.
|
|
126
|
+
*/
|
|
127
|
+
declare class UnsupportedLogicalCapabilityError extends Error {
|
|
128
|
+
readonly queryError: Extract<QueryError, {
|
|
129
|
+
kind: 'unsupported-capability';
|
|
130
|
+
}>;
|
|
131
|
+
constructor(capability: string, context: string);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Thrown when a query's grouped + filtered dimensions span more than one stored
|
|
135
|
+
* dataset. Replaces the resolver's raw "unknown column" error so hosts can map
|
|
136
|
+
* it to a 4xx instead of leaking an opaque 500. Carries the typed `queryError`.
|
|
137
|
+
*/
|
|
138
|
+
declare class UnresolvableDatasetError extends Error {
|
|
139
|
+
readonly queryError: Extract<QueryError, {
|
|
140
|
+
kind: 'unresolvable-dataset';
|
|
141
|
+
}>;
|
|
142
|
+
constructor(dimensions: readonly Dimension[], filterDims?: readonly Dimension[]);
|
|
143
|
+
}
|
|
79
144
|
type LogicalDataset = TableName;
|
|
80
145
|
type ComparisonFilter = 'new' | 'lost' | 'improving' | 'declining';
|
|
81
146
|
interface PlannerCapabilities {
|
|
@@ -133,9 +198,6 @@ interface LogicalComparisonPlan {
|
|
|
133
198
|
previous: LogicalQueryPlan;
|
|
134
199
|
comparisonFilter?: ComparisonFilter;
|
|
135
200
|
}
|
|
136
|
-
declare class UnsupportedLogicalCapabilityError extends Error {
|
|
137
|
-
constructor(capability: keyof PlannerCapabilities, context: string);
|
|
138
|
-
}
|
|
139
201
|
declare function inferDataset(dimensions: readonly Dimension[], filterDims?: readonly Dimension[]): LogicalDataset;
|
|
140
202
|
/**
|
|
141
203
|
* True when every grouped + filtered dimension fits inside one stored dataset,
|
|
@@ -145,14 +207,6 @@ declare function inferDataset(dimensions: readonly Dimension[], filterDims?: rea
|
|
|
145
207
|
* time.
|
|
146
208
|
*/
|
|
147
209
|
declare function isDatasetResolvable(dimensions: readonly Dimension[], filterDims?: readonly Dimension[]): boolean;
|
|
148
|
-
/**
|
|
149
|
-
* Thrown when a query's grouped + filtered dimensions span more than one
|
|
150
|
-
* stored dataset. Replaces the resolver's raw "unknown column" error so hosts
|
|
151
|
-
* can map it to a 4xx instead of leaking an opaque 500.
|
|
152
|
-
*/
|
|
153
|
-
declare class UnresolvableDatasetError extends Error {
|
|
154
|
-
constructor(dimensions: readonly Dimension[], filterDims?: readonly Dimension[]);
|
|
155
|
-
}
|
|
156
210
|
/**
|
|
157
211
|
* `BuilderState`-level convenience for {@link isDatasetResolvable}: extracts
|
|
158
212
|
* the state's dimension filters (the same way `buildLogicalPlan` does) and
|
|
@@ -160,6 +214,19 @@ declare class UnresolvableDatasetError extends Error {
|
|
|
160
214
|
* composite source) detect a cross-dimension query without rebuilding a plan.
|
|
161
215
|
*/
|
|
162
216
|
declare function isStateResolvable(state: BuilderState): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Errors-as-values core: builds the logical plan or returns a typed `QueryError`
|
|
219
|
+
* for every modelled failure (missing date range, a regex filter on an engine
|
|
220
|
+
* without regex pushdown, a cross-dimension query with no stored home).
|
|
221
|
+
* `buildLogicalPlan` is the throwing wrapper for call sites that prefer exceptions.
|
|
222
|
+
*/
|
|
223
|
+
declare function buildLogicalPlanResult(state: BuilderState, capabilities?: PlannerCapabilities): Result<LogicalQueryPlan, QueryError>;
|
|
163
224
|
declare function buildLogicalPlan(state: BuilderState, capabilities?: PlannerCapabilities): LogicalQueryPlan;
|
|
225
|
+
/**
|
|
226
|
+
* Errors-as-values core for the comparison plan: returns a typed `QueryError`
|
|
227
|
+
* when the engine lacks the comparison-join or multi-dataset capability the
|
|
228
|
+
* paired queries need, or when either side fails to plan.
|
|
229
|
+
*/
|
|
230
|
+
declare function buildLogicalComparisonPlanResult(current: BuilderState, previous: BuilderState, capabilities?: PlannerCapabilities, comparisonFilter?: ComparisonFilter): Result<LogicalComparisonPlan, QueryError>;
|
|
164
231
|
declare function buildLogicalComparisonPlan(current: BuilderState, previous: BuilderState, capabilities?: PlannerCapabilities, comparisonFilter?: ComparisonFilter): LogicalComparisonPlan;
|
|
165
|
-
export { ComparisonFilter, LogicalComparisonPlan, LogicalDataset, LogicalDimensionFilter, LogicalFilterGroup, LogicalFilterLeaf, LogicalFilterNode, LogicalMetricFilter, LogicalQueryPlan, PlannerCapabilities, type TableName, UnresolvableDatasetError, UnsupportedLogicalCapabilityError, buildLogicalComparisonPlan, buildLogicalPlan, inferDataset, isDatasetResolvable, isStateResolvable };
|
|
232
|
+
export { ComparisonFilter, LogicalComparisonPlan, LogicalDataset, LogicalDimensionFilter, LogicalFilterGroup, LogicalFilterLeaf, LogicalFilterNode, LogicalMetricFilter, LogicalQueryPlan, PlannerCapabilities, type QueryError, type QueryErrorKind, type TableName, UnresolvableDatasetError, UnsupportedLogicalCapabilityError, buildLogicalComparisonPlan, buildLogicalComparisonPlanResult, buildLogicalPlan, buildLogicalPlanResult, inferDataset, isDatasetResolvable, isStateResolvable };
|