@gscdump/sdk 0.38.2 → 0.40.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,10 +3,9 @@
3
3
  Consumer SDK for hosted gscdump.com integrations.
4
4
 
5
5
  > The descriptor-driven HTTP client and ticketed realtime state machine are
6
- > exported from `@gscdump/sdk/v1`. Existing root HTTP/realtime clients remain
7
- > legacy compatibility surfaces during the release and cutover overlap; the
8
- > legacy socket client still sends a long-lived key in its first frame and must
9
- > not be used for a v1 browser integration. See the
6
+ > exported from `@gscdump/sdk/v1`. The root HTTP client remains a temporary
7
+ > compatibility surface during the release and cutover overlap; the unsafe
8
+ > long-lived-key realtime client was removed before v1. See the
10
9
  > [v1 contract](../../docs/hosted-api-v1.md).
11
10
 
12
11
  This package is for partner applications that consume gscdump.com APIs,
@@ -14,9 +13,9 @@ webhooks, and realtime events. Callers inject the HTTP transport and auth they
14
13
  want to use; route construction stays inside the hosted adapter.
15
14
 
16
15
  ```ts
17
- import { createGscdumpClient } from '@gscdump/sdk'
16
+ import { createPartnerClient } from '@gscdump/sdk'
18
17
 
19
- const gscdump = createGscdumpClient({
18
+ const gscdump = createPartnerClient({
20
19
  apiBase: 'https://example.com/api',
21
20
  apiKey: process.env.GSCDUMP_API_KEY,
22
21
  fetch: $fetch,
@@ -1,2 +1,2 @@
1
1
  import * as import_gscdump_query from "gscdump/query";
2
- export { import_gscdump_query as query_d_exports };
2
+ export { __exportAll, __reExport, query_d_exports };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
- import { query_d_exports } from "./_chunks/query.mjs";
1
+ import { __exportAll, __reExport, query_d_exports } from "./_chunks/query.mjs";
2
2
  import { Result } from "gscdump/result";
3
- import { AddPartnerTeamMemberParams, AnalyticsClient, AnalyticsClient as AnalyticsClient$1, BackfillRange, BackfillResponse, BindPartnerSiteTeamParams, BuilderState, BulkRegisterPartnerSiteResult, BulkRegisterPartnerSitesParams, BulkRegisterPartnerSitesResponse, CANONICAL_WEBHOOK_EVENTS, CanonicalWebhookEventType, CreatePartnerTeamParams, CreateWebhookEnvelopeOptions, DataDetailOptions, DataQueryOptions, DeletePartnerUserResponse, GscComparisonFilter, GscdumpAnalysisParams, GscdumpAnalysisPreset, GscdumpAnalysisResponse, GscdumpAnalysisSourcesResponse, GscdumpAvailableSite, GscdumpCanonicalMismatchesResponse, GscdumpDataDetailResponse, GscdumpDataResponse, GscdumpDataRow, GscdumpDateRangeParams, GscdumpIndexPercentResponse, GscdumpIndexingDiagnosticsResponse, GscdumpIndexingResponse, GscdumpIndexingUrlStatus, GscdumpIndexingUrlsResponse, GscdumpKeywordSparklinesParams, GscdumpKeywordSparklinesResponse, GscdumpMeta, GscdumpPageTrendParams, GscdumpPageTrendResponse, GscdumpPermissionRecovery, GscdumpQueryTrendParams, GscdumpQueryTrendResponse, GscdumpSiteRegistration, GscdumpSitemap, GscdumpSitemapChangesResponse, GscdumpSitemapHistory, GscdumpSitemapsResponse, GscdumpSyncStatusResponse, GscdumpSyncStatusResponse as GscdumpSyncStatusResponse$1, GscdumpTeamMemberRow, GscdumpTeamRow, GscdumpTopAssociationParams, GscdumpTopAssociationResponse, GscdumpTotals, GscdumpUserRegistration, GscdumpUserSettings, GscdumpUserSite, GscdumpUserSite as GscdumpUserSite$1, GscdumpUserStatus, GscdumpUserTokenUpdate, IndexingDiagnosticsParams, IndexingUrlsParams, InspectionHistoryResponse, InspectionIndex, PartnerClient, PartnerClient as PartnerClient$1, PartnerLifecycleAccount, PartnerLifecycleResponse, PartnerLifecycleResponse as PartnerLifecycleResponse$1, PartnerLifecycleSite, PartnerLifecycleSite as PartnerLifecycleSite$1, PartnerRealtimeEvent, PartnerRealtimeEvent as PartnerRealtimeEvent$1, PartnerRealtimeEventType, PartnerRealtimeMessage, PartnerRealtimeMessage as PartnerRealtimeMessage$1, PartnerWebhookData, PartnerWebhookHeaders, PartnerWebhookHeaders as PartnerWebhookHeaders$1, RealtimeAuthFailedEvent, RealtimeAuthRequiredMessage, RealtimeConnectedMessage, RealtimeEnrichmentCompleteEvent, RealtimeErrorMessage, RealtimeJobFailedEvent, RealtimeNeedsReauthEvent, RealtimePongMessage, RealtimeSiteAddedEvent, RealtimeSiteRemovedEvent, RealtimeSubscribedMessage, RealtimeSyncCompleteEvent, RealtimeSyncFailedEvent, RealtimeSyncJobCompleteEvent, RealtimeSyncProgressEvent, RealtimeSyncSiteCompleteEvent, RegisterPartnerSiteParams, RegisterPartnerUserParams, RollupEnvelope, UpdatePartnerUserTokensParams, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, WebhookEnvelope, WebhookEnvelope as WebhookEnvelope$1, WebhookEventType, WhoamiResponse } from "@gscdump/contracts";
3
+ import { arbitrarySql as arbitrarySql$1, auxCloudOnly as auxCloudOnly$1, entityDailySparkline as entityDailySparkline$1, entityDailyTimeseries as entityDailyTimeseries$1, multiSeriesStackedDaily as multiSeriesStackedDaily$1, singleRowLookup as singleRowLookup$1, siteDailyTimeseries as siteDailyTimeseries$1, topNBreakdown as topNBreakdown$1, twoDimensionDetail as twoDimensionDetail$1 } from "@gscdump/contracts/archetypes";
4
+ import { AddPartnerTeamMemberParams, AnalyticsClient, AnalyticsClient as AnalyticsClient$1, BackfillRange, BackfillResponse, BindPartnerSiteTeamParams, BuilderState, BulkRegisterPartnerSiteResult, BulkRegisterPartnerSitesParams, BulkRegisterPartnerSitesResponse, CANONICAL_WEBHOOK_EVENTS, CanonicalWebhookEventType, CreatePartnerTeamParams, CreateWebhookEnvelopeOptions, DataDetailOptions, DataQueryOptions, DeletePartnerUserResponse, GscComparisonFilter, GscdumpAnalysisParams, GscdumpAnalysisPreset, GscdumpAnalysisResponse, GscdumpAnalysisSourcesResponse, GscdumpAvailableSite, GscdumpCanonicalMismatchesResponse, GscdumpDataDetailResponse, GscdumpDataResponse, GscdumpDataRow, GscdumpDateRangeParams, GscdumpIndexPercentResponse, GscdumpIndexingDiagnosticsResponse, GscdumpIndexingResponse, GscdumpIndexingUrlStatus, GscdumpIndexingUrlsResponse, GscdumpKeywordSparklinesParams, GscdumpKeywordSparklinesResponse, GscdumpMeta, GscdumpPageTrendParams, GscdumpPageTrendResponse, GscdumpPermissionRecovery, GscdumpQueryTrendParams, GscdumpQueryTrendResponse, GscdumpSiteRegistration, GscdumpSitemap, GscdumpSitemapChangesResponse, GscdumpSitemapHistory, GscdumpSitemapsResponse, GscdumpSyncStatusResponse, GscdumpSyncStatusResponse as GscdumpSyncStatusResponse$1, GscdumpTeamMemberRow, GscdumpTeamRow, GscdumpTopAssociationParams, GscdumpTopAssociationResponse, GscdumpTotals, GscdumpUserRegistration, GscdumpUserSettings, GscdumpUserSite, GscdumpUserSite as GscdumpUserSite$1, GscdumpUserStatus, GscdumpUserTokenUpdate, IndexingDiagnosticsParams, IndexingUrlsParams, InspectionHistoryResponse, InspectionIndex, PartnerClient, PartnerClient as PartnerClient$1, PartnerLifecycleAccount, PartnerLifecycleResponse, PartnerLifecycleSite, PartnerLifecycleSite as PartnerLifecycleSite$1, PartnerWebhookData, PartnerWebhookHeaders, PartnerWebhookHeaders as PartnerWebhookHeaders$1, RegisterPartnerSiteParams, RegisterPartnerUserParams, RollupEnvelope, SourceInfoOptions, UpdatePartnerUserTokensParams, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, WebhookEnvelope, WebhookEnvelope as WebhookEnvelope$1, WebhookEventType, WhoamiResponse } from "@gscdump/contracts";
4
5
  import { ZodTypeAny } from "zod";
5
6
  import { ActionSource } from "@gscdump/analysis";
6
7
  import { AnalysisTool } from "@gscdump/engine/analysis-types";
@@ -136,7 +137,20 @@ interface DailyAnonInput {
136
137
  anonymizedImpressionsPct: number;
137
138
  }
138
139
  declare function weightedAnonPct(days: readonly DailyAnonInput[] | null | undefined, window?: number): number | null;
140
+ declare namespace archetypes_d_exports {
141
+ export { ARCHETYPE_EXECUTION_CLASS, arbitrarySql, auxCloudOnly, entityDailySparkline, entityDailyTimeseries, multiSeriesStackedDaily, singleRowLookup, siteDailyTimeseries, topNBreakdown, twoDimensionDetail };
142
+ }
139
143
  import * as import__gscdump_contracts_archetypes from "@gscdump/contracts/archetypes";
144
+ declare const ARCHETYPE_EXECUTION_CLASS: Record<import("@gscdump/contracts").QueryArchetype, import("@gscdump/contracts").ArchetypeExecutionClass>;
145
+ declare const arbitrarySql: typeof arbitrarySql$1;
146
+ declare const auxCloudOnly: typeof auxCloudOnly$1;
147
+ declare const entityDailySparkline: typeof entityDailySparkline$1;
148
+ declare const entityDailyTimeseries: typeof entityDailyTimeseries$1;
149
+ declare const multiSeriesStackedDaily: typeof multiSeriesStackedDaily$1;
150
+ declare const singleRowLookup: typeof singleRowLookup$1;
151
+ declare const siteDailyTimeseries: typeof siteDailyTimeseries$1;
152
+ declare const topNBreakdown: typeof topNBreakdown$1;
153
+ declare const twoDimensionDetail: typeof twoDimensionDetail$1;
140
154
  type PartnerFetch = HostedFetch;
141
155
  type PartnerHeaders = HostedHeaders;
142
156
  type PartnerFetchOptions = HostedFetchOptions;
@@ -156,7 +170,6 @@ interface PartnerClientOptions extends HostedClientOptions {
156
170
  validate?: boolean | 'request' | 'response';
157
171
  }
158
172
  declare function createPartnerClient(options?: PartnerClientOptions): PartnerClient$1;
159
- declare const createGscdumpClient: typeof createPartnerClient;
160
173
  declare const COUNTRY_NAMES: Record<string, string>;
161
174
  declare const countryName: (code: string) => string;
162
175
  declare const CWV_GOOD_LCP = 2500;
@@ -213,7 +226,7 @@ interface GscClassifiedError {
213
226
  code?: number;
214
227
  /** Best-effort human message: server-supplied `message`, then `data.message`, then the error's own message. */
215
228
  message?: string;
216
- /** Seconds the server suggested waiting (429 with `retryAfter` payload). */
229
+ /** Seconds the server suggested waiting (429/503 retry payloads). */
217
230
  retryAfter?: number;
218
231
  }
219
232
  declare function classifyGscError(e: unknown): GscClassifiedError;
@@ -246,6 +259,14 @@ interface DateRangeResult {
246
259
  yearEnd: string;
247
260
  days: number;
248
261
  }
262
+ interface PeriodOptions {
263
+ /** Subtract GSC's stable-data latency from `end`. Default `true`. */
264
+ stableData?: boolean;
265
+ /** IANA timezone used to resolve today's calendar date. Default GSC/Pacific time. */
266
+ timezone?: string;
267
+ /** Clock used to resolve today's calendar date. Defaults to the current time. */
268
+ now?: Date;
269
+ }
249
270
  declare function isCustomPeriod(p: Period | string): p is CustomPeriod;
250
271
  declare function parseCustomPeriod(p: Period | string): {
251
272
  start: string;
@@ -253,8 +274,8 @@ declare function parseCustomPeriod(p: Period | string): {
253
274
  prevStart?: string;
254
275
  prevEnd?: string;
255
276
  } | null;
256
- declare function periodToDateRange(period: Period | string, stableData?: boolean): DateRangeResult;
257
- declare function periodToDays(period: Period | string): number;
277
+ declare function periodToDateRange(period: Period | string, stableDataOrOptions?: boolean | PeriodOptions): DateRangeResult;
278
+ declare function periodToDays(period: Period | string, stableDataOrOptions?: boolean | PeriodOptions): number;
258
279
  declare function compareRange(range: DateRangeResult, mode: CompareMode): {
259
280
  start: string;
260
281
  end: string;
@@ -349,6 +370,29 @@ declare function positionFor(r: {
349
370
  impressions: number;
350
371
  sum_position: number;
351
372
  }): number;
373
+ type GscSearchType = 'web' | 'image' | 'video' | 'news' | 'discover' | 'googleNews';
374
+ interface SearchTypeOptions {
375
+ searchType?: GscSearchType;
376
+ }
377
+ interface SourceRangeOptions {
378
+ start?: string;
379
+ end?: string;
380
+ startDate?: string;
381
+ endDate?: string;
382
+ }
383
+ interface AnalysisSourcesOptions extends SearchTypeOptions, SourceRangeOptions {
384
+ tables?: string[] | string;
385
+ maxBytes?: number;
386
+ maxRows?: number;
387
+ maxFiles?: number;
388
+ }
389
+ declare const DEFAULT_SEARCH_TYPE: GscSearchType;
390
+ declare function withDefaultSearchType<T extends object>(value: T, searchType?: GscSearchType): T & SearchTypeOptions;
391
+ declare function withDefaultSearchType<T>(value: T, searchType?: GscSearchType): T;
392
+ declare function searchTypeQuery(searchType?: GscSearchType): Record<string, string>;
393
+ declare function dateRangeOptionsQuery(options: SourceRangeOptions | undefined): Record<string, string>;
394
+ declare function sourceInfoQuery(options: SourceInfoOptions | undefined): Record<string, string>;
395
+ declare function tablesQuery(tablesOrOptions: string[] | string | AnalysisSourcesOptions | undefined, options?: AnalysisSourcesOptions): Record<string, string>;
352
396
  interface IndexingIssueDetail {
353
397
  description: string;
354
398
  fix: string;
@@ -403,83 +447,18 @@ declare const issueTypeToGroup: Record<string, string>;
403
447
  declare function enrichIssueDetails(modules?: {
404
448
  name: string;
405
449
  }[]): Record<string, IndexingIssueDetail>;
406
- declare function analyticsStatusToSyncStatus(status: PartnerLifecycleSite$1['analytics']['status']): GscdumpUserSite$1['syncStatus'];
407
- declare function lifecycleSiteToUserSite(site: PartnerLifecycleSite$1): GscdumpUserSite$1;
408
- declare function lifecycleSiteToSyncStatus(site: PartnerLifecycleSite$1): GscdumpSyncStatusResponse$1;
409
- declare function findLifecycleSite(lifecycle: PartnerLifecycleResponse$1, siteIdOrPropertyUrl: string): PartnerLifecycleSite$1 | null;
410
- type PartnerRealtimeScope = 'partner' | 'user';
411
- type PartnerRealtimeStatus = 'idle' | 'connecting' | 'open' | 'authenticated' | 'closed' | 'error';
412
- type PartnerRealtimeHandler<T> = (value: T) => void;
413
- interface PartnerWebSocketLike {
414
- readyState: number;
415
- onopen: ((event: unknown) => void) | null;
416
- onmessage: ((event: {
417
- data: unknown;
418
- }) => void) | null;
419
- onerror: ((event: unknown) => void) | null;
420
- onclose: ((event: unknown) => void) | null;
421
- send: (data: string) => void;
422
- close: (code?: number, reason?: string) => void;
423
- }
424
- interface PartnerWebSocketConstructor {
425
- new (url: string, protocols?: string | string[]): PartnerWebSocketLike;
426
- }
427
- interface PartnerRealtimeReconnectOptions {
428
- /** Default `true`. Set `false` to disable automatic reconnection entirely. */
429
- enabled?: boolean;
430
- /** First-retry delay in ms; doubles each attempt. Default `1000`. */
431
- baseDelayMs?: number;
432
- /** Upper bound on the backoff delay in ms. Default `30000`. */
433
- maxDelayMs?: number;
434
- /** Stop after this many consecutive failed attempts. Default `Infinity`. */
435
- maxRetries?: number;
436
- /** Apply equal-jitter to each delay so many clients don't reconnect in lockstep. Default `true`. */
437
- jitter?: boolean;
438
- }
439
- interface PartnerRealtimeOptions {
440
- /**
441
- * HTTP API base used only to derive a same-origin websocket base when `wsBase`
442
- * is omitted. Prefer passing `wsBase` when the websocket origin differs.
443
- */
444
- apiBase?: string;
445
- /** WebSocket origin base, for example `wss://origin.example`. */
446
- wsBase?: string;
447
- /** Partner or user API key sent in the first auth message. */
448
- apiKey: string;
449
- /** `/ws/partner` or `/ws/user`. User scope supports partner key + user id. */
450
- scope?: PartnerRealtimeScope;
451
- /** Required by the hosted `/ws/user` route when authenticating with a partner API key. */
452
- userId?: number | string;
453
- /** Optional initial site filter sent after authentication succeeds. */
454
- siteIds?: string[];
455
- protocols?: string | string[];
456
- WebSocket?: PartnerWebSocketConstructor;
457
- /**
458
- * Automatic reconnection on unexpected close (network drop, server restart).
459
- * A raw WebSocket `error` Event carries no actionable detail, so rather than
460
- * surfacing it the client transparently reconnects with exponential backoff.
461
- * `true` (default) uses defaults; pass an object to tune; `false` disables.
462
- * The backoff counter resets once a reconnection reaches `authenticated`.
463
- */
464
- reconnect?: boolean | PartnerRealtimeReconnectOptions;
465
- /** Injected timer hooks (for tests). Defaults to global `setTimeout`/`clearTimeout`. */
466
- setTimeout?: (handler: () => void, ms: number) => unknown;
467
- clearTimeout?: (handle: unknown) => void;
468
- }
469
- interface PartnerRealtimeClient {
470
- readonly status: PartnerRealtimeStatus;
471
- readonly socket: PartnerWebSocketLike | null;
472
- connect: () => PartnerWebSocketLike;
473
- close: (code?: number, reason?: string) => void;
474
- ping: () => void;
475
- subscribe: (siteIds: string[]) => void;
476
- onStatus: (handler: PartnerRealtimeHandler<PartnerRealtimeStatus>) => () => void;
477
- onMessage: (handler: PartnerRealtimeHandler<PartnerRealtimeMessage$1>) => () => void;
478
- onEvent: (handler: PartnerRealtimeHandler<PartnerRealtimeEvent$1>) => () => void;
479
- onError: (handler: PartnerRealtimeHandler<unknown>) => () => void;
480
- }
481
- declare function createPartnerRealtimeClient(options: PartnerRealtimeOptions): PartnerRealtimeClient;
482
- declare const createGscdumpRealtimeClient: typeof createPartnerRealtimeClient;
450
+ /**
451
+ * Stable lifecycle fields shared by the legacy partner response and public v1.
452
+ * Keeping the adapters structural lets consumers migrate to v1 without
453
+ * re-introducing legacy-only fields such as `intId` or `lifecycleRevision`.
454
+ */
455
+ type LifecycleSiteLike = Pick<PartnerLifecycleSite$1, 'siteId' | 'externalSiteId' | 'requestedUrl' | 'gscPropertyUrl' | 'permissionLevel' | 'analytics' | 'indexing' | 'latestError' | 'updatedAt'>;
456
+ declare function analyticsStatusToSyncStatus(status: LifecycleSiteLike['analytics']['status']): GscdumpUserSite$1['syncStatus'];
457
+ declare function lifecycleSiteToUserSite(site: LifecycleSiteLike): GscdumpUserSite$1;
458
+ declare function lifecycleSiteToSyncStatus(site: LifecycleSiteLike): GscdumpSyncStatusResponse$1;
459
+ declare function findLifecycleSite<TSite extends LifecycleSiteLike>(lifecycle: {
460
+ sites: readonly TSite[];
461
+ }, siteIdOrPropertyUrl: string): TSite | null;
483
462
  type SearchConsoleStageKey = 'not_connected' | 'waiting_for_data' | 'weak_discovery' | 'discovery_backlog' | 'crawl_blocked' | 'indexability_blocked' | 'index_rejection' | 'partially_indexed' | 'indexed_invisible' | 'visible_not_clicked' | 'ranking_stalled' | 'declining_visibility' | 'healthy_growth_ready';
