@gscdump/sdk 0.25.13 → 0.26.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/index.d.mts +41 -2
- package/dist/index.mjs +113 -62
- package/package.json +6 -13
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { query_d_exports } from "./_chunks/query.mjs";
|
|
2
2
|
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, 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 { Result } from "gscdump/result";
|
|
3
4
|
import { BuilderState as BuilderState$1, Dimension, Metric, SearchType } from "gscdump/query";
|
|
4
5
|
import { ActionSource } from "@gscdump/analysis";
|
|
5
6
|
import { AnalysisTool } from "@gscdump/engine/analysis-types";
|
|
@@ -225,6 +226,15 @@ interface TopNBreakdownQuery extends ArchetypeQueryBase {
|
|
|
225
226
|
limit: number;
|
|
226
227
|
/** Pagination offset. Non-zero may force `duckdb` execution. */
|
|
227
228
|
offset?: number;
|
|
229
|
+
/**
|
|
230
|
+
* Request the full unwindowed group count (`meta.totalRows`) so paginated /
|
|
231
|
+
* load-more tables know how many rows exist beyond the current `limit`.
|
|
232
|
+
* Computed as `COUNT(*) OVER()` over the grouped result, which requires a
|
|
233
|
+
* window function — so a query with `includeTotal` is escalated to `duckdb`
|
|
234
|
+
* on the server tail (R2 SQL cannot express it). Not honoured for the
|
|
235
|
+
* `device` dimension, which has at most a handful of rows.
|
|
236
|
+
*/
|
|
237
|
+
includeTotal?: boolean;
|
|
228
238
|
}
|
|
229
239
|
/** One aggregated row for a fully-specified filter. `WHERE` + `GROUP BY`. */
|
|
230
240
|
interface SingleRowLookupQuery extends ArchetypeQueryBase {
|
|
@@ -299,7 +309,13 @@ interface ArchetypeResult<R extends ArchetypeResultRow = ArchetypeResultRow> {
|
|
|
299
309
|
source: ArchetypeResultSource;
|
|
300
310
|
meta?: {
|
|
301
311
|
rowCount: number;
|
|
302
|
-
queryMs: number;
|
|
312
|
+
queryMs: number;
|
|
313
|
+
/**
|
|
314
|
+
* Full unwindowed group count for a `top-n-breakdown` requested with
|
|
315
|
+
* `includeTotal`. Independent of `limit`/`offset`; lets paginated tables
|
|
316
|
+
* show "X of Y" and stop loading. Undefined when not requested.
|
|
317
|
+
*/
|
|
318
|
+
totalRows?: number; /** Set when `compareRange` was supplied — the comparison-period rows. */
|
|
303
319
|
compareRows?: R[];
|
|
304
320
|
truncated?: boolean;
|
|
305
321
|
};
|
|
@@ -353,6 +369,17 @@ declare class PartnerApiError extends Error {
|
|
|
353
369
|
constructor(info: PartnerErrorInfo);
|
|
354
370
|
}
|
|
355
371
|
declare function toPartnerError(error: unknown): PartnerApiError;
|
|
372
|
+
/** Narrow an unknown error to the modelled `PartnerApiError`. */
|
|
373
|
+
declare function isPartnerError(error: unknown): error is PartnerApiError;
|
|
374
|
+
/** Human-readable, log-friendly rendering of a modelled partner failure. */
|
|
375
|
+
declare function formatPartnerError(error: PartnerApiError): string;
|
|
376
|
+
/**
|
|
377
|
+
* Re-raise a modelled `PartnerApiError` as itself. The error variant of every
|
|
378
|
+
* `*Result` core already IS the throwable `PartnerApiError`, so the throwing
|
|
379
|
+
* wrappers preserve the exact identity/message existing call sites and tests
|
|
380
|
+
* assert (`rejects.toThrow(PartnerApiError)`, `toThrow('Invalid webhook signature')`).
|
|
381
|
+
*/
|
|
382
|
+
declare function partnerErrorToException(error: PartnerApiError): PartnerApiError;
|
|
356
383
|
interface GscConsoleUrlOpts {
|
|
357
384
|
/** The GSC property — either `sc-domain:example.com` or a URL-prefix. */
|
|
358
385
|
siteLabel: string;
|
|
@@ -872,6 +899,18 @@ declare function classifyReachStage(input: SiteTriageInput): ReachVerdict;
|
|
|
872
899
|
declare function classifySiteTriage(input: SiteTriageInput): SiteTriage;
|
|
873
900
|
declare function serializeWebhookPayload(payload: string | object): string;
|
|
874
901
|
declare function verifyWebhookSignature(payload: string | object, signature: string | null | undefined, secret: string): Promise<boolean>;
|
|
902
|
+
/**
|
|
903
|
+
* Errors-as-values core for {@link parseWebhookPayload}: a failed HMAC signature
|
|
904
|
+
* check is a caller-actionable `auth` (401) failure at the webhook boundary, so
|
|
905
|
+
* it is returned as a modelled `PartnerApiError` rather than only thrown. A
|
|
906
|
+
* malformed envelope (schema parse) is a defect and keeps propagating.
|
|
907
|
+
*/
|
|
908
|
+
declare function parseWebhookPayloadResult<TData extends Record<string, unknown> = Record<string, unknown>>(payload: string | object, options?: {
|
|
909
|
+
secret?: string;
|
|
910
|
+
signature?: string | null;
|
|
911
|
+
headers?: PartnerWebhookHeaders$1 | Headers;
|
|
912
|
+
validateSignature?: boolean;
|
|
913
|
+
}): Promise<Result<WebhookEnvelope$1<TData>, PartnerApiError>>;
|
|
875
914
|
declare function parseWebhookPayload<TData extends Record<string, unknown> = Record<string, unknown>>(payload: string | object, options?: {
|
|
876
915
|
secret?: string;
|
|
877
916
|
signature?: string | null;
|
|
@@ -879,4 +918,4 @@ declare function parseWebhookPayload<TData extends Record<string, unknown> = Rec
|
|
|
879
918
|
validateSignature?: boolean;
|
|
880
919
|
}): Promise<WebhookEnvelope$1<TData>>;
|
|
881
920
|
declare function readWebhookHeaders(headers: Headers | PartnerWebhookHeaders$1 | null | undefined): Required<PartnerWebhookHeaders$1>;
|
|
882
|
-
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 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, getGscUnstableCutoffDate, gscConsoleUrl, investigationStatusConfig, isCustomPeriod, issueDetails, issueGroups, issueTypeToGroup, lifecycleSiteToSyncStatus, lifecycleSiteToUserSite, normalizeSiteType, nuxtSeoTips, parseCustomPeriod, parseWebhookPayload, periodToDateRange, periodToDays, positionFor, reachLivenessRatio, readWebhookHeaders, serializeWebhookPayload, severityOrder, siteTypeBaseline, siteUrlToHostname, splitOpportunityTitle, summarizeDailyRows, toPartnerError, truncateQuery, verifyWebhookSignature, weightedAnonPct };
|
|
921
|
+
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 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 };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { query_exports } from "./query.mjs";
|
|
2
2
|
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, analyticsRoutes, partnerEndpointSchemas, partnerRoutes, partnerWebhookEnvelopeSchema } from "@gscdump/contracts";
|
|
3
|
+
import { err, ok, unwrapResult } from "gscdump/result";
|
|
3
4
|
import { ofetch } from "ofetch";
|
|
4
5
|
import { resolveWindow } from "@gscdump/engine/period";
|
|
5
6
|
import { endOfMonth, format, startOfMonth, startOfQuarter, startOfWeek, subDays, subMonths } from "date-fns";
|
|
@@ -47,6 +48,16 @@ function toPartnerError(error) {
|
|
|
47
48
|
data
|
|
48
49
|
});
|
|
49
50
|
}
|
|
51
|
+
function isPartnerError(error) {
|
|
52
|
+
return error instanceof PartnerApiError;
|
|
53
|
+
}
|
|
54
|
+
function formatPartnerError(error) {
|
|
55
|
+
const status = error.statusCode != null ? ` (${error.statusCode})` : "";
|
|
56
|
+
return `[${error.kind}]${status} ${error.message}`;
|
|
57
|
+
}
|
|
58
|
+
function partnerErrorToException(error) {
|
|
59
|
+
return error;
|
|
60
|
+
}
|
|
50
61
|
const TRAILING_SLASH_RE$2 = /\/+$/;
|
|
51
62
|
const LEADING_SLASH_RE$1 = /^\/+/;
|
|
52
63
|
const DEFAULT_SEARCH_TYPE$1 = "web";
|
|
@@ -120,18 +131,21 @@ function indexingUrlsQuery$1(params = {}) {
|
|
|
120
131
|
function createAnalyticsClient(options = {}) {
|
|
121
132
|
const fetchImpl = options.fetch ?? ofetch;
|
|
122
133
|
const apiBase = trimApiBase$1(options.apiBase);
|
|
123
|
-
async function
|
|
134
|
+
async function requestResult(path, init = {}, responseSchema) {
|
|
124
135
|
const headers = mergeHeaders$1(await resolveHeaders$1(options), init.headers);
|
|
125
136
|
try {
|
|
126
137
|
const out = await fetchImpl(buildPath$1(apiBase, path), {
|
|
127
138
|
...init,
|
|
128
139
|
headers
|
|
129
140
|
});
|
|
130
|
-
return shouldValidate$1(options, "response") ? parseWith$1(responseSchema, out) : out;
|
|
141
|
+
return ok(shouldValidate$1(options, "response") ? parseWith$1(responseSchema, out) : out);
|
|
131
142
|
} catch (error) {
|
|
132
|
-
|
|
143
|
+
return err(toPartnerError(error));
|
|
133
144
|
}
|
|
134
145
|
}
|
|
146
|
+
async function request(path, init = {}, responseSchema) {
|
|
147
|
+
return unwrapResult(await requestResult(path, init, responseSchema), partnerErrorToException);
|
|
148
|
+
}
|
|
135
149
|
return {
|
|
136
150
|
whoami() {
|
|
137
151
|
return request(analyticsRoutes.whoami, {}, partnerEndpointSchemas.analyticsWhoami.response);
|
|
@@ -359,8 +373,16 @@ function dataDetailQuery(state, options) {
|
|
|
359
373
|
if (opts?.comparison) query.qc = JSON.stringify(withDefaultSearchType(opts.comparison, scoped.searchType));
|
|
360
374
|
return query;
|
|
361
375
|
}
|
|
376
|
+
function validateAnalysisParamsResult(params) {
|
|
377
|
+
if ((params.preset === "non-brand" || params.preset === "brand-only") && !params.brandTerms?.trim()) return err(new PartnerApiError({
|
|
378
|
+
kind: "validation",
|
|
379
|
+
statusCode: 400,
|
|
380
|
+
message: "brandTerms is required for brand/non-brand presets"
|
|
381
|
+
}));
|
|
382
|
+
return ok(params);
|
|
383
|
+
}
|
|
362
384
|
function assertAnalysisParams(params) {
|
|
363
|
-
|
|
385
|
+
unwrapResult(validateAnalysisParamsResult(params), partnerErrorToException);
|
|
364
386
|
}
|
|
365
387
|
function analysisQuery(params) {
|
|
366
388
|
const query = {
|
|
@@ -442,18 +464,91 @@ function sleep(ms) {
|
|
|
442
464
|
function createPartnerClient(options = {}) {
|
|
443
465
|
const fetchImpl = options.fetch ?? ofetch;
|
|
444
466
|
const apiBase = trimApiBase(options.apiBase);
|
|
445
|
-
async function
|
|
467
|
+
async function requestResult(path, init = {}, responseSchema) {
|
|
446
468
|
const headers = mergeHeaders(await resolveHeaders(options), init.headers);
|
|
447
469
|
try {
|
|
448
470
|
const out = await fetchImpl(buildPath(apiBase, path), {
|
|
449
471
|
...init,
|
|
450
472
|
headers
|
|
451
473
|
});
|
|
452
|
-
return shouldValidate(options, "response") ? parseWith(responseSchema, out) : out;
|
|
474
|
+
return ok(shouldValidate(options, "response") ? parseWith(responseSchema, out) : out);
|
|
453
475
|
} catch (error) {
|
|
454
|
-
|
|
476
|
+
return err(toPartnerError(error));
|
|
455
477
|
}
|
|
456
478
|
}
|
|
479
|
+
async function request(path, init = {}, responseSchema) {
|
|
480
|
+
return unwrapResult(await requestResult(path, init, responseSchema), partnerErrorToException);
|
|
481
|
+
}
|
|
482
|
+
async function waitForUserReadyResult(userId, waitOptions = {}) {
|
|
483
|
+
const attempts = waitOptions.attempts ?? 12;
|
|
484
|
+
const intervalMs = waitOptions.intervalMs ?? 1e3;
|
|
485
|
+
let latest = null;
|
|
486
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
487
|
+
const result = await requestResult(partnerRoutes.users.status(userId));
|
|
488
|
+
if (!result.ok) return result;
|
|
489
|
+
latest = result.value;
|
|
490
|
+
if (latest.status === "ready") return ok(latest);
|
|
491
|
+
if (attempt < attempts - 1) await sleep(intervalMs);
|
|
492
|
+
}
|
|
493
|
+
return err(new PartnerApiError({
|
|
494
|
+
kind: "provisioning",
|
|
495
|
+
statusCode: 409,
|
|
496
|
+
message: "gscdump user database is still provisioning",
|
|
497
|
+
data: latest
|
|
498
|
+
}));
|
|
499
|
+
}
|
|
500
|
+
function waitForUserReadyToException(error) {
|
|
501
|
+
const e = new Error(error.message);
|
|
502
|
+
e.data = error.data;
|
|
503
|
+
return e;
|
|
504
|
+
}
|
|
505
|
+
async function waitForUserLifecycleReadyResult(userId, waitOptions = {}) {
|
|
506
|
+
const attempts = waitOptions.attempts ?? 12;
|
|
507
|
+
const intervalMs = waitOptions.intervalMs ?? 1e3;
|
|
508
|
+
let latest = null;
|
|
509
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
510
|
+
const result = await requestResult(partnerRoutes.users.lifecycle(userId));
|
|
511
|
+
if (!result.ok) return result;
|
|
512
|
+
latest = result.value;
|
|
513
|
+
const status = latest.account.status;
|
|
514
|
+
if (status === "ready") return ok(latest);
|
|
515
|
+
if (status === "refresh_missing" || status === "scope_missing" || status === "reauth_required") return err(new PartnerApiError({
|
|
516
|
+
kind: "auth",
|
|
517
|
+
statusCode: 401,
|
|
518
|
+
message: "Google Search Console authorization must be refreshed",
|
|
519
|
+
data: latest.account
|
|
520
|
+
}));
|
|
521
|
+
if (status === "disconnected" || status === "oauth_received") return err(new PartnerApiError({
|
|
522
|
+
kind: "provisioning",
|
|
523
|
+
statusCode: 409,
|
|
524
|
+
message: "gscdump user is not fully connected",
|
|
525
|
+
data: latest.account
|
|
526
|
+
}));
|
|
527
|
+
if (attempt < attempts - 1) await sleep(intervalMs);
|
|
528
|
+
}
|
|
529
|
+
return err(new PartnerApiError({
|
|
530
|
+
kind: "provisioning",
|
|
531
|
+
statusCode: 409,
|
|
532
|
+
message: "gscdump user database is still provisioning",
|
|
533
|
+
data: latest
|
|
534
|
+
}));
|
|
535
|
+
}
|
|
536
|
+
async function getSiteSyncStatusResult(siteId, userId) {
|
|
537
|
+
if (!userId) return requestResult(partnerRoutes.sites.syncStatus(siteId));
|
|
538
|
+
const lifecycle = await requestResult(partnerRoutes.users.lifecycle(userId));
|
|
539
|
+
if (!lifecycle.ok) return lifecycle;
|
|
540
|
+
const site = findLifecycleSite(lifecycle.value, siteId);
|
|
541
|
+
if (!site) return err(new PartnerApiError({
|
|
542
|
+
kind: "not-found",
|
|
543
|
+
statusCode: 404,
|
|
544
|
+
message: "gscdump lifecycle site not found",
|
|
545
|
+
data: {
|
|
546
|
+
siteId,
|
|
547
|
+
userId
|
|
548
|
+
}
|
|
549
|
+
}));
|
|
550
|
+
return ok(lifecycleSiteToSyncStatus(site));
|
|
551
|
+
}
|
|
457
552
|
return {
|
|
458
553
|
registerUser(params) {
|
|
459
554
|
const body = shouldValidate(options, "request") ? partnerEndpointSchemas.registerUser.body.parse(params) : params;
|
|
@@ -476,46 +571,10 @@ function createPartnerClient(options = {}) {
|
|
|
476
571
|
return request(partnerRoutes.users.lifecycle(userId));
|
|
477
572
|
},
|
|
478
573
|
async waitForUserReady(userId, waitOptions = {}) {
|
|
479
|
-
|
|
480
|
-
const intervalMs = waitOptions.intervalMs ?? 1e3;
|
|
481
|
-
let latest = null;
|
|
482
|
-
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
483
|
-
latest = await request(partnerRoutes.users.status(userId));
|
|
484
|
-
if (latest.status === "ready") return latest;
|
|
485
|
-
if (attempt < attempts - 1) await sleep(intervalMs);
|
|
486
|
-
}
|
|
487
|
-
const err = /* @__PURE__ */ new Error("gscdump user database is still provisioning");
|
|
488
|
-
err.data = latest;
|
|
489
|
-
throw err;
|
|
574
|
+
return unwrapResult(await waitForUserReadyResult(userId, waitOptions), waitForUserReadyToException);
|
|
490
575
|
},
|
|
491
576
|
async waitForUserLifecycleReady(userId, waitOptions = {}) {
|
|
492
|
-
|
|
493
|
-
const intervalMs = waitOptions.intervalMs ?? 1e3;
|
|
494
|
-
let latest = null;
|
|
495
|
-
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
496
|
-
latest = await request(partnerRoutes.users.lifecycle(userId));
|
|
497
|
-
const status = latest.account.status;
|
|
498
|
-
if (status === "ready") return latest;
|
|
499
|
-
if (status === "refresh_missing" || status === "scope_missing" || status === "reauth_required") throw new PartnerApiError({
|
|
500
|
-
kind: "auth",
|
|
501
|
-
statusCode: 401,
|
|
502
|
-
message: "Google Search Console authorization must be refreshed",
|
|
503
|
-
data: latest.account
|
|
504
|
-
});
|
|
505
|
-
if (status === "disconnected" || status === "oauth_received") throw new PartnerApiError({
|
|
506
|
-
kind: "provisioning",
|
|
507
|
-
statusCode: 409,
|
|
508
|
-
message: "gscdump user is not fully connected",
|
|
509
|
-
data: latest.account
|
|
510
|
-
});
|
|
511
|
-
if (attempt < attempts - 1) await sleep(intervalMs);
|
|
512
|
-
}
|
|
513
|
-
throw new PartnerApiError({
|
|
514
|
-
kind: "provisioning",
|
|
515
|
-
statusCode: 409,
|
|
516
|
-
message: "gscdump user database is still provisioning",
|
|
517
|
-
data: latest
|
|
518
|
-
});
|
|
577
|
+
return unwrapResult(await waitForUserLifecycleReadyResult(userId, waitOptions), partnerErrorToException);
|
|
519
578
|
},
|
|
520
579
|
getUserSites(userId) {
|
|
521
580
|
return request(partnerRoutes.users.sites(userId), {}, partnerEndpointSchemas.getUserSites.response);
|
|
@@ -547,18 +606,7 @@ function createPartnerClient(options = {}) {
|
|
|
547
606
|
return request(partnerRoutes.sites.analysisSources(siteId), { query: tablesQuery(tables, options) }, partnerEndpointSchemas.getAnalysisSources.response);
|
|
548
607
|
},
|
|
549
608
|
async getSiteSyncStatus(siteId, userId) {
|
|
550
|
-
|
|
551
|
-
const site = findLifecycleSite(await request(partnerRoutes.users.lifecycle(userId)), siteId);
|
|
552
|
-
if (!site) throw new PartnerApiError({
|
|
553
|
-
kind: "not-found",
|
|
554
|
-
statusCode: 404,
|
|
555
|
-
message: "gscdump lifecycle site not found",
|
|
556
|
-
data: {
|
|
557
|
-
siteId,
|
|
558
|
-
userId
|
|
559
|
-
}
|
|
560
|
-
});
|
|
561
|
-
return lifecycleSiteToSyncStatus(site);
|
|
609
|
+
return unwrapResult(await getSiteSyncStatusResult(siteId, userId), partnerErrorToException);
|
|
562
610
|
},
|
|
563
611
|
getData(siteId, state, queryOptions) {
|
|
564
612
|
if (shouldValidate(options, "request")) {
|
|
@@ -2197,18 +2245,21 @@ async function verifyWebhookSignature(payload, signature, secret) {
|
|
|
2197
2245
|
if (!received) return false;
|
|
2198
2246
|
return constantTimeEqual(new Uint8Array(await hmacSha256(toPayloadString(payload), secret)), received);
|
|
2199
2247
|
}
|
|
2200
|
-
async function
|
|
2248
|
+
async function parseWebhookPayloadResult(payload, options = {}) {
|
|
2201
2249
|
const payloadString = toPayloadString(payload);
|
|
2202
2250
|
const signature = options.signature ?? readWebhookHeaders(options.headers).signature;
|
|
2203
2251
|
if (options.secret && (options.validateSignature ?? true)) {
|
|
2204
|
-
if (!await verifyWebhookSignature(payloadString, signature, options.secret))
|
|
2252
|
+
if (!await verifyWebhookSignature(payloadString, signature, options.secret)) return err(new PartnerApiError({
|
|
2205
2253
|
kind: "auth",
|
|
2206
2254
|
statusCode: 401,
|
|
2207
2255
|
message: "Invalid webhook signature"
|
|
2208
|
-
});
|
|
2256
|
+
}));
|
|
2209
2257
|
}
|
|
2210
2258
|
const parsed = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
2211
|
-
return partnerWebhookEnvelopeSchema.parse(parsed);
|
|
2259
|
+
return ok(partnerWebhookEnvelopeSchema.parse(parsed));
|
|
2260
|
+
}
|
|
2261
|
+
async function parseWebhookPayload(payload, options = {}) {
|
|
2262
|
+
return unwrapResult(await parseWebhookPayloadResult(payload, options), partnerErrorToException);
|
|
2212
2263
|
}
|
|
2213
2264
|
function readWebhookHeaders(headers) {
|
|
2214
2265
|
if (!headers) return {
|
|
@@ -2233,4 +2284,4 @@ function readWebhookHeaders(headers) {
|
|
|
2233
2284
|
signature: headers.signature ?? null
|
|
2234
2285
|
};
|
|
2235
2286
|
}
|
|
2236
|
-
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, getGscUnstableCutoffDate, gscConsoleUrl, investigationStatusConfig, isCustomPeriod, issueDetails, issueGroups, issueTypeToGroup, lifecycleSiteToSyncStatus, lifecycleSiteToUserSite, normalizeSiteType, nuxtSeoTips, parseCustomPeriod, parseWebhookPayload, periodToDateRange, periodToDays, positionFor, reachLivenessRatio, readWebhookHeaders, serializeWebhookPayload, severityOrder, siteTypeBaseline, siteUrlToHostname, splitOpportunityTitle, summarizeDailyRows, toPartnerError, truncateQuery, verifyWebhookSignature, weightedAnonPct };
|
|
2287
|
+
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 };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.26.0",
|
|
5
5
|
"description": "Consumer SDK for hosted gscdump.com integrations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -40,25 +40,18 @@
|
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18"
|
|
42
42
|
},
|
|
43
|
-
"peerDependencies": {
|
|
44
|
-
"gscdump": "0.25.13"
|
|
45
|
-
},
|
|
46
|
-
"peerDependenciesMeta": {
|
|
47
|
-
"gscdump": {
|
|
48
|
-
"optional": true
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
43
|
"dependencies": {
|
|
52
44
|
"date-fns": "^4.4.0",
|
|
53
45
|
"ofetch": "^1.5.1",
|
|
54
46
|
"zod": "^4.4.3",
|
|
55
|
-
"@gscdump/analysis": "0.
|
|
56
|
-
"@gscdump/contracts": "0.
|
|
57
|
-
"@gscdump/engine": "0.
|
|
47
|
+
"@gscdump/analysis": "0.26.0",
|
|
48
|
+
"@gscdump/contracts": "0.26.0",
|
|
49
|
+
"@gscdump/engine": "0.26.0",
|
|
50
|
+
"gscdump": "0.26.0"
|
|
58
51
|
},
|
|
59
52
|
"devDependencies": {
|
|
60
53
|
"typescript": "^6.0.3",
|
|
61
|
-
"vitest": "^4.1.
|
|
54
|
+
"vitest": "^4.1.8"
|
|
62
55
|
},
|
|
63
56
|
"scripts": {
|
|
64
57
|
"build": "obuild",
|