gscdump 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ interface Ok<A> {
2
+ readonly ok: true;
3
+ readonly value: A;
4
+ }
5
+ interface Err<E> {
6
+ readonly ok: false;
7
+ readonly error: E;
8
+ }
9
+ type Result<A, E> = Ok<A> | Err<E>;
10
+ declare function ok<A>(value: A): Ok<A>;
11
+ declare function err<E>(error: E): Err<E>;
12
+ declare function isOk<A, E>(result: Result<A, E>): result is Ok<A>;
13
+ declare function isErr<A, E>(result: Result<A, E>): result is Err<E>;
14
+ /**
15
+ * Collapses a `Result` back into the throwing world: returns the value or throws
16
+ * via `toError`. Used by the throwing wrappers that sit over the `Result` core so
17
+ * existing call sites keep their `await`/`throw` ergonomics.
18
+ */
19
+ declare function unwrapResult<A, E>(result: Result<A, E>, toError: (error: E) => unknown): A;
20
+ export { Err, Ok, Result, err, isErr, isOk, ok, unwrapResult };
@@ -0,0 +1,112 @@
1
+ import { GscAggregationType, GscDataState } from "./contracts.mjs";
2
+ declare const _default: {
3
+ name: string;
4
+ 'alpha-2': string;
5
+ 'alpha-3': string;
6
+ 'country-code': string;
7
+ }[];
8
+ declare const Devices: {
9
+ readonly MOBILE: "MOBILE";
10
+ readonly DESKTOP: "DESKTOP";
11
+ readonly TABLET: "TABLET";
12
+ };
13
+ type Device = typeof Devices[keyof typeof Devices];
14
+ declare const SearchTypes: {
15
+ readonly WEB: "web";
16
+ readonly IMAGE: "image";
17
+ readonly VIDEO: "video";
18
+ readonly NEWS: "news";
19
+ readonly DISCOVER: "discover";
20
+ readonly GOOGLE_NEWS: "googleNews";
21
+ };
22
+ type SearchType = typeof SearchTypes[keyof typeof SearchTypes];
23
+ declare const Countries: { [K in (typeof _default)[number]["alpha-3"]]: Lowercase<K>; };
24
+ type Country = typeof Countries[keyof typeof Countries];
25
+ interface DimensionValueMap {
26
+ query: string;
27
+ queryCanonical: string;
28
+ page: string;
29
+ country: Country;
30
+ device: Device;
31
+ searchAppearance: string;
32
+ date: string;
33
+ /** Hour bucket — ISO-8601 with PT offset, e.g. `2025-07-14T13:00:00-07:00`. Use with `dataState: 'hourly_all'`. */
34
+ hour: string;
35
+ }
36
+ type Dimension = keyof DimensionValueMap;
37
+ interface QueryParamValueMap {
38
+ searchType: SearchType;
39
+ }
40
+ type QueryParamName = keyof QueryParamValueMap;
41
+ interface Column<D extends Dimension> {
42
+ readonly __columnBrand: 'gscdump.Column';
43
+ readonly dimension: D;
44
+ }
45
+ interface QueryParam<P extends QueryParamName> {
46
+ readonly __queryParamBrand: 'gscdump.QueryParam';
47
+ readonly param: P;
48
+ }
49
+ type FilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'includingRegex' | 'excludingRegex';
50
+ type DateOperator = 'gte' | 'gt' | 'lte' | 'lt' | 'between';
51
+ type MetricOperator = 'metricGte' | 'metricGt' | 'metricLte' | 'metricLt' | 'metricBetween';
52
+ type SpecialOperator = 'topLevel';
53
+ interface InternalFilter {
54
+ dimension: Dimension | QueryParamName | Metric;
55
+ operator: FilterOperator | DateOperator | MetricOperator | SpecialOperator;
56
+ expression: string;
57
+ expression2?: string;
58
+ }
59
+ interface Filter<C = object> {
60
+ readonly __filterBrand: 'gscdump.Filter';
61
+ readonly _constraints: C;
62
+ readonly _filters: InternalFilter[];
63
+ readonly _nestedGroups?: Filter<any>[];
64
+ readonly _groupType?: 'and' | 'or';
65
+ }
66
+ type MergeConstraints<F extends Filter<any>[]> = UnionToIntersection<F[number]['_constraints']>;
67
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
68
+ interface GSCResult<D extends Dimension[], C> {
69
+ rows: Array<GSCRow<D, C>>;
70
+ }
71
+ type GSCRow<D extends Dimension[], C> = { [K in D[number]]: K extends keyof C ? C[K] : DimensionValueMap[K]; } & {
72
+ clicks: number;
73
+ impressions: number;
74
+ ctr: number;
75
+ position: number;
76
+ };
77
+ type Metric = 'clicks' | 'impressions' | 'ctr' | 'position';
78
+ interface MetricColumn<M extends Metric> {
79
+ readonly __metricColumnBrand: 'gscdump.MetricColumn';
80
+ readonly metric: M;
81
+ }
82
+ interface BuilderState {
83
+ dimensions: Dimension[];
84
+ metrics?: Metric[];
85
+ filter?: Filter<any>;
86
+ prefilter?: Filter<any>;
87
+ orderBy?: {
88
+ column: Metric | 'date';
89
+ dir: 'asc' | 'desc';
90
+ };
91
+ rowLimit?: number;
92
+ startRow?: number;
93
+ /** GSC `dataState`. `'hourly_all'` is required when grouping by `hour`. */
94
+ dataState?: GscDataState;
95
+ /** GSC `aggregationType`. `'byNewsShowcasePanel'` requires `type=discover|googleNews` with NEWS_SHOWCASE searchAppearance. */
96
+ aggregationType?: GscAggregationType;
97
+ /** GSC search corpus. Wins over any `searchType` filter when both are set. */
98
+ searchType?: SearchType;
99
+ }
100
+ interface JsonInternalFilter {
101
+ dimension: string;
102
+ operator: string;
103
+ expression: string;
104
+ expression2?: string;
105
+ }
106
+ interface JsonFilter {
107
+ _filters: JsonInternalFilter[];
108
+ _nestedGroups?: JsonFilter[];
109
+ _groupType?: 'and' | 'or';
110
+ }
111
+ type FilterInput = Filter<any> | JsonFilter;
112
+ export { BuilderState, Column, Countries, Country, Device, Devices, Dimension, DimensionValueMap, Filter, FilterInput, FilterOperator, GSCResult, GSCRow, InternalFilter, JsonFilter, JsonInternalFilter, MergeConstraints, Metric, MetricColumn, MetricOperator, QueryParam, QueryParamName, QueryParamValueMap, SearchType, SearchTypes };
@@ -1,47 +1,2 @@
1
- import { ColumnDef, ColumnType, Row, TableName, TableSchema, TenantCtx } from "@gscdump/contracts";
2
- type GscSearchAnalyticsDimension = 'page' | 'query' | 'country' | 'device' | 'date' | 'hour' | 'searchAppearance';
3
- type GscDataState = 'final' | 'all' | 'hourly_all';
4
- interface GscSearchAnalyticsMetadata {
5
- /** First date (YYYY-MM-DD, PT) still being collected. Populated when dataState=`all` and grouped by `date`. */
6
- first_incomplete_date?: string;
7
- /** First hour (YYYY-MM-DDThh:mm:ss±hh:mm, PT) still being collected. Populated when dataState=`hourly_all` and grouped by `hour`. */
8
- first_incomplete_hour?: string;
9
- }
10
- type GscSearchAnalyticsFilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'includingRegex' | 'excludingRegex';
11
- interface GscSearchAnalyticsFilter {
12
- dimension: GscSearchAnalyticsDimension;
13
- expression: string;
14
- operator?: GscSearchAnalyticsFilterOperator;
15
- }
16
- interface GscSearchAnalyticsFilterGroup {
17
- groupType?: 'and' | 'or';
18
- filters: GscSearchAnalyticsFilter[];
19
- }
20
- type GscSearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';
21
- type GscAggregationType = 'auto' | 'byPage' | 'byProperty' | 'byNewsShowcasePanel';
22
- type GscResponseAggregationType = 'auto' | 'byPage' | 'byProperty' | 'byNewsShowcasePanel';
23
- interface GscSearchAnalyticsRequest {
24
- startDate: string;
25
- endDate: string;
26
- dimensions?: GscSearchAnalyticsDimension[];
27
- dimensionFilterGroups?: GscSearchAnalyticsFilterGroup[];
28
- rowLimit?: number;
29
- startRow?: number;
30
- /** GSC search corpus. Maps to wire field `type` (the API still accepts the deprecated `searchType` alias). */
31
- type?: GscSearchType;
32
- dataState?: GscDataState;
33
- aggregationType?: GscAggregationType;
34
- }
35
- interface GscSearchAnalyticsRow {
36
- keys: string[];
37
- clicks: number;
38
- impressions: number;
39
- ctr: number;
40
- position: number;
41
- }
42
- interface GscSearchAnalyticsResponse {
43
- rows?: GscSearchAnalyticsRow[];
44
- responseAggregationType?: GscResponseAggregationType;
45
- metadata?: GscSearchAnalyticsMetadata;
46
- }
1
+ import { ColumnDef, ColumnType, GscAggregationType, GscDataState, GscResponseAggregationType, GscSearchAnalyticsDimension, GscSearchAnalyticsFilter, GscSearchAnalyticsFilterGroup, GscSearchAnalyticsFilterOperator, GscSearchAnalyticsMetadata, GscSearchAnalyticsRequest, GscSearchAnalyticsResponse, GscSearchAnalyticsRow, GscSearchType, Row, TableName, TableSchema, TenantCtx } from "./_chunks/contracts.mjs";
47
2
  export { type ColumnDef, type ColumnType, GscAggregationType, GscDataState, GscResponseAggregationType, GscSearchAnalyticsDimension, GscSearchAnalyticsFilter, GscSearchAnalyticsFilterGroup, GscSearchAnalyticsFilterOperator, GscSearchAnalyticsMetadata, GscSearchAnalyticsRequest, GscSearchAnalyticsResponse, GscSearchAnalyticsRow, GscSearchType, type Row, type TableName, type TableSchema, type TenantCtx };