484
463
  type SearchConsoleStageSeverity = 'success' | 'error' | 'warning' | 'info' | 'neutral';
485
464
  interface SearchConsoleStageEvidence {
@@ -754,7 +733,6 @@ declare function parseWebhookPayload<TData extends Record<string, unknown> = Rec
754
733
  validateSignature?: boolean;
755
734
  }): Promise<WebhookEnvelope$1<TData>>;
756
735
  declare function readWebhookHeaders(headers: Headers | PartnerWebhookHeaders$1 | null | undefined): Required<PartnerWebhookHeaders$1>;
757
- type ARCHETYPE_EXECUTION_CLASS = import__gscdump_contracts_archetypes.ARCHETYPE_EXECUTION_CLASS;
758
736
  type ArbitrarySqlQuery = import__gscdump_contracts_archetypes.ArbitrarySqlQuery;
759
737
  type ArchetypeExecutionClass = import__gscdump_contracts_archetypes.ArchetypeExecutionClass;
760
738
  type ArchetypeFacet = import__gscdump_contracts_archetypes.ArchetypeFacet;
@@ -774,4 +752,5 @@ type SingleRowLookupQuery = import__gscdump_contracts_archetypes.SingleRowLookup
774
752
  type SiteDailyTimeseriesQuery = import__gscdump_contracts_archetypes.SiteDailyTimeseriesQuery;
