gscdump 0.1.3 → 0.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 +4 -9
- package/dist/analysis/index.d.mts +513 -0
- package/dist/analysis/index.mjs +872 -0
- package/dist/index.d.mts +126 -908
- package/dist/index.mjs +290 -3413
- package/dist/query/index.d.mts +72 -55
- package/dist/query/index.mjs +208 -87
- package/package.json +5 -1
package/dist/query/index.d.mts
CHANGED
|
@@ -1,45 +1,11 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import { indexing_v3 } from "@googleapis/indexing/v3";
|
|
1
|
+
import _dayjs, { Dayjs } from "dayjs";
|
|
3
2
|
import { searchconsole_v1 } from "@googleapis/searchconsole/v1";
|
|
4
3
|
|
|
5
4
|
//#region src/core/types.d.ts
|
|
6
|
-
type ApiSite = searchconsole_v1.Schema$WmxSite;
|
|
7
|
-
type ApiSitemap = searchconsole_v1.Schema$WmxSitemap;
|
|
8
|
-
type SearchAnalyticsQuery = searchconsole_v1.Schema$SearchAnalyticsQueryRequest;
|
|
9
|
-
type SearchAnalyticsResponse = searchconsole_v1.Schema$SearchAnalyticsQueryResponse;
|
|
10
|
-
type InspectUrlIndexResponse = searchconsole_v1.Schema$InspectUrlIndexResponse;
|
|
11
|
-
type UrlNotificationMetadata = indexing_v3.Schema$UrlNotificationMetadata;
|
|
12
|
-
type PublishUrlNotificationResponse = indexing_v3.Schema$PublishUrlNotificationResponse;
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region src/core/client.d.ts
|
|
15
5
|
|
|
16
|
-
|
|
17
|
-
sites: {
|
|
18
|
-
list: () => Promise<{
|
|
19
|
-
siteEntry?: ApiSite[];
|
|
20
|
-
}>;
|
|
21
|
-
};
|
|
22
|
-
sitemaps: {
|
|
23
|
-
list: (siteUrl: string) => Promise<{
|
|
24
|
-
sitemap?: ApiSitemap[];
|
|
25
|
-
}>;
|
|
26
|
-
get: (siteUrl: string, feedpath: string) => Promise<ApiSitemap>;
|
|
27
|
-
submit: (siteUrl: string, feedpath: string) => Promise<void>;
|
|
28
|
-
delete: (siteUrl: string, feedpath: string) => Promise<void>;
|
|
29
|
-
};
|
|
30
|
-
searchAnalytics: {
|
|
31
|
-
query: (siteUrl: string, body: SearchAnalyticsQuery) => Promise<SearchAnalyticsResponse>;
|
|
32
|
-
};
|
|
33
|
-
urlInspection: {
|
|
34
|
-
inspect: (siteUrl: string, inspectionUrl: string) => Promise<InspectUrlIndexResponse>;
|
|
35
|
-
};
|
|
36
|
-
indexing: {
|
|
37
|
-
publish: (url: string, type: 'URL_UPDATED' | 'URL_DELETED') => Promise<PublishUrlNotificationResponse>;
|
|
38
|
-
getMetadata: (url: string) => Promise<UrlNotificationMetadata>;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
6
|
+
type SearchAnalyticsQuery = searchconsole_v1.Schema$SearchAnalyticsQueryRequest;
|
|
41
7
|
//#endregion
|
|
42
|
-
//#region src/utils/countries.d.ts
|
|
8
|
+
//#region src/query/utils/countries.d.ts
|
|
43
9
|
declare const _default: {
|
|
44
10
|
name: string;
|
|
45
11
|
'alpha-2': string;
|
|
@@ -48,18 +14,26 @@ declare const _default: {
|
|
|
48
14
|
}[];
|
|
49
15
|
//#endregion
|
|
50
16
|
//#region src/query/constants.d.ts
|
|
51
|
-
declare const
|
|
17
|
+
declare const Devices: {
|
|
52
18
|
readonly MOBILE: "MOBILE";
|
|
53
19
|
readonly DESKTOP: "DESKTOP";
|
|
54
20
|
readonly TABLET: "TABLET";
|
|
55
21
|
};
|
|
56
|
-
type Device = typeof
|
|
57
|
-
declare const
|
|
58
|
-
|
|
22
|
+
type Device = typeof Devices[keyof typeof Devices];
|
|
23
|
+
declare const SearchTypes: {
|
|
24
|
+
readonly WEB: "web";
|
|
25
|
+
readonly IMAGE: "image";
|
|
26
|
+
readonly VIDEO: "video";
|
|
27
|
+
readonly NEWS: "news";
|
|
28
|
+
};
|
|
29
|
+
type SearchType = typeof SearchTypes[keyof typeof SearchTypes];
|
|
30
|
+
declare const Countries: { [K in (typeof _default)[number]["alpha-3"]]: Lowercase<K> };
|
|
31
|
+
type Country = typeof Countries[keyof typeof Countries];
|
|
59
32
|
//#endregion
|
|
60
33
|
//#region src/query/types.d.ts
|
|
61
34
|
interface DimensionValueMap {
|
|
62
35
|
query: string;
|
|
36
|
+
queryCanonical: string;
|
|
63
37
|
page: string;
|
|
64
38
|
country: Country;
|
|
65
39
|
device: Device;
|
|
@@ -67,16 +41,27 @@ interface DimensionValueMap {
|
|
|
67
41
|
date: string;
|
|
68
42
|
}
|
|
69
43
|
type Dimension = keyof DimensionValueMap;
|
|
44
|
+
interface QueryParamValueMap {
|
|
45
|
+
searchType: SearchType;
|
|
46
|
+
}
|
|
47
|
+
type QueryParamName = keyof QueryParamValueMap;
|
|
70
48
|
declare const ColumnBrand: unique symbol;
|
|
71
49
|
interface Column<D extends Dimension> {
|
|
72
50
|
readonly [ColumnBrand]: D;
|
|
73
51
|
readonly dimension: D;
|
|
74
52
|
}
|
|
53
|
+
declare const QueryParamBrand: unique symbol;
|
|
54
|
+
interface QueryParam<P extends QueryParamName> {
|
|
55
|
+
readonly [QueryParamBrand]: P;
|
|
56
|
+
readonly param: P;
|
|
57
|
+
}
|
|
75
58
|
type FilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'includingRegex' | 'excludingRegex';
|
|
76
59
|
type DateOperator = 'gte' | 'gt' | 'lte' | 'lt' | 'between';
|
|
60
|
+
type MetricOperator = 'metricGte' | 'metricGt' | 'metricLte' | 'metricLt' | 'metricBetween';
|
|
61
|
+
type SpecialOperator = 'topLevel';
|
|
77
62
|
interface InternalFilter {
|
|
78
|
-
dimension: Dimension;
|
|
79
|
-
operator: FilterOperator | DateOperator;
|
|
63
|
+
dimension: Dimension | QueryParamName | Metric;
|
|
64
|
+
operator: FilterOperator | DateOperator | MetricOperator | SpecialOperator;
|
|
80
65
|
expression: string;
|
|
81
66
|
expression2?: string;
|
|
82
67
|
}
|
|
@@ -85,10 +70,11 @@ interface Filter<C = object> {
|
|
|
85
70
|
readonly [FilterBrand]: true;
|
|
86
71
|
readonly _constraints: C;
|
|
87
72
|
readonly _filters: InternalFilter[];
|
|
73
|
+
readonly _nestedGroups?: Filter<any>[];
|
|
88
74
|
readonly _groupType?: 'and' | 'or';
|
|
89
75
|
}
|
|
90
76
|
type MergeConstraints<F extends Filter<any>[]> = UnionToIntersection<F[number]['_constraints']>;
|
|
91
|
-
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
77
|
+
type UnionToIntersection<U$1> = (U$1 extends any ? (k: U$1) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
92
78
|
interface GSCResult<D extends Dimension[], C> {
|
|
93
79
|
rows: Array<GSCRow<D, C>>;
|
|
94
80
|
}
|
|
@@ -98,24 +84,38 @@ type GSCRow<D extends Dimension[], C> = { [K in D[number]]: K extends keyof C ?
|
|
|
98
84
|
ctr: number;
|
|
99
85
|
position: number;
|
|
100
86
|
};
|
|
87
|
+
type Metric = 'clicks' | 'impressions' | 'ctr' | 'position';
|
|
88
|
+
declare const MetricColumnBrand: unique symbol;
|
|
89
|
+
interface MetricColumn<M extends Metric> {
|
|
90
|
+
readonly [MetricColumnBrand]: M;
|
|
91
|
+
readonly metric: M;
|
|
92
|
+
}
|
|
101
93
|
interface BuilderState {
|
|
102
94
|
dimensions: Dimension[];
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
metrics?: Metric[];
|
|
96
|
+
filter?: Filter<any>;
|
|
97
|
+
orderBy?: {
|
|
98
|
+
column: Metric | 'date';
|
|
99
|
+
dir: 'asc' | 'desc';
|
|
100
|
+
};
|
|
105
101
|
rowLimit?: number;
|
|
106
102
|
startRow?: number;
|
|
107
103
|
}
|
|
108
104
|
//#endregion
|
|
109
105
|
//#region src/query/builder.d.ts
|
|
106
|
+
type SelectableColumn = Column<Dimension> | MetricColumn<Metric>;
|
|
107
|
+
type OrderableColumn = MetricColumn<Metric> | Column<'date'>;
|
|
108
|
+
type ExtractDimensions<T extends SelectableColumn[]> = { [K in keyof T]: T[K] extends Column<infer D> ? D : never }[number] extends infer U ? Exclude<U, never>[] : never;
|
|
110
109
|
interface GSCQueryBuilder<D extends Dimension[] = [], C = object> {
|
|
111
|
-
select:
|
|
110
|
+
select: {
|
|
111
|
+
<T extends Dimension[]>(...dims: T): GSCQueryBuilder<T, C>;
|
|
112
|
+
<T extends SelectableColumn[]>(...cols: T): GSCQueryBuilder<ExtractDimensions<T> & Dimension[], C>;
|
|
113
|
+
};
|
|
112
114
|
where: <F extends Filter<any>>(filter: F) => GSCQueryBuilder<D, C & F['_constraints']>;
|
|
113
|
-
|
|
115
|
+
orderBy: (col: OrderableColumn, dir: 'asc' | 'desc') => GSCQueryBuilder<D, C>;
|
|
114
116
|
limit: (n: number) => GSCQueryBuilder<D, C>;
|
|
115
117
|
offset: (n: number) => GSCQueryBuilder<D, C>;
|
|
116
|
-
execute: (client: GoogleSearchConsoleClient) => Promise<GSCResult<D, C>>;
|
|
117
118
|
toBody: () => SearchAnalyticsQuery;
|
|
118
|
-
/** Expose internal state for analysis functions to merge with */
|
|
119
119
|
getState: () => BuilderState;
|
|
120
120
|
}
|
|
121
121
|
declare const gsc: GSCQueryBuilder<[], object>;
|
|
@@ -123,13 +123,20 @@ declare const gsc: GSCQueryBuilder<[], object>;
|
|
|
123
123
|
//#region src/query/columns.d.ts
|
|
124
124
|
declare const page: Column<"page">;
|
|
125
125
|
declare const query: Column<"query">;
|
|
126
|
+
declare const queryCanonical: Column<"queryCanonical">;
|
|
126
127
|
declare const device: Column<"device">;
|
|
127
128
|
declare const country: Column<"country">;
|
|
128
129
|
declare const searchAppearance: Column<"searchAppearance">;
|
|
129
130
|
declare const date: Column<"date">;
|
|
131
|
+
declare const clicks: MetricColumn<"clicks">;
|
|
132
|
+
declare const impressions: MetricColumn<"impressions">;
|
|
133
|
+
declare const ctr: MetricColumn<"ctr">;
|
|
134
|
+
declare const position: MetricColumn<"position">;
|
|
135
|
+
declare const searchType: QueryParam<"searchType">;
|
|
130
136
|
//#endregion
|
|
131
137
|
//#region src/query/operators.d.ts
|
|
132
138
|
declare function eq<D extends Dimension, V extends DimensionValueMap[D]>(column: Column<D>, value: V): Filter<Record<D, V>>;
|
|
139
|
+
declare function eq<P extends QueryParamName, V extends QueryParamValueMap[P]>(param: QueryParam<P>, value: V): Filter<Record<P, V>>;
|
|
133
140
|
declare function ne<D extends Dimension>(column: Column<D>, value: DimensionValueMap[D]): Filter<object>;
|
|
134
141
|
declare function inArray<D extends Dimension, V extends DimensionValueMap[D]>(column: Column<D>, values: readonly V[]): Filter<Record<D, V>>;
|
|
135
142
|
declare function contains<D extends Dimension>(column: Column<D>, pattern: string): Filter<object>;
|
|
@@ -139,23 +146,33 @@ declare function notRegex<D extends Dimension>(column: Column<D>, pattern: RegEx
|
|
|
139
146
|
declare function and<F extends Filter<any>[]>(...filters: F): Filter<MergeConstraints<F>>;
|
|
140
147
|
declare function or<F extends Filter<any>[]>(...filters: F): Filter<object>;
|
|
141
148
|
declare function not<F extends Filter<any>>(filter: F): Filter<object>;
|
|
149
|
+
declare function gte<M extends Metric>(column: MetricColumn<M>, value: number): Filter<object>;
|
|
142
150
|
declare function gte<D extends Dimension>(column: Column<D>, value: DimensionValueMap[D]): Filter<object>;
|
|
151
|
+
declare function gt<M extends Metric>(column: MetricColumn<M>, value: number): Filter<object>;
|
|
143
152
|
declare function gt<D extends Dimension>(column: Column<D>, value: DimensionValueMap[D]): Filter<object>;
|
|
153
|
+
declare function lte<M extends Metric>(column: MetricColumn<M>, value: number): Filter<object>;
|
|
144
154
|
declare function lte<D extends Dimension>(column: Column<D>, value: DimensionValueMap[D]): Filter<object>;
|
|
155
|
+
declare function lt<M extends Metric>(column: MetricColumn<M>, value: number): Filter<object>;
|
|
145
156
|
declare function lt<D extends Dimension>(column: Column<D>, value: DimensionValueMap[D]): Filter<object>;
|
|
157
|
+
declare function between<M extends Metric>(column: MetricColumn<M>, start: number, end: number): Filter<object>;
|
|
146
158
|
declare function between<D extends Dimension>(column: Column<D>, start: DimensionValueMap[D], end: DimensionValueMap[D]): Filter<object>;
|
|
159
|
+
declare function topLevel(column: Column<'page'>): Filter<object>;
|
|
147
160
|
//#endregion
|
|
148
161
|
//#region src/query/resolver.d.ts
|
|
149
|
-
|
|
150
|
-
* Extract date range from filters. Used by analysis functions to get the period.
|
|
151
|
-
*/
|
|
152
|
-
declare function extractDateRange(filters: Filter<any>[]): {
|
|
162
|
+
declare function extractDateRange(filter?: Filter<any>): {
|
|
153
163
|
startDate?: string;
|
|
154
164
|
endDate?: string;
|
|
155
165
|
};
|
|
166
|
+
declare function extractMetricFilters(filter?: Filter<any>): InternalFilter[];
|
|
167
|
+
declare function extractSpecialOperatorFilters(filter?: Filter<any>): InternalFilter[];
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/query/utils/dayjs.d.ts
|
|
170
|
+
declare function dayjs(date?: _dayjs.ConfigType): Dayjs;
|
|
171
|
+
declare function currentPstDate(): string;
|
|
172
|
+
declare function dayjsPst(): Dayjs;
|
|
156
173
|
//#endregion
|
|
157
174
|
//#region src/query/index.d.ts
|
|
158
175
|
declare function today(): string;
|
|
159
176
|
declare function daysAgo(n: number): string;
|
|
160
177
|
//#endregion
|
|
161
|
-
export { type BuilderState, type Column,
|
|
178
|
+
export { type BuilderState, type Column, Countries, type Country, type Device, Devices, type Dimension, type DimensionValueMap, type Filter, type GSCQueryBuilder, type GSCResult, type GSCRow, type InternalFilter, type Metric, type MetricColumn, type QueryParam, type QueryParamName, type QueryParamValueMap, type SearchType, SearchTypes, and, between, clicks, contains, country, ctr, currentPstDate, date, dayjs, dayjsPst, daysAgo, device, eq, extractDateRange, extractMetricFilters, extractSpecialOperatorFilters, gsc, gt, gte, impressions, inArray, like, lt, lte, ne, not, notRegex, or, page, position, query, queryCanonical, regex, searchAppearance, searchType, today, topLevel };
|
package/dist/query/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import _dayjs from "dayjs";
|
|
|
2
2
|
import timezone from "dayjs/plugin/timezone.js";
|
|
3
3
|
import utc from "dayjs/plugin/utc.js";
|
|
4
4
|
|
|
5
|
-
//#region src/utils/dayjs.ts
|
|
5
|
+
//#region src/query/utils/dayjs.ts
|
|
6
6
|
_dayjs.extend(utc);
|
|
7
7
|
_dayjs.extend(timezone);
|
|
8
8
|
function dayjs(date$1) {
|
|
@@ -24,128 +24,179 @@ const DATE_OPERATORS = [
|
|
|
24
24
|
"lt",
|
|
25
25
|
"between"
|
|
26
26
|
];
|
|
27
|
+
const METRIC_OPERATORS = [
|
|
28
|
+
"metricGte",
|
|
29
|
+
"metricGt",
|
|
30
|
+
"metricLte",
|
|
31
|
+
"metricLt",
|
|
32
|
+
"metricBetween"
|
|
33
|
+
];
|
|
34
|
+
const SPECIAL_OPERATORS = ["topLevel"];
|
|
35
|
+
const QUERY_PARAMS = ["searchType"];
|
|
36
|
+
function isMetricOperator(op) {
|
|
37
|
+
return METRIC_OPERATORS.includes(op);
|
|
38
|
+
}
|
|
39
|
+
function isSpecialOperator(op) {
|
|
40
|
+
return SPECIAL_OPERATORS.includes(op);
|
|
41
|
+
}
|
|
27
42
|
function isDateOperator(op) {
|
|
28
43
|
return DATE_OPERATORS.includes(op);
|
|
29
44
|
}
|
|
45
|
+
function isQueryParam(dim) {
|
|
46
|
+
return QUERY_PARAMS.includes(dim);
|
|
47
|
+
}
|
|
30
48
|
function addDays(dateStr, days) {
|
|
31
49
|
const d = new Date(dateStr);
|
|
32
50
|
d.setDate(d.getDate() + days);
|
|
33
51
|
return d.toISOString().split("T")[0];
|
|
34
52
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*/
|
|
38
|
-
function extractDateRange(filters) {
|
|
39
|
-
const { startDate, endDate } = extractDateFilters(filters);
|
|
40
|
-
return {
|
|
41
|
-
startDate,
|
|
42
|
-
endDate
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function extractDateFilters(filters) {
|
|
53
|
+
function extractSpecialFilters(filter) {
|
|
54
|
+
if (!filter) return {};
|
|
46
55
|
let startDate;
|
|
47
56
|
let endDate;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
startDate = df.expression;
|
|
69
|
-
endDate = df.expression2;
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
if (otherFilters.length > 0) nonDateFilters.push({
|
|
73
|
-
...filter,
|
|
74
|
-
_filters: otherFilters
|
|
75
|
-
});
|
|
57
|
+
let searchType$1;
|
|
58
|
+
const otherFilters = [];
|
|
59
|
+
const cleanedNestedGroups = [];
|
|
60
|
+
for (const f of filter._filters) if (f.dimension === "date" && isDateOperator(f.operator)) switch (f.operator) {
|
|
61
|
+
case "gte":
|
|
62
|
+
startDate = f.expression;
|
|
63
|
+
break;
|
|
64
|
+
case "gt":
|
|
65
|
+
startDate = addDays(f.expression, 1);
|
|
66
|
+
break;
|
|
67
|
+
case "lte":
|
|
68
|
+
endDate = f.expression;
|
|
69
|
+
break;
|
|
70
|
+
case "lt":
|
|
71
|
+
endDate = addDays(f.expression, -1);
|
|
72
|
+
break;
|
|
73
|
+
case "between":
|
|
74
|
+
startDate = f.expression;
|
|
75
|
+
endDate = f.expression2;
|
|
76
|
+
break;
|
|
76
77
|
}
|
|
78
|
+
else if (isQueryParam(f.dimension)) {
|
|
79
|
+
if (f.dimension === "searchType") searchType$1 = f.expression;
|
|
80
|
+
} else if (isMetricOperator(f.operator) || isSpecialOperator(f.operator)) otherFilters.push(f);
|
|
81
|
+
else otherFilters.push(f);
|
|
82
|
+
if (filter._nestedGroups) for (const nested of filter._nestedGroups) {
|
|
83
|
+
const extracted = extractSpecialFilters(nested);
|
|
84
|
+
if (extracted.startDate) startDate = extracted.startDate;
|
|
85
|
+
if (extracted.endDate) endDate = extracted.endDate;
|
|
86
|
+
if (extracted.searchType) searchType$1 = extracted.searchType;
|
|
87
|
+
if (extracted.dimensionFilter) cleanedNestedGroups.push(extracted.dimensionFilter);
|
|
88
|
+
}
|
|
89
|
+
const dimensionFilter = otherFilters.length > 0 || cleanedNestedGroups.length > 0 ? {
|
|
90
|
+
...filter,
|
|
91
|
+
_filters: otherFilters,
|
|
92
|
+
_nestedGroups: cleanedNestedGroups.length > 0 ? cleanedNestedGroups : void 0
|
|
93
|
+
} : void 0;
|
|
77
94
|
return {
|
|
78
95
|
startDate,
|
|
79
96
|
endDate,
|
|
80
|
-
|
|
97
|
+
searchType: searchType$1,
|
|
98
|
+
dimensionFilter
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function extractDateRange(filter) {
|
|
102
|
+
const { startDate, endDate } = extractSpecialFilters(filter);
|
|
103
|
+
return {
|
|
104
|
+
startDate,
|
|
105
|
+
endDate
|
|
81
106
|
};
|
|
82
107
|
}
|
|
108
|
+
function extractMetricFilters(filter) {
|
|
109
|
+
if (!filter) return [];
|
|
110
|
+
const metricFilters = filter._filters.filter((f) => isMetricOperator(f.operator));
|
|
111
|
+
const nested = filter._nestedGroups?.flatMap((g) => extractMetricFilters(g)) ?? [];
|
|
112
|
+
return [...metricFilters, ...nested];
|
|
113
|
+
}
|
|
114
|
+
function extractSpecialOperatorFilters(filter) {
|
|
115
|
+
if (!filter) return [];
|
|
116
|
+
const special = filter._filters.filter((f) => isSpecialOperator(f.operator));
|
|
117
|
+
const nested = filter._nestedGroups?.flatMap((g) => extractSpecialOperatorFilters(g)) ?? [];
|
|
118
|
+
return [...special, ...nested];
|
|
119
|
+
}
|
|
83
120
|
function resolveToBody(state) {
|
|
84
|
-
const { startDate, endDate,
|
|
85
|
-
if (!startDate || !endDate) throw new Error("Date range required: use .where(between(date, start, end)) or .where(gte(date, start)
|
|
121
|
+
const { startDate, endDate, searchType: searchType$1, dimensionFilter } = extractSpecialFilters(state.filter);
|
|
122
|
+
if (!startDate || !endDate) throw new Error("Date range required: use .where(between(date, start, end)) or .where(and(gte(date, start), lte(date, end)))");
|
|
86
123
|
const body = {
|
|
87
124
|
dimensions: state.dimensions,
|
|
88
125
|
startDate,
|
|
89
126
|
endDate
|
|
90
127
|
};
|
|
128
|
+
if (searchType$1) body.searchType = searchType$1;
|
|
91
129
|
if (state.rowLimit) body.rowLimit = state.rowLimit;
|
|
92
130
|
if (state.startRow) body.startRow = state.startRow;
|
|
93
|
-
const filterGroups =
|
|
131
|
+
const filterGroups = resolveFilter(dimensionFilter);
|
|
94
132
|
if (filterGroups.length > 0) body.dimensionFilterGroups = filterGroups;
|
|
95
133
|
return body;
|
|
96
134
|
}
|
|
97
|
-
function
|
|
135
|
+
function isApiFilter(f) {
|
|
136
|
+
return !isMetricOperator(f.operator) && !isSpecialOperator(f.operator);
|
|
137
|
+
}
|
|
138
|
+
function resolveFilter(filter) {
|
|
139
|
+
if (!filter) return [];
|
|
98
140
|
const groups = [];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
141
|
+
const groupType = filter._groupType ?? "and";
|
|
142
|
+
const apiFilters = filter._filters.filter(isApiFilter);
|
|
143
|
+
if (groupType === "or") {
|
|
144
|
+
if (apiFilters.length > 0) groups.push({
|
|
145
|
+
groupType: "or",
|
|
146
|
+
filters: apiFilters.map((f) => ({
|
|
147
|
+
dimension: f.dimension,
|
|
148
|
+
operator: f.operator,
|
|
149
|
+
expression: f.expression
|
|
150
|
+
}))
|
|
151
|
+
});
|
|
152
|
+
} else if (apiFilters.length > 0) groups.push({ filters: apiFilters.map((f) => ({
|
|
108
153
|
dimension: f.dimension,
|
|
109
154
|
operator: f.operator,
|
|
110
155
|
expression: f.expression
|
|
111
156
|
})) });
|
|
157
|
+
if (filter._nestedGroups) for (const nested of filter._nestedGroups) groups.push(...resolveFilter(nested));
|
|
112
158
|
return groups;
|
|
113
159
|
}
|
|
114
160
|
|
|
115
161
|
//#endregion
|
|
116
162
|
//#region src/query/builder.ts
|
|
117
|
-
function
|
|
118
|
-
return
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
dimensions.forEach((dim, i) => {
|
|
126
|
-
result[dim] = row.keys?.[i];
|
|
127
|
-
});
|
|
128
|
-
return result;
|
|
129
|
-
}) };
|
|
163
|
+
function isDimensionString(v) {
|
|
164
|
+
return typeof v === "string";
|
|
165
|
+
}
|
|
166
|
+
function isMetricColumn(v) {
|
|
167
|
+
return typeof v === "object" && v !== null && "metric" in v;
|
|
168
|
+
}
|
|
169
|
+
function isDimensionColumn(v) {
|
|
170
|
+
return typeof v === "object" && v !== null && "dimension" in v && !("metric" in v);
|
|
130
171
|
}
|
|
131
172
|
function createBuilder(state) {
|
|
132
173
|
return {
|
|
133
|
-
select(...
|
|
174
|
+
select(...args) {
|
|
175
|
+
const dimensions = [];
|
|
176
|
+
const metrics = [];
|
|
177
|
+
for (const arg of args) if (isDimensionString(arg)) dimensions.push(arg);
|
|
178
|
+
else if (isDimensionColumn(arg)) dimensions.push(arg.dimension);
|
|
179
|
+
else if (isMetricColumn(arg)) metrics.push(arg.metric);
|
|
134
180
|
return createBuilder({
|
|
135
181
|
...state,
|
|
136
|
-
dimensions
|
|
182
|
+
dimensions,
|
|
183
|
+
metrics: metrics.length > 0 ? metrics : void 0
|
|
137
184
|
});
|
|
138
185
|
},
|
|
139
186
|
where(filter) {
|
|
140
187
|
return createBuilder({
|
|
141
188
|
...state,
|
|
142
|
-
|
|
189
|
+
filter
|
|
143
190
|
});
|
|
144
191
|
},
|
|
145
|
-
|
|
192
|
+
orderBy(col, dir) {
|
|
193
|
+
const column = isMetricColumn(col) ? col.metric : col.dimension;
|
|
146
194
|
return createBuilder({
|
|
147
195
|
...state,
|
|
148
|
-
|
|
196
|
+
orderBy: {
|
|
197
|
+
column,
|
|
198
|
+
dir
|
|
199
|
+
}
|
|
149
200
|
});
|
|
150
201
|
},
|
|
151
202
|
limit(n) {
|
|
@@ -160,10 +211,6 @@ function createBuilder(state) {
|
|
|
160
211
|
startRow: n
|
|
161
212
|
});
|
|
162
213
|
},
|
|
163
|
-
async execute(client) {
|
|
164
|
-
const body = resolveToBody(state);
|
|
165
|
-
return transformResponse(await client.searchAnalytics.query(state.siteUrl, body), state.dimensions);
|
|
166
|
-
},
|
|
167
214
|
toBody() {
|
|
168
215
|
return resolveToBody(state);
|
|
169
216
|
},
|
|
@@ -172,25 +219,34 @@ function createBuilder(state) {
|
|
|
172
219
|
}
|
|
173
220
|
};
|
|
174
221
|
}
|
|
175
|
-
const gsc = createBuilder({
|
|
176
|
-
dimensions: [],
|
|
177
|
-
filters: []
|
|
178
|
-
});
|
|
222
|
+
const gsc = createBuilder({ dimensions: [] });
|
|
179
223
|
|
|
180
224
|
//#endregion
|
|
181
225
|
//#region src/query/columns.ts
|
|
182
226
|
function createColumn(dimension) {
|
|
183
227
|
return { dimension };
|
|
184
228
|
}
|
|
229
|
+
function createMetricColumn(metric) {
|
|
230
|
+
return { metric };
|
|
231
|
+
}
|
|
232
|
+
function createQueryParam(param) {
|
|
233
|
+
return { param };
|
|
234
|
+
}
|
|
185
235
|
const page = createColumn("page");
|
|
186
236
|
const query = createColumn("query");
|
|
237
|
+
const queryCanonical = createColumn("queryCanonical");
|
|
187
238
|
const device = createColumn("device");
|
|
188
239
|
const country = createColumn("country");
|
|
189
240
|
const searchAppearance = createColumn("searchAppearance");
|
|
190
241
|
const date = createColumn("date");
|
|
242
|
+
const clicks = createMetricColumn("clicks");
|
|
243
|
+
const impressions = createMetricColumn("impressions");
|
|
244
|
+
const ctr = createMetricColumn("ctr");
|
|
245
|
+
const position = createMetricColumn("position");
|
|
246
|
+
const searchType = createQueryParam("searchType");
|
|
191
247
|
|
|
192
248
|
//#endregion
|
|
193
|
-
//#region src/utils/countries.ts
|
|
249
|
+
//#region src/query/utils/countries.ts
|
|
194
250
|
var countries_default = [
|
|
195
251
|
{
|
|
196
252
|
"name": "Afghanistan",
|
|
@@ -1690,20 +1746,26 @@ var countries_default = [
|
|
|
1690
1746
|
|
|
1691
1747
|
//#endregion
|
|
1692
1748
|
//#region src/query/constants.ts
|
|
1693
|
-
const
|
|
1749
|
+
const Devices = {
|
|
1694
1750
|
MOBILE: "MOBILE",
|
|
1695
1751
|
DESKTOP: "DESKTOP",
|
|
1696
1752
|
TABLET: "TABLET"
|
|
1697
1753
|
};
|
|
1698
|
-
const
|
|
1754
|
+
const SearchTypes = {
|
|
1755
|
+
WEB: "web",
|
|
1756
|
+
IMAGE: "image",
|
|
1757
|
+
VIDEO: "video",
|
|
1758
|
+
NEWS: "news"
|
|
1759
|
+
};
|
|
1760
|
+
const Countries = Object.fromEntries(countries_default.map((c) => [c["alpha-3"], c["alpha-3"].toLowerCase()]));
|
|
1699
1761
|
|
|
1700
1762
|
//#endregion
|
|
1701
1763
|
//#region src/query/operators.ts
|
|
1702
|
-
function eq(
|
|
1764
|
+
function eq(columnOrParam, value) {
|
|
1703
1765
|
return {
|
|
1704
1766
|
_constraints: {},
|
|
1705
1767
|
_filters: [{
|
|
1706
|
-
dimension:
|
|
1768
|
+
dimension: "dimension" in columnOrParam ? columnOrParam.dimension : columnOrParam.param,
|
|
1707
1769
|
operator: "equals",
|
|
1708
1770
|
expression: String(value)
|
|
1709
1771
|
}]
|
|
@@ -1771,9 +1833,17 @@ function notRegex(column, pattern) {
|
|
|
1771
1833
|
};
|
|
1772
1834
|
}
|
|
1773
1835
|
function and(...filters) {
|
|
1836
|
+
const flatFilters = [];
|
|
1837
|
+
const nestedGroups = [];
|
|
1838
|
+
for (const f of filters) if (f._groupType === "or") nestedGroups.push(f);
|
|
1839
|
+
else {
|
|
1840
|
+
flatFilters.push(...f._filters);
|
|
1841
|
+
if (f._nestedGroups) nestedGroups.push(...f._nestedGroups);
|
|
1842
|
+
}
|
|
1774
1843
|
return {
|
|
1775
1844
|
_constraints: {},
|
|
1776
|
-
_filters:
|
|
1845
|
+
_filters: flatFilters,
|
|
1846
|
+
_nestedGroups: nestedGroups.length > 0 ? nestedGroups : void 0,
|
|
1777
1847
|
_groupType: "and"
|
|
1778
1848
|
};
|
|
1779
1849
|
}
|
|
@@ -1811,6 +1881,14 @@ function invertOperator(op) {
|
|
|
1811
1881
|
}[op];
|
|
1812
1882
|
}
|
|
1813
1883
|
function gte(column, value) {
|
|
1884
|
+
if ("metric" in column) return {
|
|
1885
|
+
_constraints: {},
|
|
1886
|
+
_filters: [{
|
|
1887
|
+
dimension: column.metric,
|
|
1888
|
+
operator: "metricGte",
|
|
1889
|
+
expression: String(value)
|
|
1890
|
+
}]
|
|
1891
|
+
};
|
|
1814
1892
|
return {
|
|
1815
1893
|
_constraints: {},
|
|
1816
1894
|
_filters: [{
|
|
@@ -1821,6 +1899,14 @@ function gte(column, value) {
|
|
|
1821
1899
|
};
|
|
1822
1900
|
}
|
|
1823
1901
|
function gt(column, value) {
|
|
1902
|
+
if ("metric" in column) return {
|
|
1903
|
+
_constraints: {},
|
|
1904
|
+
_filters: [{
|
|
1905
|
+
dimension: column.metric,
|
|
1906
|
+
operator: "metricGt",
|
|
1907
|
+
expression: String(value)
|
|
1908
|
+
}]
|
|
1909
|
+
};
|
|
1824
1910
|
return {
|
|
1825
1911
|
_constraints: {},
|
|
1826
1912
|
_filters: [{
|
|
@@ -1831,6 +1917,14 @@ function gt(column, value) {
|
|
|
1831
1917
|
};
|
|
1832
1918
|
}
|
|
1833
1919
|
function lte(column, value) {
|
|
1920
|
+
if ("metric" in column) return {
|
|
1921
|
+
_constraints: {},
|
|
1922
|
+
_filters: [{
|
|
1923
|
+
dimension: column.metric,
|
|
1924
|
+
operator: "metricLte",
|
|
1925
|
+
expression: String(value)
|
|
1926
|
+
}]
|
|
1927
|
+
};
|
|
1834
1928
|
return {
|
|
1835
1929
|
_constraints: {},
|
|
1836
1930
|
_filters: [{
|
|
@@ -1841,6 +1935,14 @@ function lte(column, value) {
|
|
|
1841
1935
|
};
|
|
1842
1936
|
}
|
|
1843
1937
|
function lt(column, value) {
|
|
1938
|
+
if ("metric" in column) return {
|
|
1939
|
+
_constraints: {},
|
|
1940
|
+
_filters: [{
|
|
1941
|
+
dimension: column.metric,
|
|
1942
|
+
operator: "metricLt",
|
|
1943
|
+
expression: String(value)
|
|
1944
|
+
}]
|
|
1945
|
+
};
|
|
1844
1946
|
return {
|
|
1845
1947
|
_constraints: {},
|
|
1846
1948
|
_filters: [{
|
|
@@ -1851,6 +1953,15 @@ function lt(column, value) {
|
|
|
1851
1953
|
};
|
|
1852
1954
|
}
|
|
1853
1955
|
function between(column, start, end) {
|
|
1956
|
+
if ("metric" in column) return {
|
|
1957
|
+
_constraints: {},
|
|
1958
|
+
_filters: [{
|
|
1959
|
+
dimension: column.metric,
|
|
1960
|
+
operator: "metricBetween",
|
|
1961
|
+
expression: String(start),
|
|
1962
|
+
expression2: String(end)
|
|
1963
|
+
}]
|
|
1964
|
+
};
|
|
1854
1965
|
return {
|
|
1855
1966
|
_constraints: {},
|
|
1856
1967
|
_filters: [{
|
|
@@ -1861,6 +1972,16 @@ function between(column, start, end) {
|
|
|
1861
1972
|
}]
|
|
1862
1973
|
};
|
|
1863
1974
|
}
|
|
1975
|
+
function topLevel(column) {
|
|
1976
|
+
return {
|
|
1977
|
+
_constraints: {},
|
|
1978
|
+
_filters: [{
|
|
1979
|
+
dimension: column.dimension,
|
|
1980
|
+
operator: "topLevel",
|
|
1981
|
+
expression: ""
|
|
1982
|
+
}]
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1864
1985
|
|
|
1865
1986
|
//#endregion
|
|
1866
1987
|
//#region src/query/index.ts
|
|
@@ -1872,4 +1993,4 @@ function daysAgo(n) {
|
|
|
1872
1993
|
}
|
|
1873
1994
|
|
|
1874
1995
|
//#endregion
|
|
1875
|
-
export {
|
|
1996
|
+
export { Countries, Devices, SearchTypes, and, between, clicks, contains, country, ctr, currentPstDate, date, dayjs, dayjsPst, daysAgo, device, eq, extractDateRange, extractMetricFilters, extractSpecialOperatorFilters, gsc, gt, gte, impressions, inArray, like, lt, lte, ne, not, notRegex, or, page, position, query, queryCanonical, regex, searchAppearance, searchType, today, topLevel };
|