@@ -1,20 +1,2 @@
1
- interface Ok<A> {
2
- readonly ok: true;
3
- readonly value: A;
4
- }
5
- interface Err<E> {
6
- readonly ok: false;
7
- readonly error: E;
8
- }
9
- type Result<A, E> = Ok<A> | Err<E>;
10
- declare function ok<A>(value: A): Ok<A>;
11
- declare function err<E>(error: E): Err<E>;
12
- declare function isOk<A, E>(result: Result<A, E>): result is Ok<A>;
13
- declare function isErr<A, E>(result: Result<A, E>): result is Err<E>;
14
- /**
15
- * Collapses a `Result` back into the throwing world: returns the value or throws
16
- * via `toError`. Used by the throwing wrappers that sit over the `Result` core so
17
- * existing call sites keep their `await`/`throw` ergonomics.
18
- */
19
- declare function unwrapResult<A, E>(result: Result<A, E>, toError: (error: E) => unknown): A;
1
+ import { Err, Ok, Result, err, isErr, isOk, ok, unwrapResult } from "../_chunks/result.mjs";
20
2
  export { Err, Ok, Result, err, isErr, isOk, ok, unwrapResult };
package/dist/dates.d.mts CHANGED
@@ -1,63 +1,3 @@
1
- /** Milliseconds in a UTC day. Use for date arithmetic without DST surprises. */
2
- declare const MS_PER_DAY = 86400000;
3
- /** Format a Date as YYYY-MM-DD (UTC). */
4
- declare function toIsoDate(d: Date): string;
5
- /** Most recent date GSC has fully finalized data for (no further updates). */
6
- declare const GSC_FINALIZED_LAG_DAYS = 3;
7
- /** Most recent date GSC will return data for, may still be updating. */
8
- declare const GSC_FRESHEST_LAG_DAYS = 1;
9
- /** Approximate historical retention window for Search Analytics. */
10
- declare const GSC_RETENTION_MONTHS = 16;
11
- /** Today's date (YYYY-MM-DD) in PST. */
12
- declare function getPstDate(): string;
13
- /** YYYY-MM-DD for `now() - n` days, UTC. */
14
- declare function daysAgo(n: number): string;
15
- /** Most recent finalized date (3 days ago PST). */
16
- declare function getLatestGscDate(): string;
17
- /** Freshest date GSC will return (yesterday PST, may still update). */
18
- declare function getFreshestGscDate(): string;
19
- /**
20
- * Dates that are still pending (1-3 days ago PST). These need to be re-synced
21
- * each day until they finalize.
22
- */
23
- declare function getPendingDates(): string[];
24
- /** All dates between two YYYY-MM-DD strings (inclusive, oldest first). */
25
- declare function getDateRange(startDate: string, endDate: string): string[];
26
- /** Default span used when chunking long backfills into batches. */
27
- declare const DAYS_PER_RANGE = 30;
28
- /**
29
- * Like {@link getDateRange} but skips dates outside GSC's queryable window
30
- * (older than retention or newer than the freshest date).
31
- */
32
- declare function generateGscDateRange(startDate: string, endDate: string): string[];
33
- /**
34
- * Group a sorted list of dates into contiguous runs, splitting on either a
35
- * gap or after `daysPerRange` dates accumulate. Useful for bucketing
36
- * backfill work into bounded jobs.
37
- */
38
- declare function groupIntoRanges(dates: string[], daysPerRange?: number): Array<{
39
- startDate: string;
40
- endDate: string;
41
- }>;
42
- /** Inclusive day count between two YYYY-MM-DD strings. */
43
- declare function countDays(startDate: string, endDate: string): number;
44
- /** Oldest date GSC retains (~16 months ago). */
45
- declare function getOldestGscDate(): string;
46
- /** Add `n` UTC days to a YYYY-MM-DD string (n may be negative). */
47
- declare function addDays(dateStr: string, n: number): string;
48
- declare function getNextDate(dateStr: string): string;
49
- interface BackfillProgress {
50
- progress: number;
51
- daysAvailable: number;
52
- daysSynced: number;
53
- oldestGscDate: string;
54
- isComplete: boolean;
55
- }
56
- /**
57
- * Backfill progress (0-1) given the oldest + newest dates synced.
58
- * Returns null when no sync data exists.
59
- */
60
- declare function getBackfillProgress(oldestDateSynced: string | null, newestDateSynced: string | null): BackfillProgress | null;
61
- declare function currentPstDate(): string;
62
- declare function daysAgoPst(n: number): string;
1
+ import { DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_RETENTION_MONTHS, MS_PER_DAY, addDays, countDays, daysAgo, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPstDate, groupIntoRanges, toIsoDate } from "./_chunks/gsc-dates.mjs";
2
+ import { currentPstDate, daysAgoPst } from "./_chunks/dayjs.mjs";
63
3
  export { DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_RETENTION_MONTHS, MS_PER_DAY, addDays, countDays, currentPstDate, daysAgoPst, daysAgo as daysAgoUtc, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPstDate, groupIntoRanges, toIsoDate };