775
753
  type TopNBreakdownQuery = import__gscdump_contracts_archetypes.TopNBreakdownQuery;
776
754
  type TwoDimensionDetailQuery = import__gscdump_contracts_archetypes.TwoDimensionDetailQuery;
777
- export { ARCHETYPE_EXECUTION_CLASS, type AddPartnerTeamMemberParams, type AnalyticsClient, type AnalyticsClientOptions, type AnalyticsFetch, type AnalyticsFetchOptions, type AnalyticsHeaders, type ArbitrarySqlQuery, type ArchetypeExecutionClass, type ArchetypeFacet, type ArchetypeQuery, type ArchetypeQueryBase, type ArchetypeResult, type ArchetypeResultRow, type ArchetypeResultSource, type AuxCloudOnlyQuery, type BackfillRange, type BackfillResponse, type BindPartnerSiteTeamParams, type BuilderState, type BulkRegisterPartnerSiteResult, type BulkRegisterPartnerSitesParams, type BulkRegisterPartnerSitesResponse, CANONICAL_WEBHOOK_EVENTS, COMPARE_OPTIONS, COUNTRY_NAMES, CWV_GOOD_CLS, CWV_GOOD_INP, CWV_GOOD_LCP, CWV_POOR_CLS, CWV_POOR_INP, CWV_POOR_LCP, type CalendarPeriod, type CanonicalDailyRow, type CanonicalWebhookEventType, type ClassifySearchConsoleStageInput, type CompareMode, type CreatePartnerTeamParams, type CreateWebhookEnvelopeOptions, type CustomPeriod, type CwvBucket, type DailyAnonInput, type DataDetailOptions, type DataQueryOptions, type DateRange, type DateRangeResult, type DeletePartnerUserResponse, type EntityDailySparklineQuery, type EntityDailyTimeseriesQuery, GSC_COLUMN_OPTIONS, GSC_PERIOD_OPTIONS, GSC_PERIOD_OPTIONS_LONG, GSC_STABLE_LATENCY_DAYS, type GscAnalyzerAccent, type GscAnalyzerCapabilities, type GscAnalyzerCapability, type GscAnalyzerDefinition, type GscAnalyzerDefinitionWithCapability, type GscAnalyzerInsightCard, type GscAnalyzerKind, type GscAnalyzerPanelResult, type GscAnalyzerPanelSpec, type GscAnalyzerStatTile, type GscClassifiedError, type GscColumn, type GscColumnOption, type GscComparisonFilter, type GscConsoleUrlOpts, type GscDailySummary, type GscErrorStatus, type GscRowTotals, type GscdumpAnalysisParams, type GscdumpAnalysisPreset, type GscdumpAnalysisResponse, type GscdumpAnalysisSourcesResponse, type GscdumpAvailableSite, type GscdumpCanonicalMismatchesResponse, type GscdumpDataDetailResponse, type GscdumpDataResponse, type GscdumpDataRow, type GscdumpDateRangeParams, type GscdumpIndexPercentResponse, type GscdumpIndexingDiagnosticsResponse, type GscdumpIndexingResponse, type GscdumpIndexingUrlStatus, type GscdumpIndexingUrlsResponse, type GscdumpKeywordSparklinesParams, type GscdumpKeywordSparklinesResponse, type GscdumpMeta, type GscdumpPageTrendParams, type GscdumpPageTrendResponse, type GscdumpPermissionRecovery, type GscdumpQueryTrendParams, type GscdumpQueryTrendResponse, type GscdumpSiteRegistration, type GscdumpSitemap, type GscdumpSitemapChangesResponse, type GscdumpSitemapHistory, type GscdumpSitemapsResponse, type GscdumpSyncStatusResponse, type GscdumpTeamMemberRow, type GscdumpTeamRow, type GscdumpTopAssociationParams, type GscdumpTopAssociationResponse, type GscdumpTotals, type GscdumpUserRegistration, type GscdumpUserSettings, type GscdumpUserSite, type GscdumpUserStatus, type GscdumpUserTokenUpdate, type HealthStage, type HealthVerdict, type IndexingDiagnosticsParams, type IndexingIssue, type IndexingIssueDetail, type IndexingUrlsParams, type InspectionHistoryResponse, type InspectionIndex, type IssueGroup, type IssueSeverity, type MultiSeriesStackedDailyQuery, PERIOD_PRESETS, PartnerApiError, type PartnerClient, type PartnerClientOptions, type PartnerErrorInfo, type PartnerErrorKind, type PartnerFetch, type PartnerFetchOptions, type PartnerHeaders, type PartnerLifecycleAccount, type PartnerLifecycleResponse, type PartnerLifecycleSite, type PartnerRealtimeClient, type PartnerRealtimeEvent, type PartnerRealtimeEventType, type PartnerRealtimeHandler, type PartnerRealtimeMessage, type PartnerRealtimeOptions, type PartnerRealtimeScope, type PartnerRealtimeStatus, type PartnerWebSocketConstructor, type PartnerWebSocketLike, type PartnerWebhookData, type PartnerWebhookHeaders, type PeerBaselineInput, type PeerConfidence, type PeerStanding, type Period, type PeriodPreset, type QueryArchetype, type RawDailyRow, type ReachStage, type ReachVerdict, type RealtimeAuthFailedEvent, type RealtimeAuthRequiredMessage, type RealtimeConnectedMessage, type RealtimeEnrichmentCompleteEvent, type RealtimeErrorMessage, type RealtimeJobFailedEvent, type RealtimeNeedsReauthEvent, type RealtimePongMessage, type RealtimeSiteAddedEvent, type RealtimeSiteRemovedEvent, type RealtimeSubscribedMessage, type RealtimeSyncCompleteEvent, type RealtimeSyncFailedEvent, type RealtimeSyncJobCompleteEvent, type RealtimeSyncProgressEvent, type RealtimeSyncSiteCompleteEvent, type RegisterPartnerSiteParams, type RegisterPartnerUserParams, type ResolvedArchetypeQuery, type RollingPeriod, type RollupEnvelope, SITE_TYPE_BASELINE, type SearchConsoleStage, type SearchConsoleStageEvidence, type SearchConsoleStageIssue, type SearchConsoleStageKey, type SearchConsoleStagePage, type SearchConsoleStageSeverity, type SearchConsoleStageSitemap, type SearchConsoleStageSummary, type SearchConsoleStageTrajectory, type SingleRowLookupQuery, type SiteBaseline, type SiteDailyTimeseriesQuery, type SiteTriage, type SiteTriageInput, type SiteType, type SiteTypeBaseline, type TopNBreakdownQuery, type TriageEvidence, type TwoDimensionDetailQuery, type UpdatePartnerUserTokensParams, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, type WebhookEnvelope, type WebhookEventType, type WhoamiResponse, analyticsStatusToSyncStatus, andFilter, classifyGscError, classifyHealthStage, classifyReachStage, classifySearchConsoleStage, classifySiteTriage, coerceRowMetrics, compareRange, countryName, coverageLabel, coverageLabels, createAnalyticsClient, createGscdumpClient, createGscdumpRealtimeClient, createPartnerClient, createPartnerRealtimeClient, cwvBucket, dateFilter, defineGscAnalyzer, derivePeerStanding, deriveSiteBaseline, enrichIssueDetails, findLifecycleSite, formatPartnerError, getGscUnstableCutoffDate, gscConsoleUrl, investigationStatusConfig, isCustomPeriod, isPartnerError, issueDetails, issueGroups, issueTypeToGroup, lifecycleSiteToSyncStatus, lifecycleSiteToUserSite, normalizeSiteType, nuxtSeoTips, parseCustomPeriod, parseWebhookPayload, parseWebhookPayloadResult, partnerErrorToException, periodToDateRange, periodToDays, positionFor, reachLivenessRatio, readWebhookHeaders, serializeWebhookPayload, severityOrder, siteTypeBaseline, siteUrlToHostname, splitOpportunityTitle, summarizeDailyRows, toPartnerError, truncateQuery, verifyWebhookSignature, weightedAnonPct };
755
+ type WireDateRange = import__gscdump_contracts_archetypes.WireDateRange;
756
+ export { ARCHETYPE_EXECUTION_CLASS, type AddPartnerTeamMemberParams, type AnalysisSourcesOptions, type AnalyticsClient, type AnalyticsClientOptions, type AnalyticsFetch, type AnalyticsFetchOptions, type AnalyticsHeaders, type ArbitrarySqlQuery, type ArchetypeExecutionClass, type ArchetypeFacet, type ArchetypeQuery, type ArchetypeQueryBase, type ArchetypeResult, type ArchetypeResultRow, type ArchetypeResultSource, type AuxCloudOnlyQuery, type BackfillRange, type BackfillResponse, type BindPartnerSiteTeamParams, type BuilderState, type BulkRegisterPartnerSiteResult, type BulkRegisterPartnerSitesParams, type BulkRegisterPartnerSitesResponse, CANONICAL_WEBHOOK_EVENTS, COMPARE_OPTIONS, COUNTRY_NAMES, CWV_GOOD_CLS, CWV_GOOD_INP, CWV_GOOD_LCP, CWV_POOR_CLS, CWV_POOR_INP, CWV_POOR_LCP, type CalendarPeriod, type CanonicalDailyRow, type CanonicalWebhookEventType, type ClassifySearchConsoleStageInput, type CompareMode, type CreatePartnerTeamParams, type CreateWebhookEnvelopeOptions, type CustomPeriod, type CwvBucket, DEFAULT_SEARCH_TYPE, type DailyAnonInput, type DataDetailOptions, type DataQueryOptions, type DateRange, type DateRangeResult, type DeletePartnerUserResponse, type EntityDailySparklineQuery, type EntityDailyTimeseriesQuery, GSC_COLUMN_OPTIONS, GSC_PERIOD_OPTIONS, GSC_PERIOD_OPTIONS_LONG, GSC_STABLE_LATENCY_DAYS, type GscAnalyzerAccent, type GscAnalyzerCapabilities, type GscAnalyzerCapability, type GscAnalyzerDefinition, type GscAnalyzerDefinitionWithCapability, type GscAnalyzerInsightCard, type GscAnalyzerKind, type GscAnalyzerPanelResult, type GscAnalyzerPanelSpec, type GscAnalyzerStatTile, type GscClassifiedError, type GscColumn, type GscColumnOption, type GscComparisonFilter, type GscConsoleUrlOpts, type GscDailySummary, type GscErrorStatus, type GscRowTotals, type GscdumpAnalysisParams, type GscdumpAnalysisPreset, type GscdumpAnalysisResponse, type GscdumpAnalysisSourcesResponse, type GscdumpAvailableSite, type GscdumpCanonicalMismatchesResponse, type GscdumpDataDetailResponse, type GscdumpDataResponse, type GscdumpDataRow, type GscdumpDateRangeParams, type GscdumpIndexPercentResponse, type GscdumpIndexingDiagnosticsResponse, type GscdumpIndexingResponse, type GscdumpIndexingUrlStatus, type GscdumpIndexingUrlsResponse, type GscdumpKeywordSparklinesParams, type GscdumpKeywordSparklinesResponse, type GscdumpMeta, type GscdumpPageTrendParams, type GscdumpPageTrendResponse, type GscdumpPermissionRecovery, type GscdumpQueryTrendParams, type GscdumpQueryTrendResponse, type GscdumpSiteRegistration, type GscdumpSitemap, type GscdumpSitemapChangesResponse, type GscdumpSitemapHistory, type GscdumpSitemapsResponse, type GscdumpSyncStatusResponse, type GscdumpTeamMemberRow, type GscdumpTeamRow, type GscdumpTopAssociationParams, type GscdumpTopAssociationResponse, type GscdumpTotals, type GscdumpUserRegistration, type GscdumpUserSettings, type GscdumpUserSite, type GscdumpUserStatus, type GscdumpUserTokenUpdate, type HealthStage, type HealthVerdict, type IndexingDiagnosticsParams, type IndexingIssue, type IndexingIssueDetail, type IndexingUrlsParams, type InspectionHistoryResponse, type InspectionIndex, type IssueGroup, type IssueSeverity, type LifecycleSiteLike, type MultiSeriesStackedDailyQuery, PERIOD_PRESETS, PartnerApiError, type PartnerClient, type PartnerClientOptions, type PartnerErrorInfo, type PartnerErrorKind, type PartnerFetch, type PartnerFetchOptions, type PartnerHeaders, type PartnerLifecycleAccount, type PartnerLifecycleResponse, type PartnerLifecycleSite, type PartnerWebhookData, type PartnerWebhookHeaders, type PeerBaselineInput, type PeerConfidence, type PeerStanding, type Period, type PeriodOptions, type PeriodPreset, type QueryArchetype, type RawDailyRow, type ReachStage, type ReachVerdict, type RegisterPartnerSiteParams, type RegisterPartnerUserParams, type ResolvedArchetypeQuery, type RollingPeriod, type RollupEnvelope, SITE_TYPE_BASELINE, type SearchConsoleStage, type SearchConsoleStageEvidence, type SearchConsoleStageIssue, type SearchConsoleStageKey, type SearchConsoleStagePage, type SearchConsoleStageSeverity, type SearchConsoleStageSitemap, type SearchConsoleStageSummary, type SearchConsoleStageTrajectory, type SearchTypeOptions, type SingleRowLookupQuery, type SiteBaseline, type SiteDailyTimeseriesQuery, type SiteTriage, type SiteTriageInput, type SiteType, type SiteTypeBaseline, type SourceRangeOptions, type TopNBreakdownQuery, type TriageEvidence, type TwoDimensionDetailQuery, type UpdatePartnerUserTokensParams, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, type WebhookEnvelope, type WebhookEventType, type WhoamiResponse, type WireDateRange, analyticsStatusToSyncStatus, andFilter, arbitrarySql, auxCloudOnly, classifyGscError, classifyHealthStage, classifyReachStage, classifySearchConsoleStage, classifySiteTriage, coerceRowMetrics, compareRange, countryName, coverageLabel, coverageLabels, createAnalyticsClient, createPartnerClient, cwvBucket, dateFilter, dateRangeOptionsQuery, defineGscAnalyzer, derivePeerStanding, deriveSiteBaseline, enrichIssueDetails, entityDailySparkline, entityDailyTimeseries, findLifecycleSite, formatPartnerError, getGscUnstableCutoffDate, gscConsoleUrl, investigationStatusConfig, isCustomPeriod, isPartnerError, issueDetails, issueGroups, issueTypeToGroup, lifecycleSiteToSyncStatus, lifecycleSiteToUserSite, multiSeriesStackedDaily, normalizeSiteType, nuxtSeoTips, parseCustomPeriod, parseWebhookPayload, parseWebhookPayloadResult, partnerErrorToException, periodToDateRange, periodToDays, positionFor, reachLivenessRatio, readWebhookHeaders, searchTypeQuery, serializeWebhookPayload, severityOrder, singleRowLookup, siteDailyTimeseries, siteTypeBaseline, siteUrlToHostname, sourceInfoQuery, splitOpportunityTitle, summarizeDailyRows, tablesQuery, toPartnerError, topNBreakdown, truncateQuery, twoDimensionDetail, verifyWebhookSignature, weightedAnonPct, withDefaultSearchType };
package/dist/index.mjs CHANGED
@@ -1,13 +1,13 @@
1
- import { __exportAll, __reExport } from "./_chunks/rolldown-runtime.mjs";
2
- import { query_exports } from "./query.mjs";
3
1
  import { analyticsEndpoints } from "@gscdump/contracts/analytics";
