@gscdump/sdk 7.12.1 → 7.13.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/README.md +13 -0
- package/dist/indexing/cohorts.d.mts +201 -0
- package/dist/indexing/cohorts.mjs +343 -0
- package/dist/indexing/overview.d.mts +158 -0
- package/dist/indexing/overview.mjs +310 -0
- package/dist/indexing/portfolio-markdown.d.mts +60 -0
- package/dist/indexing/portfolio-markdown.mjs +127 -0
- package/dist/indexing/portfolio.d.mts +99 -0
- package/dist/indexing/portfolio.mjs +206 -0
- package/dist/indexing/readings.d.mts +42 -0
- package/dist/indexing/readings.mjs +47 -0
- package/dist/indexing/regression-lead.d.mts +22 -0
- package/dist/indexing/regression-lead.mjs +48 -0
- package/dist/indexing/site-issues.d.mts +15 -0
- package/dist/indexing/site-issues.mjs +85 -0
- package/dist/indexing/trust-gate.d.mts +63 -0
- package/dist/indexing/trust-gate.mjs +74 -0
- package/dist/indexing/window.d.mts +40 -0
- package/dist/indexing/window.mjs +45 -0
- package/dist/indexing.d.mts +10 -0
- package/dist/indexing.mjs +10 -0
- package/dist/package.mjs +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { SITEMAP_TRUST_COLLAPSE_POLICY, classifySitemapCollapse, compareCurrentSitemapScope, sitemapHistoryHasCollapse } from "@gscdump/analysis/sitemap-health";
|
|
2
|
+
const TRUST_DEGRADED_STATES = /* @__PURE__ */ new Set([
|
|
3
|
+
"unknown",
|
|
4
|
+
"blip",
|
|
5
|
+
"broken",
|
|
6
|
+
"no_sitemap"
|
|
7
|
+
]);
|
|
8
|
+
function isTrustDegraded(state) {
|
|
9
|
+
return TRUST_DEGRADED_STATES.has(state);
|
|
10
|
+
}
|
|
11
|
+
const STALE_DOWNLOAD_DAYS = 7;
|
|
12
|
+
function newestFirstCounts(history) {
|
|
13
|
+
return history.toSorted((a, b) => b.date.localeCompare(a.date)).map((point) => point.urlCount);
|
|
14
|
+
}
|
|
15
|
+
function sitemapHistoryCollapsed(history) {
|
|
16
|
+
return sitemapHistoryHasCollapse(newestFirstCounts(history), SITEMAP_TRUST_COLLAPSE_POLICY);
|
|
17
|
+
}
|
|
18
|
+
function compareCurrentSitemapScope$1(history) {
|
|
19
|
+
return compareCurrentSitemapScope(newestFirstCounts(history), SITEMAP_TRUST_COLLAPSE_POLICY);
|
|
20
|
+
}
|
|
21
|
+
function classifyCurrentSitemapDrop(history) {
|
|
22
|
+
return classifySitemapCollapse(newestFirstCounts(history), SITEMAP_TRUST_COLLAPSE_POLICY);
|
|
23
|
+
}
|
|
24
|
+
function daysSince(iso, now) {
|
|
25
|
+
return (now.getTime() - new Date(iso).getTime()) / 864e5;
|
|
26
|
+
}
|
|
27
|
+
function computeTrustGate(input) {
|
|
28
|
+
if (!input.connected) return {
|
|
29
|
+
state: "not_connected",
|
|
30
|
+
reason: "Search Console is not connected."
|
|
31
|
+
};
|
|
32
|
+
const live = input.liveness;
|
|
33
|
+
if (input.noSitemapsSubmitted) return {
|
|
34
|
+
state: "no_sitemap",
|
|
35
|
+
reason: live?.status === "reachable" ? "Sitemap is reachable but not submitted in Search Console." : "No sitemap is submitted in Search Console."
|
|
36
|
+
};
|
|
37
|
+
if (live?.statusCode === 404) return {
|
|
38
|
+
state: "no_sitemap",
|
|
39
|
+
reason: "No sitemap found at /sitemap.xml."
|
|
40
|
+
};
|
|
41
|
+
const inspected = input.inspectedCount ?? input.totalUrls ?? 0;
|
|
42
|
+
if (input.sitemapsPending && inspected <= 0) return {
|
|
43
|
+
state: "pending",
|
|
44
|
+
reason: "Sitemap is submitted and waiting for Google to parse it."
|
|
45
|
+
};
|
|
46
|
+
if (inspected <= 0) return {
|
|
47
|
+
state: "pending",
|
|
48
|
+
reason: "Google has not inspected any URLs yet."
|
|
49
|
+
};
|
|
50
|
+
if (input.indexingStatus && input.indexingStatus !== "complete" && input.indexingStatus !== "partial") return {
|
|
51
|
+
state: "pending",
|
|
52
|
+
reason: "Search Console data is still syncing."
|
|
53
|
+
};
|
|
54
|
+
const corroborated = input.lastDownloadedAt != null && daysSince(input.lastDownloadedAt, input.now) >= 7 || input.sitemapCollapsed;
|
|
55
|
+
if (live && (live.status === "timeout" || live.status === "error")) {
|
|
56
|
+
if (corroborated) return {
|
|
57
|
+
state: "broken",
|
|
58
|
+
reason: live.status === "timeout" ? "Sitemap is timing out, so indexing cannot be confirmed." : "Sitemap is unreachable, so indexing cannot be confirmed."
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
state: "blip",
|
|
62
|
+
reason: "Could not reach the sitemap just now, retrying."
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (!live && corroborated) return {
|
|
66
|
+
state: "unknown",
|
|
67
|
+
reason: "Indexing cannot be confirmed right now."
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
state: "ok",
|
|
71
|
+
reason: "Google is indexing the pages it discovers."
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export { STALE_DOWNLOAD_DAYS, TRUST_DEGRADED_STATES, classifyCurrentSitemapDrop, compareCurrentSitemapScope$1 as compareCurrentSitemapScope, computeTrustGate, isTrustDegraded, sitemapHistoryCollapsed };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Period } from "../period.mjs";
|
|
2
|
+
import { IndexingTrendReading } from "./readings.mjs";
|
|
3
|
+
/** The hosted v1 Site indexing read accepts at most 90 days. */
|
|
4
|
+
export declare const INDEXING_MAX_READ_DAYS = 90;
|
|
5
|
+
/** The UTC days a portfolio indexing view shows, both ends inclusive. */
|
|
6
|
+
export interface IndexingWindow {
|
|
7
|
+
/** `YYYY-MM-DD`. */
|
|
8
|
+
start: string;
|
|
9
|
+
/** `YYYY-MM-DD`. */
|
|
10
|
+
end: string;
|
|
11
|
+
/**
|
|
12
|
+
* True when the window ends at the latest reporting day. Its Sites show their
|
|
13
|
+
* summary. A past window shows each Site's trend reading at its end.
|
|
14
|
+
*/
|
|
15
|
+
current: boolean;
|
|
16
|
+
/** The day count the indexing read sends, back from today. */
|
|
17
|
+
readDays: number;
|
|
18
|
+
/** The first day the read reaches. After `start` when the read cap cuts the window. */
|
|
19
|
+
readFrom: string;
|
|
20
|
+
}
|
|
21
|
+
/** The window days, `YYYY-MM-DD`, both ends inclusive. */
|
|
22
|
+
export type IndexingWindowDays = Pick<IndexingWindow, 'start' | 'end'>;
|
|
23
|
+
/** The window days, and whether the window ends at the latest reporting day. */
|
|
24
|
+
export type IndexingReadingWindow = Pick<IndexingWindow, 'start' | 'end' | 'current'>;
|
|
25
|
+
/**
|
|
26
|
+
* The Indexing window for a Period.
|
|
27
|
+
*
|
|
28
|
+
* Indexing readings have no reporting latency, so a Period that reaches the
|
|
29
|
+
* latest reporting day keeps its length and ends today. A past range keeps its
|
|
30
|
+
* own days. The indexing read takes a day count back from today only, at most
|
|
31
|
+
* 90. A current window asks for its own length. A past window reads back to its
|
|
32
|
+
* start, and to 28 days before its end, so the reading at the end has its
|
|
33
|
+
* changes. The cap can stop either short, because a longer request fails the
|
|
34
|
+
* whole read.
|
|
35
|
+
*/
|
|
36
|
+
export declare function indexingWindow(period: Period | string, stableData: boolean, now: Date): IndexingWindow;
|
|
37
|
+
/** The days in the window that any series reports, oldest first. */
|
|
38
|
+
export declare function readingDatesInWindow(series: readonly (readonly Pick<IndexingTrendReading, 'date'>[])[], window: IndexingWindowDays): string[];
|
|
39
|
+
/** Says where the read stops when the read cap cuts the window start. Null when it reaches it. */
|
|
40
|
+
export declare function indexingWindowNote(window: Pick<IndexingWindow, 'start' | 'end' | 'readFrom'>, series: readonly (readonly Pick<IndexingTrendReading, 'date'>[])[]): string | null;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { periodToDateRange } from "../period.mjs";
|
|
2
|
+
const INDEXING_MAX_READ_DAYS = 90;
|
|
3
|
+
const INDEXING_CHANGE_DAYS = 28;
|
|
4
|
+
const DAY_MS = 864e5;
|
|
5
|
+
function isoDay(ms) {
|
|
6
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
7
|
+
}
|
|
8
|
+
function indexingWindow(period, stableData, now) {
|
|
9
|
+
const range = periodToDateRange(period, {
|
|
10
|
+
stableData,
|
|
11
|
+
now
|
|
12
|
+
});
|
|
13
|
+
const latest = periodToDateRange("7d", {
|
|
14
|
+
stableData,
|
|
15
|
+
now
|
|
16
|
+
}).end;
|
|
17
|
+
const todayMs = Date.parse(now.toISOString().slice(0, 10));
|
|
18
|
+
const isCurrent = range.end >= latest;
|
|
19
|
+
const startMs = isCurrent ? todayMs - (range.days - 1) * DAY_MS : Date.parse(range.start);
|
|
20
|
+
const endMs = isCurrent ? todayMs : Date.parse(range.end);
|
|
21
|
+
const firstMs = Math.min(startMs, endMs - INDEXING_CHANGE_DAYS * DAY_MS);
|
|
22
|
+
const readDays = Math.min(90, isCurrent ? range.days : Math.round((todayMs - firstMs) / DAY_MS) + 1);
|
|
23
|
+
return {
|
|
24
|
+
start: isoDay(startMs),
|
|
25
|
+
end: isoDay(endMs),
|
|
26
|
+
current: isCurrent,
|
|
27
|
+
readDays,
|
|
28
|
+
readFrom: isoDay(todayMs - (readDays - 1) * DAY_MS)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function readingDatesInWindow(series, window) {
|
|
32
|
+
return [...new Set(series.flatMap((points) => points.filter((point) => point.date >= window.start && point.date <= window.end).map((point) => point.date)))].sort();
|
|
33
|
+
}
|
|
34
|
+
const noteDateFormat = new Intl.DateTimeFormat("en-US", {
|
|
35
|
+
month: "short",
|
|
36
|
+
day: "numeric",
|
|
37
|
+
year: "numeric",
|
|
38
|
+
timeZone: "UTC"
|
|
39
|
+
});
|
|
40
|
+
function indexingWindowNote(window, series) {
|
|
41
|
+
if (window.readFrom <= window.start) return null;
|
|
42
|
+
const first = readingDatesInWindow(series, window)[0] ?? window.readFrom;
|
|
43
|
+
return `Shows ${noteDateFormat.format(/* @__PURE__ */ new Date(`${first}T00:00:00Z`))} onward. Indexing data goes back 90 days.`;
|
|
44
|
+
}
|
|
45
|
+
export { INDEXING_MAX_READ_DAYS, indexingWindow, indexingWindowNote, readingDatesInWindow };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BuildIndexCohortInput, COHORT_MIN_CELL_SIZE, COHORT_MIN_ENUMERATED_SHARE, IndexCohortBaseline, IndexCohortCell, IndexCohortCoverage, IndexCohortDiagnosis, IndexCohortDimension, IndexCohortFilter, IndexCohortFilterParse, IndexCohortLead, IndexCohortLifecycle, IndexCohortPage, IndexCohortSectionRank, IndexCohortSource, IndexCohortUrlRow, IndexCohortsResponse, SITE_WIDE_NOT_INDEXED_RATE, belongsToIndexCohort, buildIndexCohortDiagnosis, buildIndexCohortsFromIndexingUrls, indexCohortFilterValue, parseIndexCohortFilter, rankIndexCohortSections, sampledIndexStateMessage, selectIndexCohortLead, selectIndexCohortUrls, wilsonInterval } from "./indexing/cohorts.mjs";
|
|
2
|
+
import { CurrentSitemapScope, STALE_DOWNLOAD_DAYS, SitemapCollapseState, SitemapCountPoint, SitemapLivenessCheck, TRUST_DEGRADED_STATES, TrustGate, TrustGateInput, TrustGateState, classifyCurrentSitemapDrop, compareCurrentSitemapScope, computeTrustGate, isTrustDegraded, sitemapHistoryCollapsed } from "./indexing/trust-gate.mjs";
|
|
3
|
+
import { AvailableInspectionStages, IndexingDiagnoseInput, IndexingDiagnosisActionId, IndexingDiagnosisReason, IndexingOverviewAction, IndexingOverviewCount, IndexingOverviewDiagnosis, IndexingOverviewDiagnosisState, IndexingOverviewInput, IndexingOverviewModel, IndexingOverviewPartialScope, IndexingOverviewReason, IndexingOverviewReasonGroup, IndexingOverviewScope, IndexingOverviewTrustFailure, IndexingOverviewVerifyScope, IndexingOverviewWaiting, IndexingReasonGroupId, InspectionStageCounts, InspectionStageRow, InspectionStageSource, InspectionStageStep, InspectionStageSteps, UnavailableInspectionStages, buildIndexingOverviewModel, countInspectionStages, indexingActionForIssue } from "./indexing/overview.mjs";
|
|
4
|
+
import { IndexingSummaryReading, IndexingTrendReading, SiteIndexingReadings, clampIndexedPercent, crawlErrorCount, notIndexedCount, readSiteIndexing } from "./indexing/readings.mjs";
|
|
5
|
+
import { SiteIndexingIssue, SiteIndexingIssuePoint, getSiteIndexingIssues } from "./indexing/site-issues.mjs";
|
|
6
|
+
import { INDEXING_MAX_READ_DAYS, IndexingReadingWindow, IndexingWindow, IndexingWindowDays, indexingWindow, indexingWindowNote, readingDatesInWindow } from "./indexing/window.mjs";
|
|
7
|
+
import { IndexingPortfolioSite, IndexingStack, IndexingStackBucket, IndexingStackOptions, IndexingStackSeries, IndexingWindowReading, PortfolioIndexingTrendPoint, PortfolioIssueRow, PortfolioIssueSiteCount, indexedRateChange, issueStack, notIndexedStack, portfolioIndexingTrend, portfolioIssueCounts, portfolioRateChangeOver, siteIndexingReading, windowReadings } from "./indexing/portfolio.mjs";
|
|
8
|
+
import { IndexingMarkdownBucket, IndexingMarkdownInput, IndexingMarkdownIssues, IndexingMarkdownSite, IndexingMarkdownTrendPoint, bucketIndexingSeries, buildIndexingPortfolioMarkdown, indexingMarkdownBucketDays } from "./indexing/portfolio-markdown.mjs";
|
|
9
|
+
import { IndexingRegressionLead, IndexingTransitionRow, selectIndexingRegressionLead } from "./indexing/regression-lead.mjs";
|
|
10
|
+
export { AvailableInspectionStages, BuildIndexCohortInput, COHORT_MIN_CELL_SIZE, COHORT_MIN_ENUMERATED_SHARE, type CurrentSitemapScope, INDEXING_MAX_READ_DAYS, IndexCohortBaseline, IndexCohortCell, IndexCohortCoverage, IndexCohortDiagnosis, IndexCohortDimension, IndexCohortFilter, IndexCohortFilterParse, IndexCohortLead, IndexCohortLifecycle, IndexCohortPage, IndexCohortSectionRank, IndexCohortSource, IndexCohortUrlRow, IndexCohortsResponse, IndexingDiagnoseInput, IndexingDiagnosisActionId, IndexingDiagnosisReason, IndexingMarkdownBucket, IndexingMarkdownInput, IndexingMarkdownIssues, IndexingMarkdownSite, IndexingMarkdownTrendPoint, IndexingOverviewAction, IndexingOverviewCount, IndexingOverviewDiagnosis, IndexingOverviewDiagnosisState, IndexingOverviewInput, IndexingOverviewModel, IndexingOverviewPartialScope, IndexingOverviewReason, IndexingOverviewReasonGroup, IndexingOverviewScope, IndexingOverviewTrustFailure, IndexingOverviewVerifyScope, IndexingOverviewWaiting, IndexingPortfolioSite, IndexingReadingWindow, IndexingReasonGroupId, IndexingRegressionLead, IndexingStack, IndexingStackBucket, IndexingStackOptions, IndexingStackSeries, IndexingSummaryReading, IndexingTransitionRow, IndexingTrendReading, IndexingWindow, IndexingWindowDays, IndexingWindowReading, InspectionStageCounts, InspectionStageRow, InspectionStageSource, InspectionStageStep, InspectionStageSteps, PortfolioIndexingTrendPoint, PortfolioIssueRow, PortfolioIssueSiteCount, SITE_WIDE_NOT_INDEXED_RATE, STALE_DOWNLOAD_DAYS, SiteIndexingIssue, SiteIndexingIssuePoint, SiteIndexingReadings, type SitemapCollapseState, SitemapCountPoint, SitemapLivenessCheck, TRUST_DEGRADED_STATES, TrustGate, TrustGateInput, TrustGateState, UnavailableInspectionStages, belongsToIndexCohort, bucketIndexingSeries, buildIndexCohortDiagnosis, buildIndexCohortsFromIndexingUrls, buildIndexingOverviewModel, buildIndexingPortfolioMarkdown, clampIndexedPercent, classifyCurrentSitemapDrop, compareCurrentSitemapScope, computeTrustGate, countInspectionStages, crawlErrorCount, getSiteIndexingIssues, indexCohortFilterValue, indexedRateChange, indexingActionForIssue, indexingMarkdownBucketDays, indexingWindow, indexingWindowNote, isTrustDegraded, issueStack, notIndexedCount, notIndexedStack, parseIndexCohortFilter, portfolioIndexingTrend, portfolioIssueCounts, portfolioRateChangeOver, rankIndexCohortSections, readSiteIndexing, readingDatesInWindow, sampledIndexStateMessage, selectIndexCohortLead, selectIndexCohortUrls, selectIndexingRegressionLead, siteIndexingReading, sitemapHistoryCollapsed, wilsonInterval, windowReadings };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { COHORT_MIN_CELL_SIZE, COHORT_MIN_ENUMERATED_SHARE, SITE_WIDE_NOT_INDEXED_RATE, belongsToIndexCohort, buildIndexCohortDiagnosis, buildIndexCohortsFromIndexingUrls, indexCohortFilterValue, parseIndexCohortFilter, rankIndexCohortSections, sampledIndexStateMessage, selectIndexCohortLead, selectIndexCohortUrls, wilsonInterval } from "./indexing/cohorts.mjs";
|
|
2
|
+
import { STALE_DOWNLOAD_DAYS, TRUST_DEGRADED_STATES, classifyCurrentSitemapDrop, compareCurrentSitemapScope, computeTrustGate, isTrustDegraded, sitemapHistoryCollapsed } from "./indexing/trust-gate.mjs";
|
|
3
|
+
import { buildIndexingOverviewModel, countInspectionStages, indexingActionForIssue } from "./indexing/overview.mjs";
|
|
4
|
+
import { clampIndexedPercent, crawlErrorCount, notIndexedCount, readSiteIndexing } from "./indexing/readings.mjs";
|
|
5
|
+
import { getSiteIndexingIssues } from "./indexing/site-issues.mjs";
|
|
6
|
+
import { INDEXING_MAX_READ_DAYS, indexingWindow, indexingWindowNote, readingDatesInWindow } from "./indexing/window.mjs";
|
|
7
|
+
import { indexedRateChange, issueStack, notIndexedStack, portfolioIndexingTrend, portfolioIssueCounts, portfolioRateChangeOver, siteIndexingReading, windowReadings } from "./indexing/portfolio.mjs";
|
|
8
|
+
import { bucketIndexingSeries, buildIndexingPortfolioMarkdown, indexingMarkdownBucketDays } from "./indexing/portfolio-markdown.mjs";
|
|
9
|
+
import { selectIndexingRegressionLead } from "./indexing/regression-lead.mjs";
|
|
10
|
+
export { COHORT_MIN_CELL_SIZE, COHORT_MIN_ENUMERATED_SHARE, INDEXING_MAX_READ_DAYS, SITE_WIDE_NOT_INDEXED_RATE, STALE_DOWNLOAD_DAYS, TRUST_DEGRADED_STATES, belongsToIndexCohort, bucketIndexingSeries, buildIndexCohortDiagnosis, buildIndexCohortsFromIndexingUrls, buildIndexingOverviewModel, buildIndexingPortfolioMarkdown, clampIndexedPercent, classifyCurrentSitemapDrop, compareCurrentSitemapScope, computeTrustGate, countInspectionStages, crawlErrorCount, getSiteIndexingIssues, indexCohortFilterValue, indexedRateChange, indexingActionForIssue, indexingMarkdownBucketDays, indexingWindow, indexingWindowNote, isTrustDegraded, issueStack, notIndexedCount, notIndexedStack, parseIndexCohortFilter, portfolioIndexingTrend, portfolioIssueCounts, portfolioRateChangeOver, rankIndexCohortSections, readSiteIndexing, readingDatesInWindow, sampledIndexStateMessage, selectIndexCohortLead, selectIndexCohortUrls, selectIndexingRegressionLead, siteIndexingReading, sitemapHistoryCollapsed, wilsonInterval, windowReadings };
|
package/dist/package.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var version = "7.
|
|
1
|
+
var version = "7.13.0";
|
|
2
2
|
export { version };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.
|
|
4
|
+
"version": "7.13.0",
|
|
5
5
|
"description": "Consumer SDK for hosted gscdump.com integrations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -86,6 +86,11 @@
|
|
|
86
86
|
"import": "./dist/hosted-query.mjs",
|
|
87
87
|
"default": "./dist/hosted-query.mjs"
|
|
88
88
|
},
|
|
89
|
+
"./indexing": {
|
|
90
|
+
"types": "./dist/indexing.d.mts",
|
|
91
|
+
"import": "./dist/indexing.mjs",
|
|
92
|
+
"default": "./dist/indexing.mjs"
|
|
93
|
+
},
|
|
89
94
|
"./indexing-issues": {
|
|
90
95
|
"types": "./dist/indexing-issues.d.mts",
|
|
91
96
|
"import": "./dist/indexing-issues.mjs",
|
|
@@ -144,8 +149,9 @@
|
|
|
144
149
|
"node": ">=22.13.0"
|
|
145
150
|
},
|
|
146
151
|
"dependencies": {
|
|
147
|
-
"@gscdump/
|
|
148
|
-
"gscdump": "^7.
|
|
152
|
+
"@gscdump/analysis": "^7.13.0",
|
|
153
|
+
"@gscdump/contracts": "^7.13.0",
|
|
154
|
+
"gscdump": "^7.13.0",
|
|
149
155
|
"ofetch": "^1.5.1",
|
|
150
156
|
"zod": "^4.6.5"
|
|
151
157
|
},
|