package/dist/dates.mjs CHANGED
@@ -1,119 +1,3 @@
1
- import { format } from "date-fns/format";
2
- import { subDays } from "date-fns/subDays";
3
- const MS_PER_DAY = 864e5;
4
- function toIsoDate(d) {
5
- return d.toISOString().slice(0, 10);
6
- }
7
- const GSC_FINALIZED_LAG_DAYS = 3;
8
- const GSC_FRESHEST_LAG_DAYS = 1;
9
- const GSC_RETENTION_MONTHS = 16;
10
- function getPstDate() {
11
- return (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", { timeZone: "America/Los_Angeles" });
12
- }
13
- function getPstDateDaysAgo(daysAgo) {
14
- const pstNow = new Date((/* @__PURE__ */ new Date()).toLocaleString("en-US", { timeZone: "America/Los_Angeles" }));
15
- pstNow.setDate(pstNow.getDate() - daysAgo);
16
- return toIsoDate(pstNow);
17
- }
18
- function daysAgo(n) {
19
- return toIsoDate(/* @__PURE__ */ new Date(Date.now() - n * MS_PER_DAY));
20
- }
21
- function getLatestGscDate() {
22
- return getPstDateDaysAgo(3);
23
- }
24
- function getFreshestGscDate() {
25
- return getPstDateDaysAgo(1);
26
- }
27
- function getPendingDates() {
28
- const dates = [];
29
- for (let daysAgo = 1; daysAgo <= 3; daysAgo++) dates.push(getPstDateDaysAgo(daysAgo));
30
- return dates;
31
- }
32
- function getDateRange(startDate, endDate) {
33
- const dates = [];
34
- const endMs = Date.parse(`${endDate}T00:00:00Z`);
35
- for (let cursor = Date.parse(`${startDate}T00:00:00Z`); cursor <= endMs; cursor += MS_PER_DAY) dates.push(toIsoDate(new Date(cursor)));
36
- return dates;
37
- }
38
- const DAYS_PER_RANGE = 30;
39
- function generateGscDateRange(startDate, endDate) {
40
- const start = startDate < getOldestGscDate() ? getOldestGscDate() : startDate;
41
- const end = endDate > getFreshestGscDate() ? getFreshestGscDate() : endDate;
42
- return start <= end ? getDateRange(start, end) : [];
43
- }
44
- function groupIntoRanges(dates, daysPerRange = 30) {
45
- if (dates.length === 0) return [];
46
- const sorted = [...dates].sort();
47
- const ranges = [];
48
- let rangeStart = sorted[0];
49
- let rangePrev = sorted[0];
50
- for (let i = 1; i < sorted.length; i++) {
51
- const current = sorted[i];
52
- const expected = getNextDate(rangePrev);
53
- const daysInRange = countDays(rangeStart, rangePrev);
54
- if (current !== expected || daysInRange >= daysPerRange) {
55
- ranges.push({
56
- startDate: rangeStart,
57
- endDate: rangePrev
58
- });
59
- rangeStart = current;
60
- }
61
- rangePrev = current;
62
- }
63
- ranges.push({
64
- startDate: rangeStart,
65
- endDate: rangePrev
66
- });
67
- return ranges;
68
- }
69
- function countDays(startDate, endDate) {
70
- return Math.round((Date.parse(`${endDate}T00:00:00Z`) - Date.parse(`${startDate}T00:00:00Z`)) / MS_PER_DAY) + 1;
71
- }
72
- function getOldestGscDate() {
73
- const date = /* @__PURE__ */ new Date();
74
- date.setMonth(date.getMonth() - 16);
75
- return toIsoDate(date);
76
- }
77
- function addDays(dateStr, n) {
78
- return toIsoDate(new Date(Date.parse(`${dateStr}T00:00:00Z`) + n * MS_PER_DAY));
79
- }
80
- function getNextDate(dateStr) {
81
- return addDays(dateStr, 1);
82
- }
83
- function getBackfillProgress(oldestDateSynced, newestDateSynced) {
84
- if (!oldestDateSynced || !newestDateSynced) return null;
85
- const oldestGsc = getOldestGscDate();
86
- const totalDays = countDays(oldestGsc, getLatestGscDate());
87
- const syncedDays = countDays(oldestDateSynced, newestDateSynced);
88
- return {
89
- progress: Math.round(Math.min(1, syncedDays / totalDays) * 100) / 100,
90
- daysAvailable: totalDays,
91
- daysSynced: syncedDays,
92
- oldestGscDate: oldestGsc,
93
- isComplete: oldestDateSynced <= oldestGsc
94
- };
95
- }
96
- const PST_FORMATTER = new Intl.DateTimeFormat("en-CA", {
97
- timeZone: "America/Los_Angeles",
98
- year: "numeric",
99
- month: "2-digit",
100
- day: "2-digit"
101
- });
102
- function pstDateParts(d = /* @__PURE__ */ new Date()) {
103
- const parts = PST_FORMATTER.formatToParts(d);
104
- const get = (t) => Number(parts.find((p) => p.type === t).value);
105
- return {
106
- year: get("year"),
107
- month: get("month"),
108
- day: get("day")
109
- };
110
- }
111
- function currentPstDate() {
112
- const { year, month, day } = pstDateParts();
113
- return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
114
- }
115
- function daysAgoPst(n) {
116
- const { year, month, day } = pstDateParts();
117
- return format(subDays(new Date(year, month - 1, day, 12), n), "yyyy-MM-dd");
118
- }
1
+ import { DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_RETENTION_MONTHS, MS_PER_DAY, addDays, countDays, daysAgo, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPstDate, groupIntoRanges, toIsoDate } from "./_chunks/gsc-dates.mjs";
2
+ import { currentPstDate, daysAgoPst } from "./_chunks/dayjs.mjs";
119
3
  export { DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_RETENTION_MONTHS, MS_PER_DAY, addDays, countDays, currentPstDate, daysAgoPst, daysAgo as daysAgoUtc, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPstDate, groupIntoRanges, toIsoDate };
package/dist/index.d.mts CHANGED
@@ -1,3 +1,10 @@
1
+ import { GscResponseAggregationType, GscSearchAnalyticsMetadata } from "./_chunks/contracts.mjs";
2
+ import { Err, Ok, Result, err, isErr, isOk, ok, unwrapResult } from "./_chunks/result.mjs";
3
+ import { BackfillProgress, DAYS_PER_RANGE, GSC_FINALIZED_LAG_DAYS, GSC_FRESHEST_LAG_DAYS, GSC_RETENTION_MONTHS, MS_PER_DAY, addDays, countDays, generateGscDateRange, getBackfillProgress, getDateRange, getFreshestGscDate, getLatestGscDate, getNextDate, getOldestGscDate, getPendingDates, getPreviousDate, getPstDate, groupIntoRanges, isValidGscDate, toIsoDate } from "./_chunks/gsc-dates.mjs";
4
+ import { Dimension, GSCRow } from "./_chunks/types.mjs";
5
+ import { GSCQueryBuilder } from "./_chunks/builder.mjs";
6
+ import { normalizeUrl } from "./normalize.mjs";
7
+ import { decodeSiteId, encodeSiteId, normalizeSiteUrl } from "./tenant.mjs";
1
8
  import { $Fetch, FetchOptions } from "ofetch";
2
9
  import { AccountNextAction, AccountStatus, AnalyticsNextAction, AnalyticsStatus, GSCDUMP_ONBOARDING_CONTRACT_VERSION, GSCDUMP_OPTIONAL_INDEXING_SCOPE, GSCDUMP_REQUIRED_ANALYTICS_SCOPE, GSCDUMP_WRITE_ANALYTICS_SCOPE, IndexingNextAction, IndexingStatus, LifecycleError, LifecycleErrorCode, LifecycleProgress, LifecycleWebhookEnvelope, LifecycleWebhookEvent, PartnerLifecycleAccount, PartnerLifecycleResponse, PartnerLifecycleSite, PropertyNextAction, PropertyStatus, QuerySourceMode, SitemapNextAction, SitemapStatus, accountNextActions, accountStatuses, analyticsNextActions, analyticsStatuses, hasOptionalIndexingScope, hasRequiredAnalyticsScope, indexingNextActions, indexingStatuses, lifecycleErrorCodes, parseGrantedScopes, propertyNextActions, propertyStatuses, querySourceModes, sitemapNextActions, sitemapStatuses } from "@gscdump/contracts/partner";
3
10
  /**
@@ -11,148 +18,6 @@ declare function runSequentialBatch<I, R>(items: I[], operation: (item: I, index
11
18
  concurrency?: number;
12
19
  onProgress?: (result: R, index: number, total: number) => void;
13
20
  }): Promise<R[]>;
14
- type GscSearchAnalyticsDimension = 'page' | 'query' | 'country' | 'device' | 'date' | 'hour' | 'searchAppearance';
15
- type GscDataState = 'final' | 'all' | 'hourly_all';
16
- interface GscSearchAnalyticsMetadata {
17
- /** First date (YYYY-MM-DD, PT) still being collected. Populated when dataState=`all` and grouped by `date`. */
18
- first_incomplete_date?: string;
19
- /** First hour (YYYY-MM-DDThh:mm:ss±hh:mm, PT) still being collected. Populated when dataState=`hourly_all` and grouped by `hour`. */
20
- first_incomplete_hour?: string;
21
- }
22
- type GscSearchAnalyticsFilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'includingRegex' | 'excludingRegex';
23
- interface GscSearchAnalyticsFilter {
24
- dimension: GscSearchAnalyticsDimension;
25
- expression: string;
26
- operator?: GscSearchAnalyticsFilterOperator;
27
- }
28
- interface GscSearchAnalyticsFilterGroup {
29
- groupType?: 'and' | 'or';
30
- filters: GscSearchAnalyticsFilter[];
31
- }
32
- type GscSearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';
33
- type GscAggregationType = 'auto' | 'byPage' | 'byProperty' | 'byNewsShowcasePanel';
34
- type GscResponseAggregationType = 'auto' | 'byPage' | 'byProperty' | 'byNewsShowcasePanel';
35
- interface GscSearchAnalyticsRequest {
36
- startDate: string;
37
- endDate: string;
38
- dimensions?: GscSearchAnalyticsDimension[];
39
- dimensionFilterGroups?: GscSearchAnalyticsFilterGroup[];
40
- rowLimit?: number;
41
- startRow?: number;
42
- /** GSC search corpus. Maps to wire field `type` (the API still accepts the deprecated `searchType` alias). */
43
- type?: GscSearchType;
44
- dataState?: GscDataState;
45
- aggregationType?: GscAggregationType;
46
- }
47
- declare const _default: {
48
- name: string;
49
- 'alpha-2': string;
50
- 'alpha-3': string;
51
- 'country-code': string;
52
- }[];
53
- declare const Devices: {
54
- readonly MOBILE: "MOBILE";
55
- readonly DESKTOP: "DESKTOP";
56
- readonly TABLET: "TABLET";
57
- };
58
- type Device = typeof Devices[keyof typeof Devices];
59
- declare const SearchTypes: {
60
- readonly WEB: "web";
61
- readonly IMAGE: "image";
62
- readonly VIDEO: "video";
63
- readonly NEWS: "news";
64
- readonly DISCOVER: "discover";
65
- readonly GOOGLE_NEWS: "googleNews";
66
- };
67
- type SearchType = typeof SearchTypes[keyof typeof SearchTypes];
68
- declare const Countries: { [K in (typeof _default)[number]["alpha-3"]]: Lowercase<K>; };
69
- type Country = typeof Countries[keyof typeof Countries];
70
- interface DimensionValueMap {
71
- query: string;
72
- queryCanonical: string;
73
- page: string;
74
- country: Country;
75
- device: Device;
76
- searchAppearance: string;
77
- date: string;
78
- /** Hour bucket — ISO-8601 with PT offset, e.g. `2025-07-14T13:00:00-07:00`. Use with `dataState: 'hourly_all'`. */
79
- hour: string;
80
- }
81
- type Dimension = keyof DimensionValueMap;
82
- interface QueryParamValueMap {
83
- searchType: SearchType;
84
- }
85
- type QueryParamName = keyof QueryParamValueMap;
86
- interface Column<D extends Dimension> {
87
- readonly __columnBrand: 'gscdump.Column';
88
- readonly dimension: D;
89
- }
90
- type FilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'includingRegex' | 'excludingRegex';
91
- type DateOperator = 'gte' | 'gt' | 'lte' | 'lt' | 'between';
92
- type MetricOperator = 'metricGte' | 'metricGt' | 'metricLte' | 'metricLt' | 'metricBetween';
93
- type SpecialOperator = 'topLevel';
94
- interface InternalFilter {
95
- dimension: Dimension | QueryParamName | Metric;
96
- operator: FilterOperator | DateOperator | MetricOperator | SpecialOperator;
97
- expression: string;
98
- expression2?: string;
99
- }
100
- interface Filter<C = object> {
101
- readonly __filterBrand: 'gscdump.Filter';
102
- readonly _constraints: C;
103
- readonly _filters: InternalFilter[];
104
- readonly _nestedGroups?: Filter<any>[];
105
- readonly _groupType?: 'and' | 'or';
106
- }
107
- type GSCRow<D extends Dimension[], C> = { [K in D[number]]: K extends keyof C ? C[K] : DimensionValueMap[K]; } & {
108
- clicks: number;
109
- impressions: number;
110
- ctr: number;
111
- position: number;
112
- };
113
- type Metric = 'clicks' | 'impressions' | 'ctr' | 'position';
114
- interface MetricColumn<M extends Metric> {
115
- readonly __metricColumnBrand: 'gscdump.MetricColumn';
116
- readonly metric: M;
117
- }
118
- interface BuilderState {
119
- dimensions: Dimension[];
120
- metrics?: Metric[];
121
- filter?: Filter<any>;
122
- prefilter?: Filter<any>;
123
- orderBy?: {
124
- column: Metric | 'date';
125
- dir: 'asc' | 'desc';
126
- };
127
- rowLimit?: number;
128
- startRow?: number;
129
- /** GSC `dataState`. `'hourly_all'` is required when grouping by `hour`. */
130
- dataState?: GscDataState;
131
- /** GSC `aggregationType`. `'byNewsShowcasePanel'` requires `type=discover|googleNews` with NEWS_SHOWCASE searchAppearance. */
132
- aggregationType?: GscAggregationType;
133
- /** GSC search corpus. Wins over any `searchType` filter when both are set. */
134
- searchType?: SearchType;
135
- }
136
- type SelectableColumn = Column<Dimension> | MetricColumn<Metric>;
137
- type OrderableColumn = MetricColumn<Metric> | Column<'date'>;
138
- 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;
139
- interface GSCQueryBuilder<D extends Dimension[] = [], C = object> {
140
- select: {
141
- <T extends Dimension[]>(...dims: T): GSCQueryBuilder<T, C>;
142
- <T extends SelectableColumn[]>(...cols: T): GSCQueryBuilder<ExtractDimensions<T> & Dimension[], C>;
143
- };
144
- where: <F extends Filter<any>>(filter: F) => GSCQueryBuilder<D, C & F['_constraints']>;
145
- prefilter: <F extends Filter<any>>(filter: F) => GSCQueryBuilder<D, C>;
146
- orderBy: (col: OrderableColumn, dir: 'asc' | 'desc') => GSCQueryBuilder<D, C>;
147
- limit: (n: number) => GSCQueryBuilder<D, C>;
148
- offset: (n: number) => GSCQueryBuilder<D, C>;
149
- dataState: (state: GscDataState) => GSCQueryBuilder<D, C>;
150
- aggregationType: (type: GscAggregationType) => GSCQueryBuilder<D, C>;
151
- /** GSC search corpus (`type` on the wire). Equivalent to filtering by `searchType`. */
152
- type: (t: GscSearchType) => GSCQueryBuilder<D, C>;
153
- toBody: () => GscSearchAnalyticsRequest;
154
- getState: () => BuilderState;
155
- }
156
21
  /** Search Console property returned by the Sites resource. */