4
2
  import { err, ok, unwrapResult } from "gscdump/result";
5
3
  import { ofetch } from "ofetch";
6
- import { partnerEndpoints, partnerRoutes } from "@gscdump/contracts/partner";
4
+ import { ARCHETYPE_EXECUTION_CLASS as ARCHETYPE_EXECUTION_CLASS$1, arbitrarySql as arbitrarySql$1, auxCloudOnly as auxCloudOnly$1, entityDailySparkline as entityDailySparkline$1, entityDailyTimeseries as entityDailyTimeseries$1, multiSeriesStackedDaily as multiSeriesStackedDaily$1, singleRowLookup as singleRowLookup$1, siteDailyTimeseries as siteDailyTimeseries$1, topNBreakdown as topNBreakdown$1, twoDimensionDetail as twoDimensionDetail$1 } from "@gscdump/contracts/archetypes";
5
+ import { partnerEndpoints } from "@gscdump/contracts/partner";
7
6
  import { resolveWindow } from "@gscdump/engine/period";
8
7
  import { endOfMonth, format, startOfMonth, startOfQuarter, startOfWeek, subDays, subMonths } from "date-fns";
9
8
  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";
10
9
  export * from "@gscdump/contracts";
10
+ const DEFAULT_SEARCH_TYPE = "web";
11
11
  function isAnalysisSourcesOptions(value) {
12
12
  return !!value && typeof value === "object" && !Array.isArray(value);
13
13
  }
@@ -49,6 +49,9 @@ function tablesQuery(tablesOrOptions, options) {
49
49
  ...dateRangeOptionsQuery(source)
50
50
  };
51
51
  if (tables) query.tables = Array.isArray(tables) ? [...new Set(tables.filter(Boolean))].sort().join(",") : [...new Set(tables.split(",").map((t) => t.trim()).filter(Boolean))].sort().join(",");
52
+ if (source?.maxBytes != null) query.maxBytes = String(Math.max(1, Math.floor(source.maxBytes)));
53
+ if (source?.maxRows != null) query.maxRows = String(Math.max(1, Math.floor(source.maxRows)));
54
+ if (source?.maxFiles != null) query.maxFiles = String(Math.max(1, Math.floor(source.maxFiles)));
52
55
  return query;
53
56
  }
54
57
  function dataQuery(state, options) {
@@ -186,10 +189,10 @@ function formatPartnerError(error) {
186
189
  function partnerErrorToException(error) {
187
190
  return error;
188
191
  }
189
- const TRAILING_SLASH_RE$1 = /\/+$/;
192
+ const TRAILING_SLASH_RE = /\/+$/;
190
193
  const LEADING_SLASH_RE = /^\/+/;
191
194
  function trimApiBase(apiBase, fallback) {
192
- return (apiBase ?? fallback).replace(TRAILING_SLASH_RE$1, "");
195
+ return (apiBase ?? fallback).replace(TRAILING_SLASH_RE, "");
193
196
  }
194
197
  function buildPath(apiBase, path) {
195
198
  if (!apiBase) return path.startsWith("/") ? path : `/${path}`;
@@ -398,9 +401,16 @@ function weightedAnonPct(days, window = 28) {
398
401
  }
399
402
  return totalImpressions > 0 ? weighted / totalImpressions : null;
400
403
  }
401
- var archetypes_exports = /* @__PURE__ */ __exportAll({});
402
- import * as import__gscdump_contracts_archetypes from "@gscdump/contracts/archetypes";
403
- __reExport(archetypes_exports, import__gscdump_contracts_archetypes);
404
+ const ARCHETYPE_EXECUTION_CLASS = ARCHETYPE_EXECUTION_CLASS$1;
405
+ const arbitrarySql = arbitrarySql$1;
406
+ const auxCloudOnly = auxCloudOnly$1;
407
+ const entityDailySparkline = entityDailySparkline$1;
408
+ const entityDailyTimeseries = entityDailyTimeseries$1;
409
+ const multiSeriesStackedDaily = multiSeriesStackedDaily$1;
410
+ const singleRowLookup = singleRowLookup$1;
411
+ const siteDailyTimeseries = siteDailyTimeseries$1;
412
+ const topNBreakdown = topNBreakdown$1;
413
+ const twoDimensionDetail = twoDimensionDetail$1;
404
414
  function normalizeLifecycleUrl(url) {
405
415
  return (url || "").replace(/^sc-domain:/, "").replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/$/, "").toLowerCase();
406
416
  }
@@ -858,7 +868,6 @@ function createPartnerClient(options = {}) {
858
868
  }
859
869
  };
860
870
  }
