@gscdump/sdk 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/canonical-json.mjs +6 -0
- package/dist/hosted-query.d.mts +7 -11
- package/dist/hosted-query.mjs +6 -30
- package/dist/lifecycle.d.mts +1 -2
- package/dist/lifecycle.mjs +1 -20
- package/dist/period.mjs +1 -2
- package/dist/request.mjs +2 -6
- package/dist/site-baseline.d.mts +1 -2
- package/dist/site-baseline.mjs +1 -1
- package/dist/v1/http.d.mts +20 -55
- package/dist/v1/http.mjs +25 -32
- package/dist/v1/realtime.d.mts +1 -1
- package/dist/v1/realtime.mjs +2 -2
- package/dist/webhook.d.mts +2 -20
- package/dist/webhook.mjs +2 -36
- package/package.json +3 -4
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
function canonicalJson(value) {
|
|
2
|
+
if (value == null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
3
|
+
if (Array.isArray(value)) return `[${Array.from(value, (item) => canonicalJson(item)).join(",")}]`;
|
|
4
|
+
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(",")}}`;
|
|
5
|
+
}
|
|
6
|
+
export { canonicalJson };
|
package/dist/hosted-query.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BuilderStateWire, DataDetailOptions, DataQueryOptions,
|
|
2
|
-
|
|
1
|
+
import { BuilderStateWire, DataDetailOptions, DataQueryOptions, IndexingDiagnosticsParams, IndexingUrlsParams, SourceInfoOptions } from "@gscdump/contracts";
|
|
2
|
+
import { GscSearchType, GscSearchType as GscSearchType$2 } from "@gscdump/contracts/search-types";
|
|
3
3
|
interface SearchTypeOptions {
|
|
4
|
-
searchType?: GscSearchType;
|
|
4
|
+
searchType?: GscSearchType$2;
|
|
5
5
|
}
|
|
6
6
|
interface SourceRangeOptions {
|
|
7
7
|
start?: string;
|
|
@@ -15,17 +15,13 @@ interface AnalysisSourcesOptions extends SearchTypeOptions, SourceRangeOptions {
|
|
|
15
15
|
maxRows?: number;
|
|
16
16
|
maxFiles?: number;
|
|
17
17
|
}
|
|
18
|
-
declare const DEFAULT_SEARCH_TYPE: GscSearchType;
|
|
19
|
-
declare function withDefaultSearchType<T extends object>(value: T, searchType?: GscSearchType): T & SearchTypeOptions & Record<string, unknown>;
|
|
20
|
-
declare function withDefaultSearchType<T>(value: T, searchType?: GscSearchType): T;
|
|
21
|
-
declare function searchTypeQuery(searchType?: GscSearchType): Record<string, string>;
|
|
22
|
-
declare function dateRangeOptionsQuery(options: SourceRangeOptions | undefined): Record<string, string>;
|
|
18
|
+
declare const DEFAULT_SEARCH_TYPE: GscSearchType$2;
|
|
19
|
+
declare function withDefaultSearchType<T extends object>(value: T, searchType?: GscSearchType$2): T & SearchTypeOptions & Record<string, unknown>;
|
|
20
|
+
declare function withDefaultSearchType<T>(value: T, searchType?: GscSearchType$2): T;
|
|
23
21
|
declare function sourceInfoQuery(options: SourceInfoOptions | undefined): Record<string, string>;
|
|
24
22
|
declare function tablesQuery(tablesOrOptions: string[] | string | AnalysisSourcesOptions | undefined, options?: AnalysisSourcesOptions): Record<string, string>;
|
|
25
23
|
declare function dataQuery(state: BuilderStateWire, options?: DataQueryOptions): Record<string, string>;
|
|
26
24
|
declare function dataDetailQuery(state: BuilderStateWire, options?: DataDetailOptions): Record<string, string>;
|
|
27
25
|
declare function indexingUrlsQuery(params?: IndexingUrlsParams): Record<string, string | number>;
|
|
28
26
|
declare function indexingDiagnosticsQuery(params?: IndexingDiagnosticsParams): Record<string, string | number>;
|
|
29
|
-
|
|
30
|
-
declare function pageTrendQuery(params: GscdumpPageTrendParams): Record<string, string>;
|
|
31
|
-
export { AnalysisSourcesOptions, DEFAULT_SEARCH_TYPE, GscSearchType, SearchTypeOptions, SourceRangeOptions, dataDetailQuery, dataQuery, dateRangeOptionsQuery, indexingDiagnosticsQuery, indexingUrlsQuery, pageTrendQuery, queryTrendQuery, searchTypeQuery, sourceInfoQuery, tablesQuery, withDefaultSearchType };
|
|
27
|
+
export { AnalysisSourcesOptions, DEFAULT_SEARCH_TYPE, type GscSearchType, SearchTypeOptions, SourceRangeOptions, dataDetailQuery, dataQuery, indexingDiagnosticsQuery, indexingUrlsQuery, sourceInfoQuery, tablesQuery, withDefaultSearchType };
|
package/dist/hosted-query.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canonicalJson } from "./canonical-json.mjs";
|
|
1
2
|
const DEFAULT_SEARCH_TYPE = "web";
|
|
2
3
|
function isAnalysisSourcesOptions(value) {
|
|
3
4
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -13,11 +14,6 @@ function withDefaultSearchType(value, searchType) {
|
|
|
13
14
|
function searchTypeQuery(searchType) {
|
|
14
15
|
return { searchType: searchType ?? "web" };
|
|
15
16
|
}
|
|
16
|
-
function stableJson(value) {
|
|
17
|
-
if (value == null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
18
|
-
if (Array.isArray(value)) return `[${value.map((item) => item === void 0 ? "null" : stableJson(item)).join(",")}]`;
|
|
19
|
-
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
|
|
20
|
-
}
|
|
21
17
|
function dateRangeOptionsQuery(options) {
|
|
22
18
|
const query = {};
|
|
23
19
|
const start = options?.start ?? options?.startDate;
|
|
@@ -49,10 +45,10 @@ function dataQuery(state, options) {
|
|
|
49
45
|
const opts = options;
|
|
50
46
|
const scoped = withDefaultSearchType(state, opts?.searchType);
|
|
51
47
|
const query = {
|
|
52
|
-
q:
|
|
48
|
+
q: canonicalJson(scoped),
|
|
53
49
|
searchType: scoped.searchType ?? "web"
|
|
54
50
|
};
|
|
55
|
-
if (opts?.comparison) query.qc =
|
|
51
|
+
if (opts?.comparison) query.qc = canonicalJson(withDefaultSearchType(opts.comparison, scoped.searchType));
|
|
56
52
|
if (opts?.filter) query.filter = opts.filter;
|
|
57
53
|
return query;
|
|
58
54
|
}
|
|
@@ -60,10 +56,10 @@ function dataDetailQuery(state, options) {
|
|
|
60
56
|
const opts = options;
|
|
61
57
|
const scoped = withDefaultSearchType(state, opts?.searchType);
|
|
62
58
|
const query = {
|
|
63
|
-
q:
|
|
59
|
+
q: canonicalJson(scoped),
|
|
64
60
|
searchType: scoped.searchType ?? "web"
|
|
65
61
|
};
|
|
66
|
-
if (opts?.comparison) query.qc =
|
|
62
|
+
if (opts?.comparison) query.qc = canonicalJson(withDefaultSearchType(opts.comparison, scoped.searchType));
|
|
67
63
|
return query;
|
|
68
64
|
}
|
|
69
65
|
function indexingUrlsQuery(params = {}) {
|
|
@@ -82,24 +78,4 @@ function indexingDiagnosticsQuery(params = {}) {
|
|
|
82
78
|
if (params.sampleLimit != null) query.sampleLimit = params.sampleLimit;
|
|
83
79
|
return query;
|
|
84
80
|
}
|
|
85
|
-
|
|
86
|
-
const query = {
|
|
87
|
-
startDate: params.startDate,
|
|
88
|
-
endDate: params.endDate,
|
|
89
|
-
searchType: params.searchType ?? "web"
|
|
90
|
-
};
|
|
91
|
-
if (params.prevStartDate) query.prevStartDate = params.prevStartDate;
|
|
92
|
-
if (params.prevEndDate) query.prevEndDate = params.prevEndDate;
|
|
93
|
-
return query;
|
|
94
|
-
}
|
|
95
|
-
function pageTrendQuery(params) {
|
|
96
|
-
const query = {
|
|
97
|
-
startDate: params.startDate,
|
|
98
|
-
endDate: params.endDate,
|
|
99
|
-
searchType: params.searchType ?? "web"
|
|
100
|
-
};
|
|
101
|
-
if (params.prevStartDate) query.prevStartDate = params.prevStartDate;
|
|
102
|
-
if (params.prevEndDate) query.prevEndDate = params.prevEndDate;
|
|
103
|
-
return query;
|
|
104
|
-
}
|
|
105
|
-
export { DEFAULT_SEARCH_TYPE, dataDetailQuery, dataQuery, dateRangeOptionsQuery, indexingDiagnosticsQuery, indexingUrlsQuery, pageTrendQuery, queryTrendQuery, searchTypeQuery, sourceInfoQuery, tablesQuery, withDefaultSearchType };
|
|
81
|
+
export { DEFAULT_SEARCH_TYPE, dataDetailQuery, dataQuery, indexingDiagnosticsQuery, indexingUrlsQuery, sourceInfoQuery, tablesQuery, withDefaultSearchType };
|
package/dist/lifecycle.d.mts
CHANGED
|
@@ -6,9 +6,8 @@ import { GscdumpSyncStatusResponse, GscdumpUserSite, PartnerLifecycleSite } from
|
|
|
6
6
|
*/
|
|
7
7
|
type LifecycleSiteLike = Pick<PartnerLifecycleSite, 'siteId' | 'externalSiteId' | 'requestedUrl' | 'gscPropertyUrl' | 'permissionLevel' | 'analytics' | 'indexing' | 'latestError' | 'updatedAt'>;
|
|
8
8
|
declare function analyticsStatusToSyncStatus(status: LifecycleSiteLike['analytics']['status']): GscdumpUserSite['syncStatus'];
|
|
9
|
-
declare function lifecycleSiteToUserSite(site: LifecycleSiteLike): GscdumpUserSite;
|
|
10
9
|
declare function lifecycleSiteToSyncStatus(site: LifecycleSiteLike): GscdumpSyncStatusResponse;
|
|
11
10
|
declare function findLifecycleSite<TSite extends LifecycleSiteLike>(lifecycle: {
|
|
12
11
|
sites: readonly TSite[];
|
|
13
12
|
}, siteIdOrPropertyUrl: string): TSite | null;
|
|
14
|
-
export { LifecycleSiteLike, analyticsStatusToSyncStatus, findLifecycleSite, lifecycleSiteToSyncStatus
|
|
13
|
+
export { LifecycleSiteLike, analyticsStatusToSyncStatus, findLifecycleSite, lifecycleSiteToSyncStatus };
|
package/dist/lifecycle.mjs
CHANGED
|
@@ -19,25 +19,6 @@ function analyticsStatusToSyncStatus(status) {
|
|
|
19
19
|
default: return "pending";
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
function lifecycleSiteToUserSite(site) {
|
|
23
|
-
const syncStatus = analyticsStatusToSyncStatus(site.analytics.status);
|
|
24
|
-
return {
|
|
25
|
-
siteId: site.siteId,
|
|
26
|
-
siteUrl: site.gscPropertyUrl || site.requestedUrl,
|
|
27
|
-
analyticsSyncStatus: syncStatus,
|
|
28
|
-
analyticsSyncProgress: site.analytics.progress,
|
|
29
|
-
syncStatus,
|
|
30
|
-
syncProgress: site.analytics.progress,
|
|
31
|
-
indexingEligible: site.indexing.eligible,
|
|
32
|
-
indexingIneligibleReason: site.indexing.reason,
|
|
33
|
-
indexingPermissionLevel: site.permissionLevel,
|
|
34
|
-
indexingStatus: site.indexing.status === "ready" ? "complete" : site.indexing.status === "not_requested" ? "not_started" : "indexing",
|
|
35
|
-
indexingProgress: site.indexing.progress,
|
|
36
|
-
lastSyncAt: site.updatedAt ? Date.parse(site.updatedAt) : null,
|
|
37
|
-
newestDateSynced: site.analytics.syncedRange.newest,
|
|
38
|
-
oldestDateSynced: site.analytics.syncedRange.oldest
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
22
|
function lifecycleSiteToSyncStatus(site) {
|
|
42
23
|
const syncStatus = analyticsStatusToSyncStatus(site.analytics.status);
|
|
43
24
|
const completed = site.analytics.progress.completed;
|
|
@@ -81,4 +62,4 @@ function findLifecycleSite(lifecycle, siteIdOrPropertyUrl) {
|
|
|
81
62
|
const propertyKey = normalizeGscPropertyKey(siteIdOrPropertyUrl);
|
|
82
63
|
return lifecycle.sites.find((site) => site.siteId === siteIdOrPropertyUrl || site.externalSiteId === siteIdOrPropertyUrl || !!propertyKey && normalizeGscPropertyKey(site.gscPropertyUrl) === propertyKey || !site.gscPropertyUrl && normalizeLifecycleUrl(site.requestedUrl) === normalized || !propertyKey && normalizeLifecycleUrl(site.requestedUrl) === normalized) ?? null;
|
|
83
64
|
}
|
|
84
|
-
export { analyticsStatusToSyncStatus, findLifecycleSite, lifecycleSiteToSyncStatus
|
|
65
|
+
export { analyticsStatusToSyncStatus, findLifecycleSite, lifecycleSiteToSyncStatus };
|
package/dist/period.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import "./gsc-constants.mjs";
|
|
2
|
-
import { resolveWindow } from "
|
|
3
|
-
import { addDays } from "gscdump/dates";
|
|
2
|
+
import { addDays, resolveWindow } from "gscdump/dates";
|
|
4
3
|
function isCustomPeriod(p) {
|
|
5
4
|
return typeof p === "string" && p.startsWith("custom:");
|
|
6
5
|
}
|
package/dist/request.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { canonicalJson } from "./canonical-json.mjs";
|
|
1
2
|
import { partnerErrorToException, toPartnerError } from "./errors.mjs";
|
|
2
3
|
import { err, ok, unwrapResult } from "gscdump/result";
|
|
3
4
|
import { ofetch } from "ofetch";
|
|
@@ -26,11 +27,6 @@ function shouldValidate(options, phase) {
|
|
|
26
27
|
function parseWith(schema, value) {
|
|
27
28
|
return schema ? schema.parse(value) : value;
|
|
28
29
|
}
|
|
29
|
-
function stableJson(value) {
|
|
30
|
-
if (value == null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
|
|
31
|
-
if (Array.isArray(value)) return `[${value.map((item) => item === void 0 ? "undefined" : stableJson(item)).join(",")}]`;
|
|
32
|
-
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
|
|
33
|
-
}
|
|
34
30
|
function headersKey(headers) {
|
|
35
31
|
return [...headers.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}:${value}`).join("\n");
|
|
36
32
|
}
|
|
@@ -48,7 +44,7 @@ function createHostedRequester(options, defaults) {
|
|
|
48
44
|
const { dedupe: _dedupe, ...fetchInit } = init;
|
|
49
45
|
const headers = mergeHeaders(await resolveHeaders(options), init.headers);
|
|
50
46
|
const fullPath = buildPath(apiBase, path);
|
|
51
|
-
const dedupeKey = dedupe && isDedupeable(init) ? `${(init.method ?? "GET").toUpperCase()} ${fullPath}\nq=${
|
|
47
|
+
const dedupeKey = dedupe && isDedupeable(init) ? `${(init.method ?? "GET").toUpperCase()} ${fullPath}\nq=${canonicalJson(init.query)}\nb=${canonicalJson(init.body)}\nh=${headersKey(headers)}` : null;
|
|
52
48
|
if (dedupeKey) {
|
|
53
49
|
const existing = inflight.get(dedupeKey);
|
|
54
50
|
if (existing) return existing;
|
package/dist/site-baseline.d.mts
CHANGED
|
@@ -24,7 +24,6 @@ interface SiteTypeBaseline {
|
|
|
24
24
|
/** The default growth lever when the site is healthy and leading. */
|
|
25
25
|
primaryGoal: 'content' | 'authority' | 'conversion' | 'coverage';
|
|
26
26
|
}
|
|
27
|
-
declare const SITE_TYPE_BASELINE: Record<SiteType, SiteTypeBaseline>;
|
|
28
27
|
declare function siteTypeBaseline(raw: string | null | undefined): SiteTypeBaseline;
|
|
29
28
|
type PeerStanding = 'leader' | 'on_par' | 'behind' | 'unknown';
|
|
30
29
|
/** How much to trust the standing: a median over 1–2 peers is noisy. */
|
|
@@ -66,4 +65,4 @@ declare function derivePeerStanding(input: PeerBaselineInput): {
|
|
|
66
65
|
* on the same lever; unknown standing falls back to the type default.
|
|
67
66
|
*/
|
|
68
67
|
declare function deriveSiteBaseline(rawType: string | null | undefined, peer?: PeerBaselineInput): SiteBaseline;
|
|
69
|
-
export { PeerBaselineInput, PeerConfidence, PeerStanding,
|
|
68
|
+
export { PeerBaselineInput, PeerConfidence, PeerStanding, SiteBaseline, SiteType, SiteTypeBaseline, derivePeerStanding, deriveSiteBaseline, normalizeSiteType, siteTypeBaseline };
|
package/dist/site-baseline.mjs
CHANGED
|
@@ -109,4 +109,4 @@ function deriveSiteBaseline(rawType, peer = {}) {
|
|
|
109
109
|
goalKind: baseline.primaryGoal
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
|
-
export {
|
|
112
|
+
export { derivePeerStanding, deriveSiteBaseline, normalizeSiteType, siteTypeBaseline };
|
package/dist/v1/http.d.mts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { ZodTypeAny, z } from "zod";
|
|
2
|
-
import { GscdumpV1ErrorEnvelope, GscdumpV1Operation as GscdumpV1Operation$1, GscdumpV1OperationId as GscdumpV1OperationId$1 } from "@gscdump/contracts/v1/http";
|
|
2
|
+
import { GscdumpV1ErrorEnvelope, GscdumpV1Operation as GscdumpV1Operation$1, GscdumpV1OperationId as GscdumpV1OperationId$1, createGscdumpV1Protocol } from "@gscdump/contracts/v1/http";
|
|
3
3
|
type MaybePromise<T> = T | Promise<T>;
|
|
4
4
|
type ValueOf<T> = T[keyof T];
|
|
5
|
+
type GscdumpV1ProtocolShape = ReturnType<typeof createGscdumpV1Protocol>;
|
|
6
|
+
type GscdumpV1RegistryOperations = GscdumpV1ProtocolShape['surfaces']['partner']['operations'] & GscdumpV1ProtocolShape['surfaces']['analytics']['operations'] & GscdumpV1ProtocolShape['surfaces']['realtime']['operations'];
|
|
7
|
+
type GscdumpV1RegistryMethodName = keyof GscdumpV1RegistryOperations & string;
|
|
8
|
+
interface GscdumpV1ClientMethodAliases {
|
|
9
|
+
queryRows: 'queryAnalyticsRows';
|
|
10
|
+
queryReport: 'queryAnalyticsReport';
|
|
11
|
+
queryReportDetail: 'queryAnalyticsReportDetail';
|
|
12
|
+
getStreamHead: 'getRealtimeStreamHead';
|
|
13
|
+
createTicket: 'createRealtimeTicket';
|
|
14
|
+
}
|
|
15
|
+
type GscdumpV1ClientMethodFor<TMethod extends GscdumpV1RegistryMethodName> = TMethod extends keyof GscdumpV1ClientMethodAliases ? GscdumpV1ClientMethodAliases[TMethod] : TMethod;
|
|
16
|
+
type GscdumpV1NamedOperations = { [TMethod in GscdumpV1RegistryMethodName as GscdumpV1ClientMethodFor<TMethod>]: GscdumpV1RegistryOperations[TMethod]; };
|
|
17
|
+
type GscdumpV1ClientMethodName = keyof GscdumpV1NamedOperations & string;
|
|
5
18
|
type GscdumpV1Operation = GscdumpV1Operation$1;
|
|
6
19
|
type GscdumpV1OperationId = GscdumpV1OperationId$1;
|
|
7
20
|
type OperationById<TId extends GscdumpV1OperationId> = Extract<GscdumpV1Operation, {
|
|
@@ -64,61 +77,13 @@ declare class GscdumpV1Error extends Error {
|
|
|
64
77
|
constructor(options: GscdumpV1ErrorOptions);
|
|
65
78
|
}
|
|
66
79
|
declare function isGscdumpV1Error(error: unknown): error is GscdumpV1Error;
|
|
67
|
-
|
|
80
|
+
type MethodId<TMethod extends GscdumpV1ClientMethodName> = GscdumpV1NamedOperations[TMethod] extends {
|
|
81
|
+
id: infer TId extends GscdumpV1OperationId;
|
|
82
|
+
} ? TId : never;
|
|
83
|
+
type GscdumpV1OperationMethod<TId extends GscdumpV1OperationId> = Record<never, never> extends GscdumpV1OperationInput<TId> ? (input?: GscdumpV1OperationInput<TId>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<TId>> : (input: GscdumpV1OperationInput<TId>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<TId>>;
|
|
84
|
+
type GscdumpV1Client = {
|
|
68
85
|
execute: <TId extends GscdumpV1OperationId>(operation: TId, input: NoInfer<GscdumpV1OperationInput<TId>>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<TId>>;
|
|
69
|
-
|
|
70
|
-
listAvailableSites: (input: GscdumpV1OperationInput<'partner.users.sites.available.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.sites.available.list'>>;
|
|
71
|
-
createSite: (input: GscdumpV1OperationInput<'partner.users.sites.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.sites.create'>>;
|
|
72
|
-
createUser: (input: GscdumpV1OperationInput<'partner.users.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.create'>>;
|
|
73
|
-
updateUserTokens: (input: GscdumpV1OperationInput<'partner.users.tokens.update'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.tokens.update'>>;
|
|
74
|
-
getSiteIndexing: (input: GscdumpV1OperationInput<'partner.sites.indexing.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.get'>>;
|
|
75
|
-
listSiteIndexingUrls: (input: GscdumpV1OperationInput<'partner.sites.indexing.urls.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.urls.list'>>;
|
|
76
|
-
listSiteBingIndexingEvidence: (input: GscdumpV1OperationInput<'partner.sites.indexing.bing.evidence.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.bing.evidence.list'>>;
|
|
77
|
-
listSiteIndexingTransitions: (input: GscdumpV1OperationInput<'partner.sites.indexing.transitions.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.transitions.list'>>;
|
|
78
|
-
getSiteIndexingDiagnostics: (input: GscdumpV1OperationInput<'partner.sites.indexing.diagnostics.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.diagnostics.get'>>;
|
|
79
|
-
getSiteSitemaps: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.get'>>;
|
|
80
|
-
getSiteSitemapChanges: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.changes.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.changes.get'>>;
|
|
81
|
-
listSitemapUrls: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.urls.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.urls.get'>>;
|
|
82
|
-
getSitemapExport: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.export.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.export.get'>>;
|
|
83
|
-
getSiteAnalysis: (input: GscdumpV1OperationInput<'partner.sites.analysis.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.analysis.get'>>;
|
|
84
|
-
getSiteAnalysisBundle: (input: GscdumpV1OperationInput<'partner.sites.analysis.bundle.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.analysis.bundle.get'>>;
|
|
85
|
-
deleteSite: (input: GscdumpV1OperationInput<'partner.sites.delete'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.delete'>>;
|
|
86
|
-
getCanonicalMismatches: (input: GscdumpV1OperationInput<'partner.sites.canonical.mismatches.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.canonical.mismatches.get'>>;
|
|
87
|
-
inspectSiteUrls: (input: GscdumpV1OperationInput<'partner.sites.indexing.inspect.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.inspect.create'>>;
|
|
88
|
-
recoverSitePermission: (input: GscdumpV1OperationInput<'partner.sites.permission.recover'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.permission.recover'>>;
|
|
89
|
-
queryKeywordSparklines: (input: GscdumpV1OperationInput<'partner.sites.keyword.sparklines.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.keyword.sparklines.query'>>;
|
|
90
|
-
getQueryTrend: (input: GscdumpV1OperationInput<'partner.sites.query.trend.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.query.trend.get'>>;
|
|
91
|
-
getPageTrend: (input: GscdumpV1OperationInput<'partner.sites.page.trend.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.page.trend.get'>>;
|
|
92
|
-
getContentVelocity: (input: GscdumpV1OperationInput<'partner.sites.content.velocity.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.content.velocity.get'>>;
|
|
93
|
-
getCtrCurve: (input: GscdumpV1OperationInput<'partner.sites.ctr.curve.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.ctr.curve.get'>>;
|
|
94
|
-
getDarkTraffic: (input: GscdumpV1OperationInput<'partner.sites.dark.traffic.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.dark.traffic.get'>>;
|
|
95
|
-
getDeviceGap: (input: GscdumpV1OperationInput<'partner.sites.device.gap.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.device.gap.get'>>;
|
|
96
|
-
getKeywordBreadth: (input: GscdumpV1OperationInput<'partner.sites.keyword.breadth.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.keyword.breadth.get'>>;
|
|
97
|
-
getPositionDistribution: (input: GscdumpV1OperationInput<'partner.sites.position.distribution.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.position.distribution.get'>>;
|
|
98
|
-
getTopAssociation: (input: GscdumpV1OperationInput<'partner.sites.top.association.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.top.association.get'>>;
|
|
99
|
-
getIndexPercent: (input: GscdumpV1OperationInput<'partner.sites.index.percent.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.index.percent.get'>>;
|
|
100
|
-
createSitemapAction: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.action.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.action.create'>>;
|
|
101
|
-
querySitemapMembership: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.membership.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.membership.query'>>;
|
|
102
|
-
createTeam: (input: GscdumpV1OperationInput<'partner.teams.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.create'>>;
|
|
103
|
-
renameTeam: (input: GscdumpV1OperationInput<'partner.teams.rename'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.rename'>>;
|
|
104
|
-
deleteTeam: (input: GscdumpV1OperationInput<'partner.teams.delete'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.delete'>>;
|
|
105
|
-
listTeamMembers: (input: GscdumpV1OperationInput<'partner.teams.members.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.members.list'>>;
|
|
106
|
-
addTeamMember: (input: GscdumpV1OperationInput<'partner.teams.members.add'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.members.add'>>;
|
|
107
|
-
updateTeamMemberRole: (input: GscdumpV1OperationInput<'partner.teams.members.role.update'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.members.role.update'>>;
|
|
108
|
-
removeTeamMember: (input: GscdumpV1OperationInput<'partner.teams.members.remove'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.members.remove'>>;
|
|
109
|
-
updateSiteTeam: (input: GscdumpV1OperationInput<'partner.sites.team.update'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.team.update'>>;
|
|
110
|
-
getTeamCatalog: (input: GscdumpV1OperationInput<'partner.teams.catalog.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.catalog.get'>>;
|
|
111
|
-
bindTeamCatalog: (input: GscdumpV1OperationInput<'partner.teams.catalog.bind'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.teams.catalog.bind'>>;
|
|
112
|
-
getSiteIntIdCrosswalk: (input: GscdumpV1OperationInput<'partner.users.sites.crosswalk.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.sites.crosswalk.get'>>;
|
|
113
|
-
deleteUser: (input: GscdumpV1OperationInput<'partner.users.delete'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.delete'>>;
|
|
114
|
-
createVerificationToken: (input: GscdumpV1OperationInput<'partner.users.verification.token.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.verification.token.create'>>;
|
|
115
|
-
addAndVerifySite: (input: GscdumpV1OperationInput<'partner.users.sites.verify.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.sites.verify.create'>>;
|
|
116
|
-
queryAnalyticsRows: (input: GscdumpV1OperationInput<'analytics.rows.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'analytics.rows.query'>>;
|
|
117
|
-
queryAnalyticsReport: (input: GscdumpV1OperationInput<'analytics.reports.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'analytics.reports.query'>>;
|
|
118
|
-
queryAnalyticsReportDetail: (input: GscdumpV1OperationInput<'analytics.reports.detail.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'analytics.reports.detail.query'>>;
|
|
119
|
-
getRealtimeStreamHead: (input?: GscdumpV1OperationInput<'realtime.stream.head.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'realtime.stream.head.get'>>;
|
|
120
|
-
createRealtimeTicket: (input: GscdumpV1OperationInput<'realtime.tickets.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'realtime.tickets.create'>>;
|
|
121
|
-
}
|
|
86
|
+
} & { [TMethod in GscdumpV1ClientMethodName]: GscdumpV1OperationMethod<MethodId<TMethod>>; };
|
|
122
87
|
/** Create one framework-neutral client whose behavior is driven by the v1 registry. */
|
|
123
88
|
declare function createGscdumpV1Client(options: CreateGscdumpV1ClientOptions): GscdumpV1Client;
|
|
124
89
|
export { CreateGscdumpV1ClientOptions, GscdumpV1Client, GscdumpV1CredentialResolver, GscdumpV1Error, GscdumpV1ErrorOptions, GscdumpV1ExecuteOptions, GscdumpV1HeadersResolver, GscdumpV1Operation, GscdumpV1OperationId, GscdumpV1OperationInput, GscdumpV1OperationResponse, GscdumpV1RetryOptions, GscdumpV1SdkErrorCode, createGscdumpV1Client, isGscdumpV1Error };
|
package/dist/v1/http.mjs
CHANGED
|
@@ -21,9 +21,6 @@ function isGscdumpV1Error(error) {
|
|
|
21
21
|
return error instanceof GscdumpV1Error;
|
|
22
22
|
}
|
|
23
23
|
const DEFAULT_API_ROOT = "https://gscdump.com/api";
|
|
24
|
-
const API_PREFIX_RE = /^\/api(?=\/)/;
|
|
25
|
-
const TRAILING_SLASH_RE = /\/+$/;
|
|
26
|
-
const LEADING_SLASH_RE = /^\/+/;
|
|
27
24
|
function validationDetails(cause) {
|
|
28
25
|
if (typeof cause === "object" && cause !== null && "issues" in cause) return { issues: cause.issues };
|
|
29
26
|
return {};
|
|
@@ -65,10 +62,6 @@ function resolveRetryOptions(options) {
|
|
|
65
62
|
maxDelayMs
|
|
66
63
|
};
|
|
67
64
|
}
|
|
68
|
-
function resolveApiUrl(apiRoot, contractPath) {
|
|
69
|
-
const relative = contractPath.replace(API_PREFIX_RE, "").replace(LEADING_SLASH_RE, "");
|
|
70
|
-
return `${apiRoot.replace(TRAILING_SLASH_RE, "")}/${relative}`;
|
|
71
|
-
}
|
|
72
65
|
function appendQueryValue(search, key, value) {
|
|
73
66
|
if (value === void 0) return;
|
|
74
67
|
if (Array.isArray(value)) {
|
|
@@ -104,13 +97,13 @@ function parseLocation(operation, location, value) {
|
|
|
104
97
|
throw requestValidationError(operation.id, location, cause);
|
|
105
98
|
}
|
|
106
99
|
}
|
|
107
|
-
function prepareRequest(buildOperationPath,
|
|
100
|
+
function prepareRequest(buildOperationPath, operation, input, options) {
|
|
108
101
|
let path;
|
|
109
102
|
if (operation.request.params === null) {
|
|
110
103
|
assertAbsentLocation(operation.id, "params", input.params);
|
|
111
|
-
path = buildOperationPath(
|
|
104
|
+
path = buildOperationPath();
|
|
112
105
|
} else try {
|
|
113
|
-
path = buildOperationPath(
|
|
106
|
+
path = buildOperationPath(input.params);
|
|
114
107
|
} catch (cause) {
|
|
115
108
|
throw requestValidationError(operation.id, "params", cause);
|
|
116
109
|
}
|
|
@@ -241,46 +234,46 @@ async function readJson(response) {
|
|
|
241
234
|
function requestIdFrom(response) {
|
|
242
235
|
return response.headers.get("x-request-id") ?? void 0;
|
|
243
236
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
237
|
+
let runtimePromise;
|
|
238
|
+
function getRuntime() {
|
|
239
|
+
return runtimePromise ??= import("@gscdump/contracts/v1/http").then(({ createGscdumpV1Protocol, createHttpV1Registry, isUnknownHttpV1OperationError }) => {
|
|
240
|
+
const protocol = createGscdumpV1Protocol();
|
|
241
|
+
return {
|
|
242
|
+
isUnknownOperationError: isUnknownHttpV1OperationError,
|
|
243
|
+
protocol,
|
|
244
|
+
registry: createHttpV1Registry(protocol)
|
|
245
|
+
};
|
|
249
246
|
});
|
|
250
|
-
return operations;
|
|
251
247
|
}
|
|
252
248
|
function createGscdumpV1Client(options) {
|
|
253
249
|
const retryOptions = resolveRetryOptions(options.retry);
|
|
254
250
|
const apiRoot = options.apiRoot ?? DEFAULT_API_ROOT;
|
|
255
251
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
256
|
-
let runtimePromise;
|
|
257
252
|
if (typeof fetchImpl !== "function") throw new TypeError("createGscdumpV1Client requires a fetch implementation in this runtime.");
|
|
258
|
-
function getRuntime() {
|
|
259
|
-
return runtimePromise ??= import("@gscdump/contracts/v1/http").then(({ buildHttpOperationPath: buildOperationPath, createGscdumpV1Protocol, listHttpOperations: listOperations }) => {
|
|
260
|
-
const protocol = createGscdumpV1Protocol();
|
|
261
|
-
return {
|
|
262
|
-
buildOperationPath,
|
|
263
|
-
operations: operationLookup(protocol, listOperations),
|
|
264
|
-
protocol
|
|
265
|
-
};
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
253
|
const execute = executeUntyped;
|
|
269
254
|
async function executeUntyped(operationId, input, executeOptions = {}) {
|
|
270
|
-
const {
|
|
271
|
-
const entry =
|
|
255
|
+
const { isUnknownOperationError, protocol, registry } = await getRuntime();
|
|
256
|
+
const entry = (() => {
|
|
257
|
+
try {
|
|
258
|
+
return registry.operation(operationId);
|
|
259
|
+
} catch (cause) {
|
|
260
|
+
if (isUnknownOperationError(cause)) return null;
|
|
261
|
+
throw cause;
|
|
262
|
+
}
|
|
263
|
+
})();
|
|
272
264
|
if (!entry) throw new GscdumpV1Error({
|
|
273
265
|
code: "request_validation",
|
|
274
266
|
message: `Unknown gscdump v1 operation: ${operationId}`,
|
|
275
267
|
retryable: false,
|
|
276
268
|
details: { operationId }
|
|
277
269
|
});
|
|
278
|
-
const { operation
|
|
270
|
+
const { operation } = entry;
|
|
279
271
|
if (typeof input !== "object" || input === null || Array.isArray(input)) throw requestValidationError(operation.id, "input", /* @__PURE__ */ new TypeError("input must be an object."));
|
|
280
|
-
const
|
|
272
|
+
const buildRegisteredPath = registry.path;
|
|
273
|
+
const prepared = prepareRequest((params) => buildRegisteredPath(operationId, params, { apiRoot }), operation, input, executeOptions);
|
|
281
274
|
let url;
|
|
282
275
|
try {
|
|
283
|
-
url = appendQuery(
|
|
276
|
+
url = appendQuery(prepared.path, prepared.query);
|
|
284
277
|
} catch (cause) {
|
|
285
278
|
throw requestValidationError(operation.id, "query", cause);
|
|
286
279
|
}
|
package/dist/v1/realtime.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RealtimeV1Cursor, RealtimeV1Event, RealtimeV1StreamHead, RealtimeV1StreamId } from "@gscdump/contracts/v1/realtime";
|
|
2
2
|
type MaybePromise<T> = T | Promise<T>;
|
|
3
|
-
declare const GSCDUMP_REALTIME_V1_SDK_VERSION: "3.
|
|
3
|
+
declare const GSCDUMP_REALTIME_V1_SDK_VERSION: "3.1.0";
|
|
4
4
|
type GscdumpRealtimeV1TransportState = 'idle' | 'ticketing' | 'connecting' | 'handshaking' | 'replaying' | 'live' | 'waiting' | 'stopped' | 'terminal';
|
|
5
5
|
type GscdumpRealtimeV1Freshness = 'unknown' | 'stale' | 'applying' | 'fresh' | 'resyncing' | 'degraded';
|
|
6
6
|
type GscdumpRealtimeV1ErrorCode = 'cursor_store_failed' | 'effect_failed' | 'heartbeat_stale' | 'integration_failed' | 'protocol_error' | 'resync_failed' | 'runtime_unavailable' | 'socket_error' | 'ticket_invalid' | 'ticket_provider_failed' | 'upgrade_rejected';
|
package/dist/v1/realtime.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { utf8Size } from "../utf8.mjs";
|
|
2
2
|
import { GSCDUMP_REALTIME_ACK_POLICY, GSCDUMP_REALTIME_CLOSE_CODES, GSCDUMP_REALTIME_CONNECTION_POLICY, GSCDUMP_REALTIME_LIMITS, GSCDUMP_REALTIME_PING, GSCDUMP_REALTIME_PONG, GSCDUMP_REALTIME_PROTOCOL_VERSION, GSCDUMP_REALTIME_SUBPROTOCOL, REALTIME_V1_EVENT_NAMES, REALTIME_V1_RESOURCE_TYPES, createRealtimeV1Schemas } from "@gscdump/contracts/v1/realtime";
|
|
3
|
-
const GSCDUMP_REALTIME_V1_SDK_VERSION = "3.
|
|
3
|
+
const GSCDUMP_REALTIME_V1_SDK_VERSION = "3.1.0";
|
|
4
4
|
var GscdumpRealtimeV1Error = class extends Error {
|
|
5
5
|
tag = "GscdumpRealtimeV1Error";
|
|
6
6
|
code;
|
|
@@ -87,7 +87,7 @@ function createGscdumpRealtimeV1Client(options) {
|
|
|
87
87
|
const schemas = createRealtimeV1Schemas();
|
|
88
88
|
const runtime = options.runtime ?? defaultRuntime();
|
|
89
89
|
const cursorStore = options.cursorStore ?? createMemoryCursorStore();
|
|
90
|
-
const sdkVersion = options.sdkVersion ?? "3.
|
|
90
|
+
const sdkVersion = options.sdkVersion ?? "3.1.0";
|
|
91
91
|
if (!sdkVersion) throw new TypeError("sdkVersion cannot be empty.");
|
|
92
92
|
let running = false;
|
|
93
93
|
let epoch = 0;
|
package/dist/webhook.d.mts
CHANGED
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Result } from "gscdump/result";
|
|
3
|
-
import { CANONICAL_WEBHOOK_EVENTS, CreateWebhookEnvelopeOptions, PartnerWebhookHeaders, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, WebhookEnvelope } from "@gscdump/contracts";
|
|
4
|
-
declare function generateWebhookSecret(): string;
|
|
5
|
-
declare function generateWebhookDeliveryId(): string;
|
|
6
|
-
declare function shouldQueueWebhook(webhookEvents: string | string[] | null | undefined, eventType: string): boolean;
|
|
7
|
-
declare function createWebhookEnvelope<TData extends Record<string, unknown>>(options: CreateWebhookEnvelopeOptions<TData>): WebhookEnvelope<TData>;
|
|
1
|
+
import { CANONICAL_WEBHOOK_EVENTS, PartnerWebhookHeaders, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, WebhookEnvelope } from "@gscdump/contracts";
|
|
8
2
|
declare function signWebhookPayload(payload: string | object, secret: string): Promise<string>;
|
|
9
3
|
declare function verifyWebhookSignature(payload: string | object, signature: string | null | undefined, secret: string): Promise<boolean>;
|
|
10
|
-
/**
|
|
11
|
-
* Errors-as-values core for {@link parseWebhookPayload}: a failed HMAC signature
|
|
12
|
-
* check is a caller-actionable `auth` (401) failure at the webhook boundary, so
|
|
13
|
-
* it is returned as a modelled `PartnerApiError` rather than only thrown. A
|
|
14
|
-
* malformed envelope (schema parse) is a defect and keeps propagating.
|
|
15
|
-
*/
|
|
16
|
-
declare function parseWebhookPayloadResult<TData extends Record<string, unknown> = Record<string, unknown>>(payload: string | object, options?: {
|
|
17
|
-
secret?: string;
|
|
18
|
-
signature?: string | null;
|
|
19
|
-
headers?: PartnerWebhookHeaders | Headers;
|
|
20
|
-
validateSignature?: boolean;
|
|
21
|
-
}): Promise<Result<WebhookEnvelope<TData>, PartnerApiError>>;
|
|
22
4
|
declare function parseWebhookPayload<TData extends Record<string, unknown> = Record<string, unknown>>(payload: string | object, options?: {
|
|
23
5
|
secret?: string;
|
|
24
6
|
signature?: string | null;
|
|
@@ -26,4 +8,4 @@ declare function parseWebhookPayload<TData extends Record<string, unknown> = Rec
|
|
|
26
8
|
validateSignature?: boolean;
|
|
27
9
|
}): Promise<WebhookEnvelope<TData>>;
|
|
28
10
|
declare function readWebhookHeaders(headers: Headers | PartnerWebhookHeaders | null | undefined): Required<PartnerWebhookHeaders>;
|
|
29
|
-
export { CANONICAL_WEBHOOK_EVENTS, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER,
|
|
11
|
+
export { CANONICAL_WEBHOOK_EVENTS, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, parseWebhookPayload, readWebhookHeaders, signWebhookPayload, verifyWebhookSignature };
|
package/dist/webhook.mjs
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { PartnerApiError, partnerErrorToException } from "./errors.mjs";
|
|
2
2
|
import { err, ok, unwrapResult } from "gscdump/result";
|
|
3
|
-
import { CANONICAL_WEBHOOK_EVENTS, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION,
|
|
4
|
-
const CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
5
|
-
const SECRET_LENGTH = 32;
|
|
3
|
+
import { CANONICAL_WEBHOOK_EVENTS, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_CONTRACT_VERSION_HEADER as WEBHOOK_CONTRACT_VERSION_HEADER$1, WEBHOOK_DELIVERY_HEADER, WEBHOOK_DELIVERY_HEADER as WEBHOOK_DELIVERY_HEADER$1, WEBHOOK_EVENT_HEADER, WEBHOOK_EVENT_HEADER as WEBHOOK_EVENT_HEADER$1, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_SIGNATURE_HEADER as WEBHOOK_SIGNATURE_HEADER$1, WEBHOOK_TIMESTAMP_HEADER, WEBHOOK_TIMESTAMP_HEADER as WEBHOOK_TIMESTAMP_HEADER$1, partnerWebhookEnvelopeSchema } from "@gscdump/contracts";
|
|
6
4
|
const encoder = new TextEncoder();
|
|
7
|
-
function randomString(length) {
|
|
8
|
-
const bytes = crypto.getRandomValues(new Uint8Array(length));
|
|
9
|
-
let value = "";
|
|
10
|
-
for (let i = 0; i < length; i++) value += CHARSET[bytes[i] % 62];
|
|
11
|
-
return value;
|
|
12
|
-
}
|
|
13
5
|
function toPayloadString(payload) {
|
|
14
6
|
return typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
15
7
|
}
|
|
@@ -39,32 +31,6 @@ async function hmacSha256(payload, secret) {
|
|
|
39
31
|
}, false, ["sign"]);
|
|
40
32
|
return crypto.subtle.sign("HMAC", key, encoder.encode(payload));
|
|
41
33
|
}
|
|
42
|
-
function generateWebhookSecret() {
|
|
43
|
-
return `whsec_${randomString(SECRET_LENGTH)}`;
|
|
44
|
-
}
|
|
45
|
-
function generateWebhookDeliveryId() {
|
|
46
|
-
return `whd_${crypto.randomUUID()}`;
|
|
47
|
-
}
|
|
48
|
-
function shouldQueueWebhook(webhookEvents, eventType) {
|
|
49
|
-
if (!webhookEvents) return false;
|
|
50
|
-
return (Array.isArray(webhookEvents) ? webhookEvents : JSON.parse(webhookEvents)).includes(eventType);
|
|
51
|
-
}
|
|
52
|
-
function createWebhookEnvelope(options) {
|
|
53
|
-
const occurredAt = options.occurredAt instanceof Date ? options.occurredAt.toISOString() : options.occurredAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
54
|
-
return {
|
|
55
|
-
contractVersion: options.contractVersion ?? WEBHOOK_CONTRACT_VERSION$1,
|
|
56
|
-
deliveryId: options.deliveryId ?? generateWebhookDeliveryId(),
|
|
57
|
-
event: options.event,
|
|
58
|
-
partnerId: options.partnerId,
|
|
59
|
-
userId: options.userId,
|
|
60
|
-
siteId: options.siteId,
|
|
61
|
-
externalUserId: options.externalUserId ?? null,
|
|
62
|
-
externalSiteId: options.externalSiteId ?? null,
|
|
63
|
-
lifecycleRevision: options.lifecycleRevision,
|
|
64
|
-
occurredAt,
|
|
65
|
-
data: options.data
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
34
|
async function signWebhookPayload(payload, secret) {
|
|
69
35
|
return `sha256=${bytesToHex(await hmacSha256(toPayloadString(payload), secret))}`;
|
|
70
36
|
}
|
|
@@ -115,4 +81,4 @@ function readWebhookHeaders(headers) {
|
|
|
115
81
|
signature: headers.signature ?? null
|
|
116
82
|
};
|
|
117
83
|
}
|
|
118
|
-
export { CANONICAL_WEBHOOK_EVENTS, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER,
|
|
84
|
+
export { CANONICAL_WEBHOOK_EVENTS, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, parseWebhookPayload, readWebhookHeaders, signWebhookPayload, verifyWebhookSignature };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.1.0",
|
|
5
5
|
"description": "Consumer SDK for hosted gscdump.com integrations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -146,9 +146,8 @@
|
|
|
146
146
|
"dependencies": {
|
|
147
147
|
"ofetch": "^1.5.1",
|
|
148
148
|
"zod": "^4.4.3",
|
|
149
|
-
"@gscdump/contracts": "^3.
|
|
150
|
-
"
|
|
151
|
-
"gscdump": "^3.0.0"
|
|
149
|
+
"@gscdump/contracts": "^3.1.0",
|
|
150
|
+
"gscdump": "^3.1.0"
|
|
152
151
|
},
|
|
153
152
|
"devDependencies": {
|
|
154
153
|
"typescript": "^7.0.2",
|