@gscdump/sdk 0.27.1 → 0.27.2
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 +23 -0
- package/dist/index.mjs +82 -31
- package/package.json +5 -5
package/dist/index.d.mts
CHANGED
|
@@ -403,6 +403,18 @@ interface PartnerWebSocketLike {
|
|
|
403
403
|
interface PartnerWebSocketConstructor {
|
|
404
404
|
new (url: string, protocols?: string | string[]): PartnerWebSocketLike;
|
|
405
405
|
}
|
|
406
|
+
interface PartnerRealtimeReconnectOptions {
|
|
407
|
+
/** Default `true`. Set `false` to disable automatic reconnection entirely. */
|
|
408
|
+
enabled?: boolean;
|
|
409
|
+
/** First-retry delay in ms; doubles each attempt. Default `1000`. */
|
|
410
|
+
baseDelayMs?: number;
|
|
411
|
+
/** Upper bound on the backoff delay in ms. Default `30000`. */
|
|
412
|
+
maxDelayMs?: number;
|
|
413
|
+
/** Stop after this many consecutive failed attempts. Default `Infinity`. */
|
|
414
|
+
maxRetries?: number;
|
|
415
|
+
/** Apply equal-jitter to each delay so many clients don't reconnect in lockstep. Default `true`. */
|
|
416
|
+
jitter?: boolean;
|
|
417
|
+
}
|
|
406
418
|
interface PartnerRealtimeOptions {
|
|
407
419
|
/**
|
|
408
420
|
* HTTP API base used only to derive a same-origin websocket base when `wsBase`
|
|
@@ -421,6 +433,17 @@ interface PartnerRealtimeOptions {
|
|
|
421
433
|
siteIds?: string[];
|
|
422
434
|
protocols?: string | string[];
|
|
423
435
|
WebSocket?: PartnerWebSocketConstructor;
|
|
436
|
+
/**
|
|
437
|
+
* Automatic reconnection on unexpected close (network drop, server restart).
|
|
438
|
+
* A raw WebSocket `error` Event carries no actionable detail, so rather than
|
|
439
|
+
* surfacing it the client transparently reconnects with exponential backoff.
|
|
440
|
+
* `true` (default) uses defaults; pass an object to tune; `false` disables.
|
|
441
|
+
* The backoff counter resets once a reconnection reaches `authenticated`.
|
|
442
|
+
*/
|
|
443
|
+
reconnect?: boolean | PartnerRealtimeReconnectOptions;
|
|
444
|
+
/** Injected timer hooks (for tests). Defaults to global `setTimeout`/`clearTimeout`. */
|
|
445
|
+
setTimeout?: (handler: () => void, ms: number) => unknown;
|
|
446
|
+
clearTimeout?: (handle: unknown) => void;
|
|
424
447
|
}
|
|
425
448
|
interface PartnerRealtimeClient {
|
|
426
449
|
readonly status: PartnerRealtimeStatus;
|
package/dist/index.mjs
CHANGED
|
@@ -1379,6 +1379,16 @@ function getGscUnstableCutoffDate() {
|
|
|
1379
1379
|
const cutoff = new Date(y, m - 1, d - 3);
|
|
1380
1380
|
return `${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, "0")}-${String(cutoff.getDate()).padStart(2, "0")}`;
|
|
1381
1381
|
}
|
|
1382
|
+
function resolveReconnect(reconnect) {
|
|
1383
|
+
const opts = reconnect === false ? { enabled: false } : reconnect === true || reconnect == null ? {} : reconnect;
|
|
1384
|
+
return {
|
|
1385
|
+
enabled: opts.enabled ?? true,
|
|
1386
|
+
baseDelayMs: opts.baseDelayMs ?? 1e3,
|
|
1387
|
+
maxDelayMs: opts.maxDelayMs ?? 3e4,
|
|
1388
|
+
maxRetries: opts.maxRetries ?? Number.POSITIVE_INFINITY,
|
|
1389
|
+
jitter: opts.jitter ?? true
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1382
1392
|
const HTTP_PROTOCOL_RE = /^http/i;
|
|
1383
1393
|
const API_SUFFIX_RE = /\/api\/?$/;
|
|
1384
1394
|
const TRAILING_SLASH_RE = /\/+$/;
|
|
@@ -1415,6 +1425,12 @@ function getWebSocketCtor(options) {
|
|
|
1415
1425
|
function createPartnerRealtimeClient(options) {
|
|
1416
1426
|
let socket = null;
|
|
1417
1427
|
let status = "idle";
|
|
1428
|
+
const reconnect = resolveReconnect(options.reconnect);
|
|
1429
|
+
const setTimer = options.setTimeout ?? ((handler, ms) => setTimeout(handler, ms));
|
|
1430
|
+
const clearTimer = options.clearTimeout ?? ((handle) => clearTimeout(handle));
|
|
1431
|
+
let manualClose = false;
|
|
1432
|
+
let reconnectAttempts = 0;
|
|
1433
|
+
let reconnectTimer = null;
|
|
1418
1434
|
const statusHandlers = /* @__PURE__ */ new Set();
|
|
1419
1435
|
const messageHandlers = /* @__PURE__ */ new Set();
|
|
1420
1436
|
const eventHandlers = /* @__PURE__ */ new Set();
|
|
@@ -1441,6 +1457,68 @@ function createPartnerRealtimeClient(options) {
|
|
|
1441
1457
|
siteIds
|
|
1442
1458
|
});
|
|
1443
1459
|
}
|
|
1460
|
+
function clearReconnectTimer() {
|
|
1461
|
+
if (reconnectTimer != null) {
|
|
1462
|
+
clearTimer(reconnectTimer);
|
|
1463
|
+
reconnectTimer = null;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
function backoffDelay(attempt) {
|
|
1467
|
+
const exp = Math.min(reconnect.maxDelayMs, reconnect.baseDelayMs * 2 ** attempt);
|
|
1468
|
+
if (!reconnect.jitter) return exp;
|
|
1469
|
+
return Math.round(exp / 2 + Math.random() * (exp / 2));
|
|
1470
|
+
}
|
|
1471
|
+
function openSocket() {
|
|
1472
|
+
if (socket) return socket;
|
|
1473
|
+
clearReconnectTimer();
|
|
1474
|
+
manualClose = false;
|
|
1475
|
+
socket = new (getWebSocketCtor(options))(buildWsUrl(options), options.protocols);
|
|
1476
|
+
setStatus("connecting");
|
|
1477
|
+
socket.onopen = () => {
|
|
1478
|
+
setStatus("open");
|
|
1479
|
+
sendJson(authPayload());
|
|
1480
|
+
};
|
|
1481
|
+
socket.onmessage = (event) => {
|
|
1482
|
+
const message = parseMessage(event.data);
|
|
1483
|
+
if (!message) return;
|
|
1484
|
+
if ("event" in message && message.event === "connected") {
|
|
1485
|
+
reconnectAttempts = 0;
|
|
1486
|
+
setStatus("authenticated");
|
|
1487
|
+
if (options.siteIds?.length) subscribe(options.siteIds);
|
|
1488
|
+
}
|
|
1489
|
+
for (const handler of messageHandlers) handler(message);
|
|
1490
|
+
if (isRealtimeEvent(message)) for (const handler of eventHandlers) handler(message);
|
|
1491
|
+
};
|
|
1492
|
+
socket.onerror = (event) => {
|
|
1493
|
+
setStatus("error");
|
|
1494
|
+
for (const handler of errorHandlers) handler(event);
|
|
1495
|
+
};
|
|
1496
|
+
socket.onclose = (event) => {
|
|
1497
|
+
socket = null;
|
|
1498
|
+
setStatus("closed");
|
|
1499
|
+
for (const handler of messageHandlers) handler({
|
|
1500
|
+
type: "error",
|
|
1501
|
+
message: `WebSocket closed: ${JSON.stringify(event)}`
|
|
1502
|
+
});
|
|
1503
|
+
scheduleReconnect();
|
|
1504
|
+
};
|
|
1505
|
+
return socket;
|
|
1506
|
+
}
|
|
1507
|
+
function scheduleReconnect() {
|
|
1508
|
+
if (!reconnect.enabled || manualClose || reconnectTimer != null) return;
|
|
1509
|
+
if (reconnectAttempts >= reconnect.maxRetries) {
|
|
1510
|
+
const err = /* @__PURE__ */ new Error(`Partner realtime reconnect exhausted after ${reconnectAttempts} attempts`);
|
|
1511
|
+
for (const handler of errorHandlers) handler(err);
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
const delay = backoffDelay(reconnectAttempts);
|
|
1515
|
+
reconnectAttempts += 1;
|
|
1516
|
+
setStatus("connecting");
|
|
1517
|
+
reconnectTimer = setTimer(() => {
|
|
1518
|
+
reconnectTimer = null;
|
|
1519
|
+
openSocket();
|
|
1520
|
+
}, delay);
|
|
1521
|
+
}
|
|
1444
1522
|
return {
|
|
1445
1523
|
get status() {
|
|
1446
1524
|
return status;
|
|
@@ -1449,38 +1527,11 @@ function createPartnerRealtimeClient(options) {
|
|
|
1449
1527
|
return socket;
|
|
1450
1528
|
},
|
|
1451
1529
|
connect() {
|
|
1452
|
-
|
|
1453
|
-
socket = new (getWebSocketCtor(options))(buildWsUrl(options), options.protocols);
|
|
1454
|
-
setStatus("connecting");
|
|
1455
|
-
socket.onopen = () => {
|
|
1456
|
-
setStatus("open");
|
|
1457
|
-
sendJson(authPayload());
|
|
1458
|
-
};
|
|
1459
|
-
socket.onmessage = (event) => {
|
|
1460
|
-
const message = parseMessage(event.data);
|
|
1461
|
-
if (!message) return;
|
|
1462
|
-
if ("event" in message && message.event === "connected") {
|
|
1463
|
-
setStatus("authenticated");
|
|
1464
|
-
if (options.siteIds?.length) subscribe(options.siteIds);
|
|
1465
|
-
}
|
|
1466
|
-
for (const handler of messageHandlers) handler(message);
|
|
1467
|
-
if (isRealtimeEvent(message)) for (const handler of eventHandlers) handler(message);
|
|
1468
|
-
};
|
|
1469
|
-
socket.onerror = (event) => {
|
|
1470
|
-
setStatus("error");
|
|
1471
|
-
for (const handler of errorHandlers) handler(event);
|
|
1472
|
-
};
|
|
1473
|
-
socket.onclose = (event) => {
|
|
1474
|
-
socket = null;
|
|
1475
|
-
setStatus("closed");
|
|
1476
|
-
for (const handler of messageHandlers) handler({
|
|
1477
|
-
type: "error",
|
|
1478
|
-
message: `WebSocket closed: ${JSON.stringify(event)}`
|
|
1479
|
-
});
|
|
1480
|
-
};
|
|
1481
|
-
return socket;
|
|
1530
|
+
return openSocket();
|
|
1482
1531
|
},
|
|
1483
1532
|
close(code, reason) {
|
|
1533
|
+
manualClose = true;
|
|
1534
|
+
clearReconnectTimer();
|
|
1484
1535
|
socket?.close(code, reason);
|
|
1485
1536
|
socket = null;
|
|
1486
1537
|
setStatus("closed");
|
|
@@ -1777,7 +1828,7 @@ function classifySearchConsoleStage(input) {
|
|
|
1777
1828
|
const discovered = issueCount$1(issues, "discovered_not_indexed");
|
|
1778
1829
|
const crawled = issueCount$1(issues, "crawled_not_indexed");
|
|
1779
1830
|
const hardBlocks = issueCount$1(issues, "blocked_robots", "server_error", "access_denied", "forbidden") + (input.crawlAuditBlockerCount ?? 0);
|
|
1780
|
-
const canonicalMismatches = input.canonicalMismatchCount ?? issueCount$1(issues, "canonical_mismatch");
|
|
1831
|
+
const canonicalMismatches = Math.min(notIndexed, input.canonicalMismatchCount ?? issueCount$1(issues, "canonical_mismatch"));
|
|
1781
1832
|
const visibleNoClickPages = (input.pageInventory ?? []).filter((page) => page.impressions >= 50 && page.clicks === 0).length;
|
|
1782
1833
|
const poorPositionPages = (input.pageInventory ?? []).filter((page) => page.impressions >= 50 && (page.position ?? 0) > 20).length;
|
|
1783
1834
|
const ctrOutlierCount = input.ctrOutlierCount ?? 0;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/sdk",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.27.
|
|
4
|
+
"version": "0.27.2",
|
|
5
5
|
"description": "Consumer SDK for hosted gscdump.com integrations.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"date-fns": "^4.4.0",
|
|
45
45
|
"ofetch": "^1.5.1",
|
|
46
46
|
"zod": "^4.4.3",
|
|
47
|
-
"@gscdump/analysis": "0.27.
|
|
48
|
-
"@gscdump/
|
|
49
|
-
"
|
|
50
|
-
"gscdump": "0.27.
|
|
47
|
+
"@gscdump/analysis": "0.27.2",
|
|
48
|
+
"@gscdump/engine": "0.27.2",
|
|
49
|
+
"gscdump": "0.27.2",
|
|
50
|
+
"@gscdump/contracts": "0.27.2"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"typescript": "^6.0.3",
|