@gscdump/sdk 1.5.0 → 1.5.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/dist/search-console-stage.mjs +102 -0
- package/dist/v1/realtime.d.mts +1 -1
- package/dist/v1/realtime.mjs +2 -2
- package/package.json +4 -4
|
@@ -133,6 +133,106 @@ const GROWTH_CLICKS_PCT_90D = 10;
|
|
|
133
133
|
const GROWTH_IMPRESSIONS_PCT_90D = 20;
|
|
134
134
|
const DECLINE_CLICKS_PCT = -10;
|
|
135
135
|
const MIN_DECLINE_PRIOR_CLICKS = 50;
|
|
136
|
+
const SEVERE_COVERAGE_PERCENT = 20;
|
|
137
|
+
const SEVERE_COVERAGE_MIN_URLS = 20;
|
|
138
|
+
const SEVERE_NOT_INDEXED_MIN_URLS = 10;
|
|
139
|
+
function severeCoverageReason(counts, totalUrls) {
|
|
140
|
+
if (counts.hardBlocks > Math.max(5, totalUrls * .05) && counts.hardBlocks >= counts.unknown && counts.hardBlocks >= counts.crawled) return "crawl";
|
|
141
|
+
const indexability = Math.max(counts.canonical, counts.noindex);
|
|
142
|
+
if (indexability > Math.max(5, totalUrls * .05) && indexability >= counts.unknown && indexability >= counts.crawled) return "indexability";
|
|
143
|
+
if (counts.generic > 0 && counts.unknown + counts.discovered + counts.crawled + counts.hardBlocks + counts.canonical + counts.noindex === 0) return "unspecified";
|
|
144
|
+
const candidates = [
|
|
145
|
+
{
|
|
146
|
+
reason: "unknown",
|
|
147
|
+
count: counts.unknown,
|
|
148
|
+
severe: counts.unknown >= Math.max(10, totalUrls * .4)
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
reason: "discovered",
|
|
152
|
+
count: counts.discovered,
|
|
153
|
+
severe: counts.discovered >= Math.max(10, totalUrls * .15)
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
reason: "crawled",
|
|
157
|
+
count: counts.crawled,
|
|
158
|
+
severe: counts.crawled >= Math.max(10, totalUrls * .15)
|
|
159
|
+
}
|
|
160
|
+
];
|
|
161
|
+
const severe = candidates.filter((candidate) => candidate.severe);
|
|
162
|
+
const winner = (severe.length > 0 ? severe : candidates).sort((left, right) => right.count - left.count)[0];
|
|
163
|
+
return winner && winner.count > 0 ? winner.reason : "mixed";
|
|
164
|
+
}
|
|
165
|
+
function severeCoverageStage(input, totalUrls, indexed) {
|
|
166
|
+
const notIndexed = Math.max(0, totalUrls - indexed);
|
|
167
|
+
const indexedPercent = totalUrls > 0 ? indexed / totalUrls * 100 : 0;
|
|
168
|
+
if (totalUrls < SEVERE_COVERAGE_MIN_URLS || notIndexed < SEVERE_NOT_INDEXED_MIN_URLS || indexedPercent >= SEVERE_COVERAGE_PERCENT) return null;
|
|
169
|
+
const issues = input.issues ?? [];
|
|
170
|
+
const counts = {
|
|
171
|
+
unknown: countSearchConsoleIssues(issues, "unknown_to_google"),
|
|
172
|
+
discovered: countSearchConsoleIssues(issues, "discovered_not_indexed"),
|
|
173
|
+
crawled: countSearchConsoleIssues(issues, "crawled_not_indexed"),
|
|
174
|
+
hardBlocks: countSearchConsoleIssues(issues, "blocked_robots", "server_error", "access_denied", "access_forbidden", "forbidden", "blocked_4xx", "redirect_error", "crawl_error", "not_found", "soft_404"),
|
|
175
|
+
canonical: countSearchConsoleIssues(issues, "canonical_mismatch", "canonical_cross_domain"),
|
|
176
|
+
noindex: countSearchConsoleIssues(issues, "noindex"),
|
|
177
|
+
generic: countSearchConsoleIssues(issues, "not_indexed")
|
|
178
|
+
};
|
|
179
|
+
if (Object.values(counts).every((count) => count === 0)) return null;
|
|
180
|
+
const reason = severeCoverageReason(counts, totalUrls);
|
|
181
|
+
const key = reason === "crawl" ? "crawl_blocked" : reason === "indexability" ? "indexability_blocked" : reason === "unknown" ? "weak_discovery" : reason === "discovered" ? "discovery_backlog" : "index_rejection";
|
|
182
|
+
const copy = {
|
|
183
|
+
crawl: {
|
|
184
|
+
summary: `Google is reporting hard access or fetch faults on ${formatSearchConsoleCount(counts.hardBlocks)} URLs.`,
|
|
185
|
+
primaryAction: "Fix fetch, server, robots, and broken-response faults before content work."
|
|
186
|
+
},
|
|
187
|
+
indexability: {
|
|
188
|
+
summary: "Google can reach pages, but canonical or indexability signals are preventing clean inclusion.",
|
|
189
|
+
primaryAction: "Make canonical and index directives agree on the URLs that should rank."
|
|
190
|
+
},
|
|
191
|
+
unknown: {
|
|
192
|
+
summary: `Google still does not know about ${formatSearchConsoleCount(counts.unknown)} of the inspected URLs.`,
|
|
193
|
+
primaryAction: "Audit sitemap freshness, sitemap membership, and internal links from already-indexed pages."
|
|
194
|
+
},
|
|
195
|
+
discovered: {
|
|
196
|
+
summary: `Google has discovered ${formatSearchConsoleCount(counts.discovered)} URLs but has not crawled them yet.`,
|
|
197
|
+
primaryAction: "Reduce low-value inventory and strengthen internal links to the pages that should be crawled."
|
|
198
|
+
},
|
|
199
|
+
crawled: {
|
|
200
|
+
summary: `Google crawled ${formatSearchConsoleCount(counts.crawled)} URLs but chose not to keep them in the index.`,
|
|
201
|
+
primaryAction: "Rule out blockers, then improve, consolidate, or noindex thin and duplicate page sets."
|
|
202
|
+
},
|
|
203
|
+
unspecified: {
|
|
204
|
+
summary: `Google reports ${formatSearchConsoleCount(counts.generic || notIndexed)} URLs as not indexed, but the current diagnostic snapshot does not expose a narrower reason bucket.`,
|
|
205
|
+
primaryAction: "Refresh URL Inspection diagnostics and join affected URLs to sitemap, internal-link, canonical, fetch, and rendered-content evidence."
|
|
206
|
+
},
|
|
207
|
+
mixed: {
|
|
208
|
+
summary: `${formatSearchConsoleCount(notIndexed)} URLs are not indexed, with multiple Google coverage reasons present.`,
|
|
209
|
+
primaryAction: "Split the affected URLs by Google coverage reason before changing the site."
|
|
210
|
+
}
|
|
211
|
+
}[reason];
|
|
212
|
+
return {
|
|
213
|
+
...stage(key, [
|
|
214
|
+
{
|
|
215
|
+
label: "Indexed pages",
|
|
216
|
+
value: `${formatSearchConsoleCount(indexed)} of ${formatSearchConsoleCount(totalUrls)}`,
|
|
217
|
+
source: "indexing"
|
|
218
|
+
},
|
|
219
|
+
...counts.unknown > 0 ? [{
|
|
220
|
+
label: "Unknown URLs",
|
|
221
|
+
value: formatSearchConsoleCount(counts.unknown),
|
|
222
|
+
source: "indexing"
|
|
223
|
+
}] : [],
|
|
224
|
+
...counts.crawled > 0 ? [{
|
|
225
|
+
label: "Crawled, not indexed",
|
|
226
|
+
value: formatSearchConsoleCount(counts.crawled),
|
|
227
|
+
source: "indexing"
|
|
228
|
+
}] : []
|
|
229
|
+
]),
|
|
230
|
+
severity: reason === "crawl" || reason === "indexability" ? "error" : "warning",
|
|
231
|
+
summary: copy.summary,
|
|
232
|
+
primaryAction: copy.primaryAction,
|
|
233
|
+
sprintFindingTypes: ["search-console-stage", "pages-not-indexed"]
|
|
234
|
+
};
|
|
235
|
+
}
|
|
136
236
|
function classifySearchConsoleStage(input) {
|
|
137
237
|
const issues = input.issues ?? [];
|
|
138
238
|
const summary = input.summary ?? null;
|
|
@@ -185,6 +285,8 @@ function classifySearchConsoleStage(input) {
|
|
|
185
285
|
value: `${formatSearchConsoleCount(indexed)} of ${formatSearchConsoleCount(totalUrls)}`,
|
|
186
286
|
source: "indexing"
|
|
187
287
|
}]);
|
|
288
|
+
const severeCoverage = isNascent ? null : severeCoverageStage(input, totalUrls, indexed);
|
|
289
|
+
if (severeCoverage) return severeCoverage;
|
|
188
290
|
if (isDeclining) return stage("declining_visibility", [{
|
|
189
291
|
label: "Clicks 90d",
|
|
190
292
|
value: `${clicks90d.toFixed(1)}%`,
|
package/dist/v1/realtime.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RealtimeV1Cursor, RealtimeV1Event, RealtimeV1StreamHead, RealtimeV1StreamId } from "@gscdump/contracts/v1/realtime";
|
|
2
2
|
type MaybePromise<T> = T | Promise<T>;
|
|
3
|
-
declare const GSCDUMP_REALTIME_V1_SDK_VERSION: "1.5.
|
|
3
|
+
declare const GSCDUMP_REALTIME_V1_SDK_VERSION: "1.5.1";
|
|
4
4
|
type GscdumpRealtimeV1TransportState = 'idle' | 'ticketing' | 'connecting' | 'handshaking' | 'replaying' | 'live' | 'waiting' | 'stopped' | 'terminal';
|
|
5
5
|
type GscdumpRealtimeV1Freshness = 'unknown' | 'stale' | 'applying' | 'fresh' | 'resyncing' | 'degraded';
|
|
6
6
|
type GscdumpRealtimeV1ErrorCode = 'cursor_store_failed' | 'effect_failed' | 'heartbeat_stale' | 'integration_failed' | 'protocol_error' | 'resync_failed' | 'runtime_unavailable' | 'socket_error' | 'ticket_invalid' | 'ticket_provider_failed' | 'upgrade_rejected';
|
package/dist/v1/realtime.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { utf8Size } from "../utf8.mjs";
|
|
2
2
|
import { GSCDUMP_REALTIME_ACK_POLICY, GSCDUMP_REALTIME_CLOSE_CODES, GSCDUMP_REALTIME_CONNECTION_POLICY, GSCDUMP_REALTIME_LIMITS, GSCDUMP_REALTIME_PING, GSCDUMP_REALTIME_PONG, GSCDUMP_REALTIME_PROTOCOL_VERSION, GSCDUMP_REALTIME_SUBPROTOCOL, REALTIME_V1_EVENT_NAMES, REALTIME_V1_RESOURCE_TYPES, createRealtimeV1Schemas } from "@gscdump/contracts/v1/realtime";
|
|
3
|
-
const GSCDUMP_REALTIME_V1_SDK_VERSION = "1.5.
|
|
3
|
+
const GSCDUMP_REALTIME_V1_SDK_VERSION = "1.5.1";
|
|
4
4
|
var GscdumpRealtimeV1Error = class extends Error {
|
|
5
5
|
tag = "GscdumpRealtimeV1Error";
|
|
6
6
|
code;
|
|
@@ -87,7 +87,7 @@ function createGscdumpRealtimeV1Client(options) {
|
|
|
87
87
|
const schemas = createRealtimeV1Schemas();
|
|
88
88
|
const runtime = options.runtime ?? defaultRuntime();
|
|
89
89
|
const cursorStore = options.cursorStore ?? createMemoryCursorStore();
|
|
90
|
-
const sdkVersion = options.sdkVersion ?? "1.5.
|
|
90
|
+
const sdkVersion = options.sdkVersion ?? "1.5.1";
|
|
91
91
|
if (!sdkVersion) throw new TypeError("sdkVersion cannot be empty.");
|
|
92
92
|
let running = false;
|
|
93
93
|
let epoch = 0;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.1",
|
|
5
5
|
"description": "Consumer SDK for hosted gscdump.com integrations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -146,9 +146,9 @@
|
|
|
146
146
|
"dependencies": {
|
|
147
147
|
"ofetch": "^1.5.1",
|
|
148
148
|
"zod": "^4.4.3",
|
|
149
|
-
"@gscdump/contracts": "^1.5.
|
|
150
|
-
"@gscdump/engine": "^1.5.
|
|
151
|
-
"gscdump": "^1.5.
|
|
149
|
+
"@gscdump/contracts": "^1.5.1",
|
|
150
|
+
"@gscdump/engine": "^1.5.1",
|
|
151
|
+
"gscdump": "^1.5.1"
|
|
152
152
|
},
|
|
153
153
|
"devDependencies": {
|
|
154
154
|
"typescript": "^7.0.2",
|