861
- const createGscdumpClient = createPartnerClient;
862
871
  const COUNTRY_NAMES = {
863
872
  US: "United States",
864
873
  GB: "United Kingdom",
@@ -965,10 +974,11 @@ function classifyGscError(e) {
965
974
  code,
966
975
  message
967
976
  };
968
- if (code === 429) {
969
- const retry = e?.data?.retryAfter;
977
+ if (code === 429 || code === 503) {
978
+ const data = e?.data;
979
+ const retry = data?.retryAfter ?? data?.retryAfterSeconds;
970
980
  return {
971
- status: "rate-limited",
981
+ status: code === 429 ? "rate-limited" : "network",
972
982
  code,
973
983
  message,
974
984
  retryAfter: typeof retry === "number" ? retry : void 0
@@ -1133,19 +1143,26 @@ function coerceRowMetrics(row) {
1133
1143
  };
1134
1144
  }
1135
1145
  function summarizeDailyRows(raw) {
1136
- const daily = raw.map(coerceRowMetrics).map((r) => ({
1137
- date: r.date,
1138
- clicks: r.clicks,
1139
- impressions: r.impressions,
1140
- sum_position: r.sum_position
1141
- })).sort((a, b) => a.date.localeCompare(b.date));
1146
+ const daily = [];
1147
+ for (let index = 0; index < raw.length; index++) {
1148
+ const row = raw[index];
1149
+ const position = row.position ?? 0;
1150
+ const sumPosition = row.sum_position ?? (position > 0 ? (position - 1) * row.impressions : 0);
1151
+ daily.push({
1152
+ date: row.date,
1153
+ clicks: row.clicks,
1154
+ impressions: row.impressions,
1155
+ sum_position: sumPosition
1156
+ });
1157
+ }
1158
+ daily.sort((a, b) => a.date.localeCompare(b.date));
1142
1159
  let clicks = 0;
1143
1160
  let impressions = 0;
1144
1161
  let weightedPosition = 0;
1145
- for (const d of daily) {
1146
- clicks += d.clicks;
1147
- impressions += d.impressions;
1148
- weightedPosition += d.sum_position;
1162
+ for (const row of daily) {
1163
+ clicks += row.clicks;
1164
+ impressions += row.impressions;
1165
+ weightedPosition += row.sum_position;
1149
1166
  }
1150
1167
  return {
1151
1168
  daily,
@@ -1481,8 +1498,14 @@ function parseCustomPeriod(p) {
1481
1498
  end
1482
1499
  };
1483
1500
  }
1484
- function todayInPST() {
1485
- return /* @__PURE__ */ new Date(`${(0, query_exports.currentPstDate)()}T00:00:00`);
1501
+ function todayInTimezone(timezone = "America/Los_Angeles", now = /* @__PURE__ */ new Date()) {
1502
+ const date = new Intl.DateTimeFormat("en-CA", {
1503
+ timeZone: timezone,
1504
+ year: "numeric",
1505
+ month: "2-digit",
1506
+ day: "2-digit"
1507
+ }).format(now);
1508
+ return /* @__PURE__ */ new Date(`${date}T00:00:00`);
1486
1509
  }
1487
1510
  const ROLLING_TO_UPSTREAM = {
1488
1511
  "7d": "last-7d",
@@ -1524,7 +1547,9 @@ function buildResultFromIso(start, end) {
1524
1547
  days
1525
1548
  };
1526
1549
  }
1527
- function periodToDateRange(period, stableData = true) {
1550
+ function periodToDateRange(period, stableDataOrOptions = true) {
1551
+ const options = typeof stableDataOrOptions === "boolean" ? { stableData: stableDataOrOptions } : stableDataOrOptions;
1552
+ const stableData = options.stableData ?? true;
1528
1553
  const custom = parseCustomPeriod(period);
1529
1554
  if (custom) {
1530
1555
  const result = buildResultFromIso(custom.start, custom.end);
@@ -1537,7 +1562,7 @@ function periodToDateRange(period, stableData = true) {
1537
1562
  };
1538
1563
  return result;
1539
1564
  }
1540
- const today = todayInPST();
1565
+ const today = todayInTimezone(options.timezone, options.now);
1541
1566
  const end = stableData ? subDays(today, 3) : subDays(today, 1);
1542
1567
  const endIso = fmt(end);
1543
1568
  const upstreamPreset = ROLLING_TO_UPSTREAM[period] ?? CALENDAR_TO_UPSTREAM[period];
@@ -1564,8 +1589,8 @@ function periodToDateRange(period, stableData = true) {
1564
1589
  }
1565
1590
  return buildResultFromIso(fmt(start), endIso);
1566
1591
  }
1567
- function periodToDays(period) {
1568
- return periodToDateRange(period).days;
1592
+ function periodToDays(period, stableDataOrOptions = true) {
1593
+ return periodToDateRange(period, stableDataOrOptions).days;
1569
1594
  }
1570
1595
  function compareRange(range, mode) {
1571
1596
  if (mode === "none") return null;
@@ -1583,189 +1608,6 @@ function getGscUnstableCutoffDate() {
1583
1608
  const cutoff = new Date(y, m - 1, d - 3);
1584
1609
  return `${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, "0")}-${String(cutoff.getDate()).padStart(2, "0")}`;
1585
1610
  }
1586
- function resolveReconnect(reconnect) {
1587
- const opts = reconnect === false ? { enabled: false } : reconnect === true || reconnect == null ? {} : reconnect;
1588
- return {
1589
- enabled: opts.enabled ?? true,
1590
- baseDelayMs: opts.baseDelayMs ?? 1e3,
1591
- maxDelayMs: opts.maxDelayMs ?? 3e4,
1592
- maxRetries: opts.maxRetries ?? Number.POSITIVE_INFINITY,
1593
- jitter: opts.jitter ?? true
1594
- };
1595
- }
1596
- const HTTP_PROTOCOL_RE = /^http/i;
1597
- const API_SUFFIX_RE = /\/api\/?$/;
1598
- const TRAILING_SLASH_RE = /\/+$/;
1599
- function inferWsBase(options) {
1600
- if (options.wsBase) return options.wsBase.replace(TRAILING_SLASH_RE, "");
1601
- if (!options.apiBase) return "";
1602
- return options.apiBase.replace(API_SUFFIX_RE, "").replace(TRAILING_SLASH_RE, "").replace(HTTP_PROTOCOL_RE, (m) => m.toLowerCase() === "https" ? "wss" : "ws");
1603
- }
1604
- function wsPath(scope) {
1605
- return scope === "partner" ? partnerRoutes.realtime.partner : partnerRoutes.realtime.user;
1606
- }
1607
- function buildWsUrl(options) {
1608
- const scope = options.scope ?? "partner";
1609
- const base = inferWsBase(options);
1610
- if (!base) return wsPath(scope);
1611
- return `${base}${wsPath(scope)}`;
1612
- }
1613
- function parseMessage(raw) {
1614
- if (typeof raw !== "string") return null;
1615
- try {
1616
- return JSON.parse(raw);
1617
- } catch {
1618
- return null;
1619
- }
1620
- }
1621
- function isRealtimeEvent(message) {
1622
- return "event" in message && message.event !== "auth.required" && message.event !== "connected";
1623
- }
1624
- function getWebSocketCtor(options) {
1625
- const ctor = options.WebSocket ?? globalThis.WebSocket;
1626
- if (!ctor) throw new Error("WebSocket is not available; pass options.WebSocket");
1627
- return ctor;
1628
- }
1629
- function createPartnerRealtimeClient(options) {
1630
- let socket = null;
1631
- let status = "idle";
1632
- const reconnect = resolveReconnect(options.reconnect);
1633
- const setTimer = options.setTimeout ?? ((handler, ms) => setTimeout(handler, ms));
1634
- const clearTimer = options.clearTimeout ?? ((handle) => clearTimeout(handle));
1635
- let manualClose = false;
1636
- let reconnectAttempts = 0;
1637
- let reconnectTimer = null;
1638
- const statusHandlers = /* @__PURE__ */ new Set();
1639
- const messageHandlers = /* @__PURE__ */ new Set();
1640
- const eventHandlers = /* @__PURE__ */ new Set();
1641
- const errorHandlers = /* @__PURE__ */ new Set();
1642
- function setStatus(next) {
1643
- status = next;
1644
- for (const handler of statusHandlers) handler(next);
1645
- }
1646
- function sendJson(payload) {
1647
- if (!socket) throw new Error("Partner realtime client is not connected");
1648
- socket.send(JSON.stringify(payload));
1649
- }
1650
- function authPayload() {
1651
- const payload = {
1652
- type: "auth",
1653
- apiKey: options.apiKey
1654
- };
1655
- if (options.userId != null) payload.userId = options.userId;
1656
- return payload;
1657
- }
1658
- function subscribe(siteIds) {
1659
- sendJson({
1660
- type: "subscribe",
1661
- siteIds
1662
- });
1663
- }
1664
- function clearReconnectTimer() {
1665
- if (reconnectTimer != null) {
1666
- clearTimer(reconnectTimer);
1667
- reconnectTimer = null;
1668
- }
1669
- }
1670
- function backoffDelay(attempt) {
1671
- const exp = Math.min(reconnect.maxDelayMs, reconnect.baseDelayMs * 2 ** attempt);
1672
- if (!reconnect.jitter) return exp;
1673
- return Math.round(exp / 2 + Math.random() * (exp / 2));
1674
- }
1675
- function openSocket() {
1676
- if (socket) return socket;
1677
- clearReconnectTimer();
1678
- manualClose = false;
1679
- socket = new (getWebSocketCtor(options))(buildWsUrl(options), options.protocols);
1680
- setStatus("connecting");
1681
- socket.onopen = () => {
1682
- setStatus("open");
1683
- sendJson(authPayload());
1684
- };
1685
- socket.onmessage = (event) => {
1686
- const message = parseMessage(event.data);
1687
- if (!message) return;
1688
- if ("event" in message && message.event === "connected") {
1689
- reconnectAttempts = 0;
1690
- setStatus("authenticated");
1691
- if (options.siteIds?.length) subscribe(options.siteIds);
1692
- }
1693
- for (const handler of messageHandlers) handler(message);
1694
- if (isRealtimeEvent(message)) for (const handler of eventHandlers) handler(message);
1695
- };
1696
- socket.onerror = (event) => {
1697
- setStatus("error");
1698
- for (const handler of errorHandlers) handler(event);
1699
- };
1700
- socket.onclose = (event) => {
1701
- socket = null;
1702
- setStatus("closed");
1703
- for (const handler of messageHandlers) handler({
1704
- type: "error",
1705
- message: `WebSocket closed: ${JSON.stringify(event)}`
1706
- });
1707
- scheduleReconnect();
1708
- };
1709
- return socket;
1710
- }
1711
- function scheduleReconnect() {
1712
- if (!reconnect.enabled || manualClose || reconnectTimer != null) return;
1713
- if (reconnectAttempts >= reconnect.maxRetries) {
1714
- const err = /* @__PURE__ */ new Error(`Partner realtime reconnect exhausted after ${reconnectAttempts} attempts`);
1715
- for (const handler of errorHandlers) handler(err);
1716
- return;
1717
- }
1718
- const delay = backoffDelay(reconnectAttempts);
1719
- reconnectAttempts += 1;
1720
- setStatus("connecting");
1721
- reconnectTimer = setTimer(() => {
1722
- reconnectTimer = null;
1723
- openSocket();
1724
- }, delay);
1725
- }
1726
- return {
1727
- get status() {
1728
- return status;
1729
- },
1730
- get socket() {
1731
- return socket;
1732
- },
1733
- connect() {
1734
- return openSocket();
1735
- },
1736
- close(code, reason) {
1737
- manualClose = true;
1738
- clearReconnectTimer();
1739
- const ws = socket;
1740
- socket = null;
1741
- setStatus("closed");
1742
- if (!ws) return;
1743
- if (ws.readyState === 0) ws.onopen = () => ws.close(code, reason);
1744
- else ws.close(code, reason);
1745
- },
1746
- ping() {
1747
- sendJson({ type: "ping" });
1748
- },
1749
- subscribe,
1750
- onStatus(handler) {
1751
- statusHandlers.add(handler);
1752
- return () => statusHandlers.delete(handler);
1753
- },
1754
- onMessage(handler) {
1755
- messageHandlers.add(handler);
1756
- return () => messageHandlers.delete(handler);
1757
- },
1758
- onEvent(handler) {
1759
- eventHandlers.add(handler);
1760
- return () => eventHandlers.delete(handler);
1761
- },
1762
- onError(handler) {
1763
- errorHandlers.add(handler);
1764
- return () => errorHandlers.delete(handler);
1765
- }
1766
- };
1767
- }
1768
- const createGscdumpRealtimeClient = createPartnerRealtimeClient;
1769
1611
  function formatSearchConsoleCount(value) {
1770
1612
  return new Intl.NumberFormat("en").format(Math.max(0, Math.round(value)));
1771
1613
  }
@@ -1893,120 +1735,123 @@ function totalSitemapErrors(sitemaps) {
1893
1735
  function signedPct1(value) {
1894
1736
  return `${value >= 0 ? "+" : ""}${value.toFixed(1)}%`;
1895
1737
  }
1738
+ const SEARCH_CONSOLE_STAGES = {
1739
+ not_connected: {
1740
+ label: "Not connected",
1741
+ severity: "neutral",
1742
+ summary: "Search Console is not connected for this site yet.",
1743
+ primaryAction: "Connect Google Search Console so we can read discovery, indexing, and performance data.",
1744
+ nextStage: "waiting_for_data",
1745
+ sprintFindingTypes: []
1746
+ },
1747
+ waiting_for_data: {
1748
+ label: "Waiting for data",
1749
+ severity: "info",
1750
+ summary: "Search Console is connected, but there is not enough indexing data to diagnose the site yet.",
1751
+ primaryAction: "Let the first sync finish, then make sure a sitemap is submitted.",
1752
+ nextStage: "weak_discovery",
1753
+ sprintFindingTypes: []
1754
+ },
1755
+ weak_discovery: {
1756
+ label: "Weak discovery",
1757
+ severity: "warning",
1758
+ summary: "Google does not have a clean map of the pages you want indexed.",
1759
+ primaryAction: "Submit a clean sitemap that contains only canonical, indexable 200 URLs.",
1760
+ nextStage: "discovery_backlog",
1761
+ sprintFindingTypes: ["search-console-stage", "sitemap-missing"]
1762
+ },
1763
+ discovery_backlog: {
1764
+ label: "Discovery backlog",
1765
+ severity: "warning",
1766
+ summary: "Google knows these pages exist, but is not crawling them fast enough.",
1767
+ primaryAction: "Add internal links from indexed pages and remove low-value URLs from the sitemap.",
1768
+ nextStage: "crawl_blocked",
1769
+ sprintFindingTypes: ["search-console-stage"]
1770
+ },
1771
+ crawl_blocked: {
1772
+ label: "Crawl blocked",
1773
+ severity: "error",
1774
+ summary: "Google is trying to access pages, but technical access problems are blocking progress.",
1775
+ primaryAction: "Fix robots.txt blocks, server errors, broken URLs, and access failures before content work.",
1776
+ nextStage: "indexability_blocked",
1777
+ sprintFindingTypes: ["search-console-stage", "noindex-block"]
1778
+ },
1779
+ indexability_blocked: {
1780
+ label: "Indexability blocked",
1781
+ severity: "error",
1782
+ summary: "Google can reach pages, but index directives or canonical signals are preventing clean indexing.",
1783
+ primaryAction: "Remove accidental noindex directives and make canonical signals agree.",
1784
+ nextStage: "index_rejection",
1785
+ sprintFindingTypes: [
1786
+ "search-console-stage",
1787
+ "noindex-block",
1788
+ "canonicalisation"
1789
+ ]
1790
+ },
1791
+ index_rejection: {
1792
+ label: "Index rejection",
1793
+ severity: "warning",
1794
+ summary: "Google is crawling pages but skipping too many of them from the index.",
1795
+ primaryAction: "Improve or consolidate crawled-but-not-indexed pages before publishing more.",
1796
+ nextStage: "partially_indexed",
1797
+ sprintFindingTypes: ["search-console-stage", "pages-not-indexed"]
1798
+ },
1799
+ partially_indexed: {
1800
+ label: "Partially indexed",
1801
+ severity: "warning",
1802
+ summary: "A meaningful share of the site is indexed, but coverage is still below a healthy level.",
1803
+ primaryAction: "Work through the largest remaining indexing blocker first.",
1804
+ nextStage: "indexed_invisible",
1805
+ sprintFindingTypes: ["search-console-stage", "pages-not-indexed"]
1806
+ },
1807
+ indexed_invisible: {
1808
+ label: "Indexed but invisible",
1809
+ severity: "warning",
1810
+ summary: "Pages are indexed, but too many are not earning impressions in Search.",
1811
+ primaryAction: "Improve query targeting, titles, headings, internal links, and page depth.",
1812
+ nextStage: "visible_not_clicked",
1813
+ sprintFindingTypes: ["search-console-stage"]
1814
+ },
1815
+ visible_not_clicked: {
1816
+ label: "Visible but not clicked",
1817
+ severity: "warning",
1818
+ summary: "Google is showing your pages, but searchers are not clicking often enough.",
1819
+ primaryAction: "Rewrite titles and descriptions for the queries already producing impressions.",
1820
+ nextStage: "ranking_stalled",
1821
+ sprintFindingTypes: ["search-console-stage", "ctr-outliers"]
1822
+ },
1823
+ ranking_stalled: {
1824
+ label: "Ranking but stalled",
1825
+ severity: "info",
1826
+ summary: "The site has search visibility, but many pages are not yet ranking in useful positions.",
1827
+ primaryAction: "Prioritise striking-distance pages, refresh content, and add internal links.",
1828
+ nextStage: "healthy_growth_ready",
1829
+ sprintFindingTypes: ["striking-distance", "internal-linking"]
1830
+ },
1831
+ declining_visibility: {
1832
+ label: "Declining visibility",
1833
+ severity: "error",
1834
+ summary: "Search visibility is dropping compared with the previous period.",
1835
+ primaryAction: "Review affected pages, recent releases, competitors, and SERP changes before expanding.",
1836
+ nextStage: "healthy_growth_ready",
1837
+ sprintFindingTypes: ["search-console-stage", "negative-movers"]
1838
+ },
1839
+ healthy_growth_ready: {
1840
+ label: "Healthy",
1841
+ severity: "success",
1842
+ summary: "Google can discover, index, and show your pages.",
1843
+ primaryAction: "Push striking-distance pages (positions 11 to 20) and close content gaps to grow impressions.",
1844
+ nextStage: null,
1845
+ sprintFindingTypes: ["striking-distance", "competitor-content-gap"]
1846
+ }
1847
+ };
1896
1848
  function stage(key, evidence) {
1849
+ const definition = SEARCH_CONSOLE_STAGES[key];
1897
1850
  return {
1898
1851
  key,
1899
1852
  evidence,
1900
- ...{
1901
- not_connected: {
1902
- label: "Not connected",
1903
- severity: "neutral",
1904
- summary: "Search Console is not connected for this site yet.",
1905
- primaryAction: "Connect Google Search Console so we can read discovery, indexing, and performance data.",
1906
- nextStage: "waiting_for_data",
1907
- sprintFindingTypes: []
1908
- },
1909
- waiting_for_data: {
1910
- label: "Waiting for data",
1911
- severity: "info",
1912
- summary: "Search Console is connected, but there is not enough indexing data to diagnose the site yet.",
1913
- primaryAction: "Let the first sync finish, then make sure a sitemap is submitted.",
1914
- nextStage: "weak_discovery",
1915
- sprintFindingTypes: []
1916
- },
1917
- weak_discovery: {
1918
- label: "Weak discovery",
1919
- severity: "warning",
1920
- summary: "Google does not have a clean map of the pages you want indexed.",
1921
- primaryAction: "Submit a clean sitemap that contains only canonical, indexable 200 URLs.",
1922
- nextStage: "discovery_backlog",
1923
- sprintFindingTypes: ["search-console-stage", "sitemap-missing"]
1924
- },
1925
- discovery_backlog: {
1926
- label: "Discovery backlog",
1927
- severity: "warning",
1928
- summary: "Google knows these pages exist, but is not crawling them fast enough.",
1929
- primaryAction: "Add internal links from indexed pages and remove low-value URLs from the sitemap.",
1930
- nextStage: "crawl_blocked",
1931
- sprintFindingTypes: ["search-console-stage"]
1932
- },
1933
- crawl_blocked: {
1934
- label: "Crawl blocked",
1935
- severity: "error",
1936
- summary: "Google is trying to access pages, but technical access problems are blocking progress.",
1937
- primaryAction: "Fix robots.txt blocks, server errors, broken URLs, and access failures before content work.",
1938
- nextStage: "indexability_blocked",
1939
- sprintFindingTypes: ["search-console-stage", "noindex-block"]
1940
- },
1941
- indexability_blocked: {
1942
- label: "Indexability blocked",
1943
- severity: "error",
1944
- summary: "Google can reach pages, but index directives or canonical signals are preventing clean indexing.",
1945
- primaryAction: "Remove accidental noindex directives and make canonical signals agree.",
1946
- nextStage: "index_rejection",
1947
- sprintFindingTypes: [
1948
- "search-console-stage",
1949
- "noindex-block",
1950
- "canonicalisation"
1951
- ]
1952
- },
1953
- index_rejection: {
1954
- label: "Index rejection",
1955
- severity: "warning",
1956
- summary: "Google is crawling pages but skipping too many of them from the index.",
1957
- primaryAction: "Improve or consolidate crawled-but-not-indexed pages before publishing more.",
1958
- nextStage: "partially_indexed",
1959
- sprintFindingTypes: ["search-console-stage", "pages-not-indexed"]
1960
- },
1961
- partially_indexed: {
1962
- label: "Partially indexed",
1963
- severity: "warning",
1964
- summary: "A meaningful share of the site is indexed, but coverage is still below a healthy level.",
1965
- primaryAction: "Work through the largest remaining indexing blocker first.",
1966
- nextStage: "indexed_invisible",
1967
- sprintFindingTypes: ["search-console-stage", "pages-not-indexed"]
1968
- },
1969
- indexed_invisible: {
1970
- label: "Indexed but invisible",
1971
- severity: "warning",
1972
- summary: "Pages are indexed, but too many are not earning impressions in Search.",
1973
- primaryAction: "Improve query targeting, titles, headings, internal links, and page depth.",
1974
- nextStage: "visible_not_clicked",
1975
- sprintFindingTypes: ["search-console-stage"]
1976
- },
1977
- visible_not_clicked: {
1978
- label: "Visible but not clicked",
1979
- severity: "warning",
1980
- summary: "Google is showing your pages, but searchers are not clicking often enough.",
1981
- primaryAction: "Rewrite titles and descriptions for the queries already producing impressions.",
1982
- nextStage: "ranking_stalled",
1983
- sprintFindingTypes: ["search-console-stage", "ctr-outliers"]
1984
- },
1985
- ranking_stalled: {
1986
- label: "Ranking but stalled",
1987
- severity: "info",
1988
- summary: "The site has search visibility, but many pages are not yet ranking in useful positions.",
1989
- primaryAction: "Prioritise striking-distance pages, refresh content, and add internal links.",
1990
- nextStage: "healthy_growth_ready",
1991
- sprintFindingTypes: ["striking-distance", "internal-linking"]
1992
- },
1993
- declining_visibility: {
1994
- label: "Declining visibility",
1995
- severity: "error",
1996
- summary: "Search visibility is dropping compared with the previous period.",
1997
- primaryAction: "Review affected pages, recent releases, competitors, and SERP changes before expanding.",
1998
- nextStage: "healthy_growth_ready",
1999
- sprintFindingTypes: ["search-console-stage", "negative-movers"]
2000
- },
2001
- healthy_growth_ready: {
2002
- label: "Healthy",
2003
- severity: "success",
2004
- summary: "Google can discover, index, and show your pages.",
2005
- primaryAction: "Push striking-distance pages (positions 11 to 20) and close content gaps to grow impressions.",
2006
- nextStage: null,
2007
- sprintFindingTypes: ["striking-distance", "competitor-content-gap"]
2008
- }
2009
- }[key]
1853
+ ...definition,
1854
+ sprintFindingTypes: [...definition.sprintFindingTypes]
2010
1855
  };
2011
1856
  }
2012
1857
  const ESTABLISHED_IMPRESSIONS_28D$1 = 2e4;
@@ -2039,8 +1884,13 @@ function classifySearchConsoleStage(input) {
2039
1884
  const crawled = countSearchConsoleIssues(issues, "crawled_not_indexed");
2040
1885
  const hardBlocks = countSearchConsoleIssues(issues, "blocked_robots", "server_error", "access_denied", "forbidden") + (input.crawlAuditBlockerCount ?? 0);
2041
1886
  const canonicalMismatches = Math.min(notIndexed, input.canonicalMismatchCount ?? countSearchConsoleIssues(issues, "canonical_mismatch"));
2042
- const visibleNoClickPages = (input.pageInventory ?? []).filter((page) => page.impressions >= 50 && page.clicks === 0).length;
2043
- const poorPositionPages = (input.pageInventory ?? []).filter((page) => page.impressions >= 50 && (page.position ?? 0) > 20).length;
1887
+ let visibleNoClickPages = 0;
1888
+ let poorPositionPages = 0;
1889
+ for (const page of input.pageInventory ?? []) {
1890
+ if (page.impressions < 50) continue;
1891
+ if (page.clicks === 0) visibleNoClickPages++;
1892
+ if ((page.position ?? 0) > 20) poorPositionPages++;
1893
+ }
2044
1894
  const ctrOutlierCount = input.ctrOutlierCount ?? 0;
2045
1895
  const traj = input.trajectory ?? null;
2046
1896
  const impressions28d = input.impressions28d ?? null;
@@ -2508,5 +2358,4 @@ function readWebhookHeaders(headers) {
2508
2358
  signature: headers.signature ?? null
2509
2359
  };
2510
2360
  }
2511
- var ARCHETYPE_EXECUTION_CLASS = archetypes_exports.ARCHETYPE_EXECUTION_CLASS;
2512
- export { ARCHETYPE_EXECUTION_CLASS, CANONICAL_WEBHOOK_EVENTS, COMPARE_OPTIONS, COUNTRY_NAMES, CWV_GOOD_CLS, CWV_GOOD_INP, CWV_GOOD_LCP, CWV_POOR_CLS, CWV_POOR_INP, CWV_POOR_LCP, GSC_COLUMN_OPTIONS, GSC_PERIOD_OPTIONS, GSC_PERIOD_OPTIONS_LONG, GSC_STABLE_LATENCY_DAYS, PERIOD_PRESETS, PartnerApiError, SITE_TYPE_BASELINE, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, analyticsStatusToSyncStatus, andFilter, classifyGscError, classifyHealthStage, classifyReachStage, classifySearchConsoleStage, classifySiteTriage, coerceRowMetrics, compareRange, countryName, coverageLabel, coverageLabels, createAnalyticsClient, createGscdumpClient, createGscdumpRealtimeClient, createPartnerClient, createPartnerRealtimeClient, cwvBucket, dateFilter, defineGscAnalyzer, derivePeerStanding, deriveSiteBaseline, enrichIssueDetails, findLifecycleSite, formatPartnerError, getGscUnstableCutoffDate, gscConsoleUrl, investigationStatusConfig, isCustomPeriod, isPartnerError, issueDetails, issueGroups, issueTypeToGroup, lifecycleSiteToSyncStatus, lifecycleSiteToUserSite, normalizeSiteType, nuxtSeoTips, parseCustomPeriod, parseWebhookPayload, parseWebhookPayloadResult, partnerErrorToException, periodToDateRange, periodToDays, positionFor, reachLivenessRatio, readWebhookHeaders, serializeWebhookPayload, severityOrder, siteTypeBaseline, siteUrlToHostname, splitOpportunityTitle, summarizeDailyRows, toPartnerError, truncateQuery, verifyWebhookSignature, weightedAnonPct };
2361
+ export { ARCHETYPE_EXECUTION_CLASS, CANONICAL_WEBHOOK_EVENTS, COMPARE_OPTIONS, COUNTRY_NAMES, CWV_GOOD_CLS, CWV_GOOD_INP, CWV_GOOD_LCP, CWV_POOR_CLS, CWV_POOR_INP, CWV_POOR_LCP, DEFAULT_SEARCH_TYPE, GSC_COLUMN_OPTIONS, GSC_PERIOD_OPTIONS, GSC_PERIOD_OPTIONS_LONG, GSC_STABLE_LATENCY_DAYS, PERIOD_PRESETS, PartnerApiError, SITE_TYPE_BASELINE, VALID_WEBHOOK_EVENTS, WEBHOOK_CONTRACT_VERSION, WEBHOOK_CONTRACT_VERSION_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_TIMESTAMP_HEADER, analyticsStatusToSyncStatus, andFilter, arbitrarySql, auxCloudOnly, classifyGscError, classifyHealthStage, classifyReachStage, classifySearchConsoleStage, classifySiteTriage, coerceRowMetrics, compareRange, countryName, coverageLabel, coverageLabels, createAnalyticsClient, createPartnerClient, cwvBucket, dateFilter, dateRangeOptionsQuery, defineGscAnalyzer, derivePeerStanding, deriveSiteBaseline, enrichIssueDetails, entityDailySparkline, entityDailyTimeseries, findLifecycleSite, formatPartnerError, getGscUnstableCutoffDate, gscConsoleUrl, investigationStatusConfig, isCustomPeriod, isPartnerError, issueDetails, issueGroups, issueTypeToGroup, lifecycleSiteToSyncStatus, lifecycleSiteToUserSite, multiSeriesStackedDaily, normalizeSiteType, nuxtSeoTips, parseCustomPeriod, parseWebhookPayload, parseWebhookPayloadResult, partnerErrorToException, periodToDateRange, periodToDays, positionFor, reachLivenessRatio, readWebhookHeaders, searchTypeQuery, serializeWebhookPayload, severityOrder, singleRowLookup, siteDailyTimeseries, siteTypeBaseline, siteUrlToHostname, sourceInfoQuery, splitOpportunityTitle, summarizeDailyRows, tablesQuery, toPartnerError, topNBreakdown, truncateQuery, twoDimensionDetail, verifyWebhookSignature, weightedAnonPct, withDefaultSearchType };
package/dist/query.mjs CHANGED
@@ -1,6 +1,2 @@
1
- import { __exportAll, __reExport } from "./_chunks/rolldown-runtime.mjs";
2
1
  export * from "gscdump/query";
3
- var query_exports = /* @__PURE__ */ __exportAll({});
4
- import * as import_gscdump_query from "gscdump/query";
5
- __reExport(query_exports, import_gscdump_query);
6
- export { query_exports };
2
+ export {};
@@ -71,7 +71,21 @@ declare function isGscdumpV1Error(error: unknown): error is GscdumpV1Error;
71
71
  interface GscdumpV1Client {
72
72
  execute: <TId extends GscdumpV1OperationId>(operation: TId, input: GscdumpV1OperationInput<TId>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<TId>>;
73
73
  getUserLifecycle: (input: GscdumpV1OperationInput<'partner.users.lifecycle.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.lifecycle.get'>>;
74
+ listAvailableSites: (input: GscdumpV1OperationInput<'partner.users.sites.available.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.sites.available.list'>>;
75
+ createSite: (input: GscdumpV1OperationInput<'partner.users.sites.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.sites.create'>>;
76
+ createUser: (input: GscdumpV1OperationInput<'partner.users.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.create'>>;
77
+ updateUserTokens: (input: GscdumpV1OperationInput<'partner.users.tokens.update'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.users.tokens.update'>>;
78
+ getSiteIndexing: (input: GscdumpV1OperationInput<'partner.sites.indexing.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.get'>>;
79
+ listSiteIndexingUrls: (input: GscdumpV1OperationInput<'partner.sites.indexing.urls.list'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.urls.list'>>;
80
+ getSiteIndexingDiagnostics: (input: GscdumpV1OperationInput<'partner.sites.indexing.diagnostics.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.indexing.diagnostics.get'>>;
81
+ getSiteSitemaps: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.get'>>;
82
+ getSiteSitemapChanges: (input: GscdumpV1OperationInput<'partner.sites.sitemaps.changes.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'partner.sites.sitemaps.changes.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'>>;
74
86
  queryAnalyticsRows: (input: GscdumpV1OperationInput<'analytics.rows.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'analytics.rows.query'>>;
87
+ queryAnalyticsReport: (input: GscdumpV1OperationInput<'analytics.reports.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'analytics.reports.query'>>;
88
+ queryAnalyticsReportDetail: (input: GscdumpV1OperationInput<'analytics.reports.detail.query'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'analytics.reports.detail.query'>>;
75
89
  getRealtimeStreamHead: (input?: GscdumpV1OperationInput<'realtime.stream.head.get'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'realtime.stream.head.get'>>;
76
90
  createRealtimeTicket: (input: GscdumpV1OperationInput<'realtime.tickets.create'>, options?: GscdumpV1ExecuteOptions) => Promise<GscdumpV1OperationResponse<'realtime.tickets.create'>>;
77
91
  }
package/dist/v1/index.mjs CHANGED
@@ -155,11 +155,12 @@ async function resolveBaseHeaders(resolver) {
155
155
  }
156
156
  async function buildRequestHeaders(options, operation, prepared, executeOptions) {
157
157
  try {
158
- const headers = new Headers(await resolveBaseHeaders(options.headers));
158
+ const [baseHeaders, credential] = await Promise.all([resolveBaseHeaders(options.headers), resolveCredential(options.credential)]);
159
+ const headers = new Headers(baseHeaders);
159
160
  for (const [key, value] of Object.entries(prepared.headers)) if (value !== void 0) headers.set(key, String(value));
160
161
  headers.delete("x-api-key");
161
162
  headers.set("accept", "application/json");
162
- headers.set("authorization", `Bearer ${await resolveCredential(options.credential)}`);
163
+ headers.set("authorization", `Bearer ${credential}`);
163
164
  if (executeOptions.idempotencyKey) headers.set("idempotency-key", executeOptions.idempotencyKey);
164
165
  if (prepared.body !== void 0) headers.set("content-type", "application/json");
165
166
  return headers;
@@ -362,11 +363,38 @@ function createGscdumpV1Client(options) {
362
363
  return {
363
364
  execute,
364
365
  getUserLifecycle: (input, executeOptions) => execute("partner.users.lifecycle.get", input, executeOptions),
366
+ listAvailableSites: (input, executeOptions) => execute("partner.users.sites.available.list", input, executeOptions),
367
+ createSite: (input, executeOptions) => execute("partner.users.sites.create", input, executeOptions),
368
+ createUser: (input, executeOptions) => execute("partner.users.create", input, executeOptions),
369
+ updateUserTokens: (input, executeOptions) => execute("partner.users.tokens.update", input, executeOptions),
370
+ getSiteIndexing: (input, executeOptions) => execute("partner.sites.indexing.get", input, executeOptions),
371
+ listSiteIndexingUrls: (input, executeOptions) => execute("partner.sites.indexing.urls.list", input, executeOptions),
372
+ getSiteIndexingDiagnostics: (input, executeOptions) => execute("partner.sites.indexing.diagnostics.get", input, executeOptions),
373
+ getSiteSitemaps: (input, executeOptions) => execute("partner.sites.sitemaps.get", input, executeOptions),
374
+ getSiteSitemapChanges: (input, executeOptions) => execute("partner.sites.sitemaps.changes.get", input, executeOptions),
375
+ getSiteAnalysis: (input, executeOptions) => execute("partner.sites.analysis.get", input, executeOptions),
376
+ getSiteAnalysisBundle: (input, executeOptions) => execute("partner.sites.analysis.bundle.get", input, executeOptions),
377
+ deleteSite: (input, executeOptions) => execute("partner.sites.delete", input, executeOptions),
365
378
  queryAnalyticsRows: (input, executeOptions) => execute("analytics.rows.query", input, executeOptions),
379
+ queryAnalyticsReport: (input, executeOptions) => execute("analytics.reports.query", input, executeOptions),
380
+ queryAnalyticsReportDetail: (input, executeOptions) => execute("analytics.reports.detail.query", input, executeOptions),
366
381
  getRealtimeStreamHead: (input = {}, executeOptions) => execute("realtime.stream.head.get", input, executeOptions),
367
382
  createRealtimeTicket: (input, executeOptions) => execute("realtime.tickets.create", input, executeOptions)
368
383
  };
369
384
  }
385
+ function utf8Size(value) {
386
+ let bytes = 0;
387
+ for (let index = 0; index < value.length; index++) {
388
+ const code = value.charCodeAt(index);
389
+ if (code <= 127) bytes++;
390
+ else if (code <= 2047) bytes += 2;
391
+ else if (code >= 55296 && code <= 56319 && index + 1 < value.length && value.charCodeAt(index + 1) >= 56320 && value.charCodeAt(index + 1) <= 57343) {
392
+ bytes += 4;
393
+ index++;
394
+ } else bytes += 3;
395
+ }
396
+ return bytes;
397
+ }
370
398
  const GSCDUMP_REALTIME_V1_SDK_VERSION = "0.37.7";
371
399
  var GscdumpRealtimeV1Error = class extends Error {
372
400
  tag = "GscdumpRealtimeV1Error";
@@ -417,13 +445,14 @@ function defaultRuntime() {
417
445
  now: () => Date.now()
418
446
  };
419
447
  }
420
- function utf8Size(value) {
421
- return new TextEncoder().encode(value).byteLength;
422
- }
448
+ const UTF8_DECODER = new TextDecoder();
449
+ const REALTIME_EVENT_NAMES = new Set(REALTIME_V1_EVENT_NAMES);
450
+ const REALTIME_RESOURCE_TYPES = new Set(REALTIME_V1_RESOURCE_TYPES);
451
+ const APPLIED_EVENT_CACHE_MAX = 1e4;
423
452
  async function messageText(raw) {
424
453
  if (typeof raw === "string") return raw;
425
- if (raw instanceof ArrayBuffer) return new TextDecoder().decode(raw);
426
- if (ArrayBuffer.isView(raw)) return new TextDecoder().decode(new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength));
454
+ if (raw instanceof ArrayBuffer) return UTF8_DECODER.decode(raw);
455
+ if (ArrayBuffer.isView(raw)) return UTF8_DECODER.decode(new Uint8Array(raw.buffer, raw.byteOffset, raw.byteLength));
427
456
  if (typeof Blob !== "undefined" && raw instanceof Blob) return raw.text();
428
457
  throw new TypeError("Realtime frames must be text or UTF-8 binary data.");
429
458
  }
@@ -472,6 +501,7 @@ function createGscdumpRealtimeV1Client(options) {
472
501
  const eventFailures = /* @__PURE__ */ new Map();
473
502
  const appliedEventIds = /* @__PURE__ */ new Set();
474
503
  const appliedEventOrder = [];
504
+ let appliedEventCursor = 0;
475
505
  function getSnapshot() {
476
506
  return {
477
507
  transport,
@@ -605,23 +635,25 @@ function createGscdumpRealtimeV1Client(options) {
605
635
  const key = eventDedupeKey(stream, id);
606
636
  if (appliedEventIds.has(key)) return;
607
637
  appliedEventIds.add(key);
608
- appliedEventOrder.push(key);
609
- if (appliedEventOrder.length > 1e4) {
610
- const oldest = appliedEventOrder.shift();
638
+ if (appliedEventOrder.length < APPLIED_EVENT_CACHE_MAX) appliedEventOrder.push(key);
639
+ else {
640
+ const oldest = appliedEventOrder[appliedEventCursor];
611
641
  if (oldest) appliedEventIds.delete(oldest);
642
+ appliedEventOrder[appliedEventCursor] = key;
643
+ appliedEventCursor = (appliedEventCursor + 1) % APPLIED_EVENT_CACHE_MAX;
612
644
  }
613
645
  }
614
646
  function eventFailureKey(event) {
615
647
  return `${event.cursor?.streamId ?? "ephemeral"}:${event.id}:${event.cursor?.sequence ?? "ephemeral"}`;
616
648
  }
617
649
  function eventForRequiredEffect(event) {
618
- return REALTIME_V1_EVENT_NAMES.includes(event.name) && event.eventVersion === 1 ? event : {
650
+ return REALTIME_EVENT_NAMES.has(event.name) && event.eventVersion === 1 ? event : {
619
651
  ...event,
620
652
  data: null
621
653
  };
622
654
  }
623
655
  function eventAdvisories(event) {
624
- if (!REALTIME_V1_EVENT_NAMES.includes(event.name)) observe({
656
+ if (!REALTIME_EVENT_NAMES.has(event.name)) observe({
625
657
  type: "advisory",
626
658
  code: "unknown_event",
627
659
  event
@@ -631,7 +663,7 @@ function createGscdumpRealtimeV1Client(options) {
631
663
  code: "unsupported_event_version",
632
664
  event
633
665
  });
634
- if (event.changes.some((change) => !REALTIME_V1_RESOURCE_TYPES.includes(change.type))) observe({
666
+ if (event.changes.some((change) => !REALTIME_RESOURCE_TYPES.has(change.type))) observe({
635
667
  type: "advisory",
636
668
  code: "unknown_resource",
637
669
  event
@@ -1058,7 +1090,8 @@ function createGscdumpRealtimeV1Client(options) {
1058
1090
  context.lastPongAt = runtime.now();
1059
1091
  return;
1060
1092
  }
1061
- if (utf8Size(text) > GSCDUMP_REALTIME_LIMITS.outboundFrameMaxBytes) throw new GscdumpRealtimeV1Error({
1093
+ const textBytes = utf8Size(text);
1094
+ if (textBytes > GSCDUMP_REALTIME_LIMITS.outboundFrameMaxBytes) throw new GscdumpRealtimeV1Error({
1062
1095
  code: "protocol_error",
1063
1096
  message: "A server frame exceeded the v1 outbound frame limit.",
1064
1097
  retryable: false,
@@ -1086,8 +1119,7 @@ function createGscdumpRealtimeV1Client(options) {
1086
1119
  cause: parsed.error
1087
1120
  });
1088
1121
  if (parsed.data.type === "event") {
1089
- const eventLimit = parsed.data.delivery === "durable" ? GSCDUMP_REALTIME_LIMITS.durableEventMaxBytes : GSCDUMP_REALTIME_LIMITS.ephemeralEventMaxBytes;
1090
- if (utf8Size(text) > eventLimit) throw new GscdumpRealtimeV1Error({
1122
+ if (textBytes > (parsed.data.delivery === "durable" ? GSCDUMP_REALTIME_LIMITS.durableEventMaxBytes : GSCDUMP_REALTIME_LIMITS.ephemeralEventMaxBytes)) throw new GscdumpRealtimeV1Error({
1091
1123
  code: "protocol_error",
1092
1124
  message: `A ${parsed.data.delivery} event exceeded its v1 size limit.`,
1093
1125
  retryable: false,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gscdump/sdk",
3
3
  "type": "module",
4
- "version": "0.38.2",
4
+ "version": "0.40.1",
5
5
  "description": "Consumer SDK for hosted gscdump.com integrations.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -49,10 +49,10 @@
49
49
  "date-fns": "^4.4.0",
50
50
  "ofetch": "^1.5.1",
51
51
  "zod": "^4.4.3",
52
- "@gscdump/contracts": "0.38.2",
53
- "@gscdump/engine": "0.38.2",
54
- "gscdump": "0.38.2",
55
- "@gscdump/analysis": "0.38.2"
52
+ "@gscdump/analysis": "0.40.1",
53
+ "@gscdump/contracts": "0.40.1",
54
+ "@gscdump/engine": "0.40.1",
55
+ "gscdump": "0.40.1"
56
56
  },
57
57
  "devDependencies": {
58
58
  "typescript": "^6.0.3",
@@ -1,25 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __exportAll = (all, no_symbols) => {
6
- let target = {};
7
- for (var name in all) __defProp(target, name, {
8
- get: all[name],
9
- enumerable: true
10
- });
11
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
12
- return target;
13
- };
14
- var __copyProps = (to, from, except, desc) => {
15
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
16
- key = keys[i];
17
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
18
- get: ((k) => from[k]).bind(null, key),
19
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
- });
21
- }
22
- return to;
23
- };
24
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
25
- export { __exportAll, __reExport };