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.
@@ -1,45 +1,11 @@
1
- import "ofetch";
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
- interface GoogleSearchConsoleClient {
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 Device: {
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 Device[keyof typeof Device];
57
- declare const Country: { [K in (typeof _default)[number]["alpha-3"]]: Lowercase<K> };
58
- type Country = typeof Country[keyof typeof Country];
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
- filters: Filter<any>[];
104
- siteUrl?: string;
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: <T extends Dimension[]>(...dims: T) => GSCQueryBuilder<T, C>;
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
- siteUrl: (url: string) => GSCQueryBuilder<D, C>;
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, Country, type Country as CountryType, Device, type Device as DeviceType, type Dimension, type DimensionValueMap, type Filter, type GSCQueryBuilder, type GSCResult, type GSCRow, and, between, contains, country, date, daysAgo, device, eq, extractDateRange, gsc, gt, gte, inArray, like, lt, lte, ne, not, notRegex, or, page, query, regex, searchAppearance, today };
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 };
@@ -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
- * Extract date range from filters. Used by analysis functions to get the period.
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
- const nonDateFilters = [];
49
- for (const filter of filters) {
50
- const dateFilters = [];
51
- const otherFilters = [];
52
- for (const f of filter._filters) if (f.dimension === "date" && isDateOperator(f.operator)) dateFilters.push(f);
53
- else otherFilters.push(f);
54
- for (const df of dateFilters) switch (df.operator) {
55
- case "gte":
56
- startDate = df.expression;
57
- break;
58
- case "gt":
59
- startDate = addDays(df.expression, 1);
60
- break;
61
- case "lte":
62
- endDate = df.expression;
63
- break;
64
- case "lt":
65
- endDate = addDays(df.expression, -1);
66
- break;
67
- case "between":
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
- nonDateFilters
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, nonDateFilters } = extractDateFilters(state.filters);
85
- if (!startDate || !endDate) throw new Error("Date range required: use .where(between(date, start, end)) or .where(gte(date, start)).where(lte(date, end))");
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 = resolveFilters(nonDateFilters);
131
+ const filterGroups = resolveFilter(dimensionFilter);
94
132
  if (filterGroups.length > 0) body.dimensionFilterGroups = filterGroups;
95
133
  return body;
96
134
  }
97
- function resolveFilters(filters) {
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
- for (const filter of filters) if ((filter._groupType ?? "and") === "or" && filter._filters.length > 1) groups.push({
100
- groupType: "or",
101
- filters: filter._filters.map((f) => ({
102
- dimension: f.dimension,
103
- operator: f.operator,
104
- expression: f.expression
105
- }))
106
- });
107
- else if (filter._filters.length > 0) groups.push({ filters: filter._filters.map((f) => ({
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 transformResponse(response, dimensions) {
118
- return { rows: (response.rows ?? []).map((row) => {
119
- const result = {
120
- clicks: row.clicks,
121
- impressions: row.impressions,
122
- ctr: row.ctr,
123
- position: row.position
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(...dims) {
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: dims
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
- filters: [...state.filters, filter]
189
+ filter
143
190
  });
144
191
  },
145
- siteUrl(url) {
192
+ orderBy(col, dir) {
193
+ const column = isMetricColumn(col) ? col.metric : col.dimension;
146
194
  return createBuilder({
147
195
  ...state,
148
- siteUrl: url
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 Device = {
1749
+ const Devices = {
1694
1750
  MOBILE: "MOBILE",
1695
1751
  DESKTOP: "DESKTOP",
1696
1752
  TABLET: "TABLET"
1697
1753
  };
1698
- const Country = Object.fromEntries(countries_default.map((c) => [c["alpha-3"], c["alpha-3"].toLowerCase()]));
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(column, value) {
1764
+ function eq(columnOrParam, value) {
1703
1765
  return {
1704
1766
  _constraints: {},
1705
1767
  _filters: [{
1706
- dimension: column.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: filters.flatMap((f) => f._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 { Country, Device, and, between, contains, country, date, daysAgo, device, eq, extractDateRange, gsc, gt, gte, inArray, like, lt, lte, ne, not, notRegex, or, page, query, regex, searchAppearance, today };
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 };