gscdump 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/builder.d.mts +24 -0
- package/dist/_chunks/contracts.d.mts +47 -0
- package/dist/_chunks/dayjs.d.mts +3 -0
- package/dist/_chunks/dayjs.mjs +30 -0
- package/dist/_chunks/gsc-dates.d.mts +64 -0
- package/dist/_chunks/gsc-dates.mjs +100 -0
- package/dist/_chunks/plan.d.mts +175 -0
- package/dist/_chunks/resolver.mjs +1930 -0
- package/dist/_chunks/result.d.mts +20 -0
- package/dist/_chunks/types.d.mts +112 -0
- package/dist/contracts.d.mts +1 -46
- package/dist/core/result.d.mts +1 -19
- package/dist/dates.d.mts +2 -62
- package/dist/dates.mjs +2 -117
- package/dist/index.d.mts +7 -240
- package/dist/index.mjs +5 -1930
- package/dist/query/index.d.mts +6 -323
- package/dist/query/index.mjs +3 -2138
- package/dist/query/plan.d.mts +2 -234
- package/dist/query/plan.mjs +2 -1809
- package/package.json +2 -2
|
@@ -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 };
|
package/dist/contracts.d.mts
CHANGED
|
@@ -1,47 +1,2 @@
|
|
|
1
|
-
import { ColumnDef, ColumnType, Row, TableName, TableSchema, TenantCtx } from "
|
|
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 };
|
package/dist/core/result.d.mts
CHANGED
|
@@ -1,20 +1,2 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
2
|
-
|
|
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,118 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
function toIsoDate(d) {
|
|
4
|
-
return d.toISOString().slice(0, 10);
|
|
5
|
-
}
|
|
6
|
-
const GSC_FINALIZED_LAG_DAYS = 3;
|
|
7
|
-
const GSC_FRESHEST_LAG_DAYS = 1;
|
|
8
|
-
const GSC_RETENTION_MONTHS = 16;
|
|
9
|
-
function getPstDate() {
|
|
10
|
-
return (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA", { timeZone: "America/Los_Angeles" });
|
|
11
|
-
}
|
|
12
|
-
function getPstDateDaysAgo(daysAgo) {
|
|
13
|
-
const pstNow = new Date((/* @__PURE__ */ new Date()).toLocaleString("en-US", { timeZone: "America/Los_Angeles" }));
|
|
14
|
-
pstNow.setDate(pstNow.getDate() - daysAgo);
|
|
15
|
-
return toIsoDate(pstNow);
|
|
16
|
-
}
|
|
17
|
-
function daysAgo(n) {
|
|
18
|
-
return toIsoDate(/* @__PURE__ */ new Date(Date.now() - n * MS_PER_DAY));
|
|
19
|
-
}
|
|
20
|
-
function getLatestGscDate() {
|
|
21
|
-
return getPstDateDaysAgo(3);
|
|
22
|
-
}
|
|
23
|
-
function getFreshestGscDate() {
|
|
24
|
-
return getPstDateDaysAgo(1);
|
|
25
|
-
}
|
|
26
|
-
function getPendingDates() {
|
|
27
|
-
const dates = [];
|
|
28
|
-
for (let daysAgo = 1; daysAgo <= 3; daysAgo++) dates.push(getPstDateDaysAgo(daysAgo));
|
|
29
|
-
return dates;
|
|
30
|
-
}
|
|
31
|
-
function getDateRange(startDate, endDate) {
|
|
32
|
-
const dates = [];
|
|
33
|
-
const endMs = Date.parse(`${endDate}T00:00:00Z`);
|
|
34
|
-
for (let cursor = Date.parse(`${startDate}T00:00:00Z`); cursor <= endMs; cursor += MS_PER_DAY) dates.push(toIsoDate(new Date(cursor)));
|
|
35
|
-
return dates;
|
|
36
|
-
}
|
|
37
|
-
const DAYS_PER_RANGE = 30;
|
|
38
|
-
function generateGscDateRange(startDate, endDate) {
|
|
39
|
-
const start = startDate < getOldestGscDate() ? getOldestGscDate() : startDate;
|
|
40
|
-
const end = endDate > getFreshestGscDate() ? getFreshestGscDate() : endDate;
|
|
41
|
-
return start <= end ? getDateRange(start, end) : [];
|
|
42
|
-
}
|
|
43
|
-
function groupIntoRanges(dates, daysPerRange = 30) {
|
|
44
|
-
if (dates.length === 0) return [];
|
|
45
|
-
const sorted = [...dates].sort();
|
|
46
|
-
const ranges = [];
|
|
47
|
-
let rangeStart = sorted[0];
|
|
48
|
-
let rangePrev = sorted[0];
|
|
49
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
50
|
-
const current = sorted[i];
|
|
51
|
-
const expected = getNextDate(rangePrev);
|
|
52
|
-
const daysInRange = countDays(rangeStart, rangePrev);
|
|
53
|
-
if (current !== expected || daysInRange >= daysPerRange) {
|
|
54
|
-
ranges.push({
|
|
55
|
-
startDate: rangeStart,
|
|
56
|
-
endDate: rangePrev
|
|
57
|
-
});
|
|
58
|
-
rangeStart = current;
|
|
59
|
-
}
|
|
60
|
-
rangePrev = current;
|
|
61
|
-
}
|
|
62
|
-
ranges.push({
|
|
63
|
-
startDate: rangeStart,
|
|
64
|
-
endDate: rangePrev
|
|
65
|
-
});
|
|
66
|
-
return ranges;
|
|
67
|
-
}
|
|
68
|
-
function countDays(startDate, endDate) {
|
|
69
|
-
return Math.round((Date.parse(`${endDate}T00:00:00Z`) - Date.parse(`${startDate}T00:00:00Z`)) / MS_PER_DAY) + 1;
|
|
70
|
-
}
|
|
71
|
-
function getOldestGscDate() {
|
|
72
|
-
const date = /* @__PURE__ */ new Date();
|
|
73
|
-
date.setMonth(date.getMonth() - 16);
|
|
74
|
-
return toIsoDate(date);
|
|
75
|
-
}
|
|
76
|
-
function addDays(dateStr, n) {
|
|
77
|
-
return toIsoDate(new Date(Date.parse(`${dateStr}T00:00:00Z`) + n * MS_PER_DAY));
|
|
78
|
-
}
|
|
79
|
-
function getNextDate(dateStr) {
|
|
80
|
-
return addDays(dateStr, 1);
|
|
81
|
-
}
|
|
82
|
-
function getBackfillProgress(oldestDateSynced, newestDateSynced) {
|
|
83
|
-
if (!oldestDateSynced || !newestDateSynced) return null;
|
|
84
|
-
const oldestGsc = getOldestGscDate();
|
|
85
|
-
const totalDays = countDays(oldestGsc, getLatestGscDate());
|
|
86
|
-
const syncedDays = countDays(oldestDateSynced, newestDateSynced);
|
|
87
|
-
return {
|
|
88
|
-
progress: Math.round(Math.min(1, syncedDays / totalDays) * 100) / 100,
|
|
89
|
-
daysAvailable: totalDays,
|
|
90
|
-
daysSynced: syncedDays,
|
|
91
|
-
oldestGscDate: oldestGsc,
|
|
92
|
-
isComplete: oldestDateSynced <= oldestGsc
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const PST_FORMATTER = new Intl.DateTimeFormat("en-CA", {
|
|
96
|
-
timeZone: "America/Los_Angeles",
|
|
97
|
-
year: "numeric",
|
|
98
|
-
month: "2-digit",
|
|
99
|
-
day: "2-digit"
|
|
100
|
-
});
|
|
101
|
-
function pstDateParts(d = /* @__PURE__ */ new Date()) {
|
|
102
|
-
const parts = PST_FORMATTER.formatToParts(d);
|
|
103
|
-
const get = (t) => Number(parts.find((p) => p.type === t).value);
|
|
104
|
-
return {
|
|
105
|
-
year: get("year"),
|
|
106
|
-
month: get("month"),
|
|
107
|
-
day: get("day")
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
function currentPstDate() {
|
|
111
|
-
const { year, month, day } = pstDateParts();
|
|
112
|
-
return `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
113
|
-
}
|
|
114
|
-
function daysAgoPst(n) {
|
|
115
|
-
const { year, month, day } = pstDateParts();
|
|
116
|
-
return format(subDays(new Date(year, month - 1, day, 12), n), "yyyy-MM-dd");
|
|
117
|
-
}
|
|
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";
|
|
118
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.
|