157
22
  interface ApiSite {
158
23
  permissionLevel?: string | null;
@@ -654,25 +519,6 @@ declare function rethrowAsGscApiError(prefix: string): (err: unknown) => never;
654
519
  * needs the permission verdict.
655
520
  */
656
521
  declare function isPermissionDeniedError(err: unknown): boolean;
657
- interface Ok<A> {
658
- readonly ok: true;
659
- readonly value: A;
660
- }
661
- interface Err<E> {
662
- readonly ok: false;
663
- readonly error: E;
664
- }
665
- type Result<A, E> = Ok<A> | Err<E>;
666
- declare function ok<A>(value: A): Ok<A>;
667
- declare function err<E>(error: E): Err<E>;
668
- declare function isOk<A, E>(result: Result<A, E>): result is Ok<A>;
669
- declare function isErr<A, E>(result: Result<A, E>): result is Err<E>;
670
- /**
671
- * Collapses a `Result` back into the throwing world: returns the value or throws
672
- * via `toError`. Used by the throwing wrappers that sit over the `Result` core so
673
- * existing call sites keep their `await`/`throw` ergonomics.
674
- */
675
- declare function unwrapResult<A, E>(result: Result<A, E>, toError: (error: E) => unknown): A;
676
522
  interface OAuthTokens {
677
523
  accessToken: string;
678
524
  /** Unix seconds. */
@@ -801,67 +647,6 @@ declare function getVerifiedSite(client: GoogleSearchConsoleClient, id: string):
801
647
  * on the property are unaffected.
802
648
  */
803
649
  declare function unverifySite(client: GoogleSearchConsoleClient, id: string): Promise<void>;
804
- /** Milliseconds in a UTC day. Use for date arithmetic without DST surprises. */
805
- declare const MS_PER_DAY = 86400000;
806
- /** Format a Date as YYYY-MM-DD (UTC). */
807
- declare function toIsoDate(d: Date): string;
808
- /** Most recent date GSC has fully finalized data for (no further updates). */
809
- declare const GSC_FINALIZED_LAG_DAYS = 3;
810
- /** Most recent date GSC will return data for, may still be updating. */
811
- declare const GSC_FRESHEST_LAG_DAYS = 1;
812
- /** Approximate historical retention window for Search Analytics. */
813
- declare const GSC_RETENTION_MONTHS = 16;
814
- /** Today's date (YYYY-MM-DD) in PST. */
815
- declare function getPstDate(): string;
816
- /** Most recent finalized date (3 days ago PST). */
817
- declare function getLatestGscDate(): string;
818
- /** Freshest date GSC will return (yesterday PST, may still update). */
819
- declare function getFreshestGscDate(): string;
820
- /**
821
- * Dates that are still pending (1-3 days ago PST). These need to be re-synced
822
- * each day until they finalize.
823
- */
824
- declare function getPendingDates(): string[];
825
- /** All dates between two YYYY-MM-DD strings (inclusive, oldest first). */
826
- declare function getDateRange(startDate: string, endDate: string): string[];
827
- /** Default span used when chunking long backfills into batches. */
828
- declare const DAYS_PER_RANGE = 30;
829
- /**
830
- * Like {@link getDateRange} but skips dates outside GSC's queryable window
831
- * (older than retention or newer than the freshest date).
832
- */
833
- declare function generateGscDateRange(startDate: string, endDate: string): string[];
834
- /**
835
- * Group a sorted list of dates into contiguous runs, splitting on either a
836
- * gap or after `daysPerRange` dates accumulate. Useful for bucketing
837
- * backfill work into bounded jobs.
838
- */
839
- declare function groupIntoRanges(dates: string[], daysPerRange?: number): Array<{
840
- startDate: string;
841
- endDate: string;
842
- }>;
843
- /** Inclusive day count between two YYYY-MM-DD strings. */
844
- declare function countDays(startDate: string, endDate: string): number;
845
- /** Oldest date GSC retains (~16 months ago). */
846
- declare function getOldestGscDate(): string;
847
- /** Add `n` UTC days to a YYYY-MM-DD string (n may be negative). */
848
- declare function addDays(dateStr: string, n: number): string;
849
- declare function getPreviousDate(dateStr: string): string;
850
- declare function getNextDate(dateStr: string): string;
851
- /** True if `dateStr` falls within GSC's queryable window. */
852
- declare function isValidGscDate(dateStr: string): boolean;
853
- interface BackfillProgress {
854
- progress: number;
855
- daysAvailable: number;
856
- daysSynced: number;
857
- oldestGscDate: string;
858
- isComplete: boolean;
859
- }
860
- /**
861
- * Backfill progress (0-1) given the oldest + newest dates synced.
862
- * Returns null when no sync data exists.
863
- */
864
- declare function getBackfillProgress(oldestDateSynced: string | null, newestDateSynced: string | null): BackfillProgress | null;
865
650
  declare const INDEXING_ISSUE_FILTERS: {
866
651
  readonly canonical_mismatch: "user_canonical IS NOT NULL AND google_canonical IS NOT NULL AND user_canonical != google_canonical";
867
652
  readonly stale_crawl: "last_crawl_time < datetime('now', '-30 days')";
@@ -996,7 +781,6 @@ declare function normalizeGscSiteUrl(siteUrl: string): string;
996
781
  * Returns lowercase hostname stripped of protocol, or null if unparseable.
997
782
  */
998
783
  declare function normalizeRegistrationTarget(inputUrl: string): string | null;
999
- declare function normalizeUrl(input: string): string;
1000
784
  interface DiscoverSitemapOptions {
1001
785
  /** User-Agent sent on the discovery requests. */
1002
786
  userAgent?: string;
@@ -1022,23 +806,6 @@ interface FetchSitemapUrlsOptions extends DiscoverSitemapOptions {
1022
806
  * `<loc>https://...</loc>` shape but doesn't validate the schema.
1023
807
  */
1024
808
  declare function fetchSitemapUrls(sitemapUrl: string, options?: FetchSitemapUrlsOptions): Promise<string[]>;
1025
- declare function encodeSiteId(siteUrl: string): string;
1026
- /**
1027
- * Best-effort inverse of `encodeSiteId` for the common prefixes. Lossy
1028
- * (`encodeSiteId` collapses non-word chars to `_` and strips trailing
1029
- * underscores), but round-trips domain properties + https origins cleanly —
1030
- * the only two shapes GSC hands out in practice.
1031
- *
1032
- * Returns the input unchanged when neither prefix is recognised, so callers
1033
- * can pass through canonical site URLs without branching.
1034
- */
1035
- declare function decodeSiteId(encoded: string): string;
1036
- /**
1037
- * Normalize a siteUrl to the form Google APIs expect: domain properties get
1038
- * the `sc-domain:` prefix added if missing, URL properties pass through.
1039
- * Idempotent — safe to call on already-prefixed values.
1040
- */
1041
- declare function normalizeSiteUrl(siteUrl: string): string;
1042
809
  /**
1043
810
  * Equivalence key for matching two URLs that point at the same resource
1044
811
  * across protocol (http/https), www. prefix, trailing slash, and casing.