@superbee/core 0.2.0-pre.16 → 0.2.0-pre.19
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 +622 -5
- package/dist/blob-journal.d.ts +187 -2
- package/dist/blob-journal.d.ts.map +1 -1
- package/dist/blob-journal.js +377 -5
- package/dist/blob-journal.js.map +1 -1
- package/dist/body-replace-guards.d.ts +50 -0
- package/dist/body-replace-guards.d.ts.map +1 -0
- package/dist/body-replace-guards.js +158 -0
- package/dist/body-replace-guards.js.map +1 -0
- package/dist/builtin-recipes/content.d.ts +93 -0
- package/dist/builtin-recipes/content.d.ts.map +1 -0
- package/dist/builtin-recipes/content.js +288 -0
- package/dist/builtin-recipes/content.js.map +1 -0
- package/dist/builtin-recipes.d.ts +10 -0
- package/dist/builtin-recipes.d.ts.map +1 -0
- package/dist/builtin-recipes.js +97 -0
- package/dist/builtin-recipes.js.map +1 -0
- package/dist/bundle-health/index.d.ts +14 -0
- package/dist/bundle-health/index.d.ts.map +1 -0
- package/dist/bundle-health/index.js +12 -0
- package/dist/bundle-health/index.js.map +1 -0
- package/dist/bundle-health/kind-findings.d.ts +44 -0
- package/dist/bundle-health/kind-findings.d.ts.map +1 -0
- package/dist/bundle-health/kind-findings.js +68 -0
- package/dist/bundle-health/kind-findings.js.map +1 -0
- package/dist/bundle-health/legacy-page.d.ts +39 -0
- package/dist/bundle-health/legacy-page.d.ts.map +1 -0
- package/dist/bundle-health/legacy-page.js +50 -0
- package/dist/bundle-health/legacy-page.js.map +1 -0
- package/dist/bundle-health/report.d.ts +202 -0
- package/dist/bundle-health/report.d.ts.map +1 -0
- package/dist/bundle-health/report.js +438 -0
- package/dist/bundle-health/report.js.map +1 -0
- package/dist/code-point-order.d.ts +8 -0
- package/dist/code-point-order.d.ts.map +1 -0
- package/dist/code-point-order.js +20 -0
- package/dist/code-point-order.js.map +1 -0
- package/dist/connectors.d.ts +223 -0
- package/dist/connectors.d.ts.map +1 -0
- package/dist/connectors.js +1143 -0
- package/dist/connectors.js.map +1 -0
- package/dist/document-field-actions.d.ts +18 -0
- package/dist/document-field-actions.d.ts.map +1 -1
- package/dist/document-field-actions.js +91 -29
- package/dist/document-field-actions.js.map +1 -1
- package/dist/document-mutation.d.ts +7 -9
- package/dist/document-mutation.d.ts.map +1 -1
- package/dist/document-mutation.js +16 -16
- package/dist/document-mutation.js.map +1 -1
- package/dist/file-journaled-backend.d.ts +31 -5
- package/dist/file-journaled-backend.d.ts.map +1 -1
- package/dist/file-journaled-backend.js +131 -118
- package/dist/file-journaled-backend.js.map +1 -1
- package/dist/hosted-client/blob-delivery.d.ts +6 -0
- package/dist/hosted-client/blob-delivery.d.ts.map +1 -1
- package/dist/hosted-client/blob-delivery.js +23 -1
- package/dist/hosted-client/blob-delivery.js.map +1 -1
- package/dist/hosted-client/blob-write.d.ts +386 -0
- package/dist/hosted-client/blob-write.d.ts.map +1 -0
- package/dist/hosted-client/blob-write.js +770 -0
- package/dist/hosted-client/blob-write.js.map +1 -0
- package/dist/hosted-client/client.d.ts +64 -0
- package/dist/hosted-client/client.d.ts.map +1 -1
- package/dist/hosted-client/client.js +31 -0
- package/dist/hosted-client/client.js.map +1 -1
- package/dist/hosted-client/directory.d.ts +46 -0
- package/dist/hosted-client/directory.d.ts.map +1 -0
- package/dist/hosted-client/directory.js +74 -0
- package/dist/hosted-client/directory.js.map +1 -0
- package/dist/hosted-client/errors.d.ts +10 -0
- package/dist/hosted-client/errors.d.ts.map +1 -1
- package/dist/hosted-client/errors.js +13 -0
- package/dist/hosted-client/errors.js.map +1 -1
- package/dist/hosted-client/inbox.d.ts +320 -0
- package/dist/hosted-client/inbox.d.ts.map +1 -0
- package/dist/hosted-client/inbox.js +379 -0
- package/dist/hosted-client/inbox.js.map +1 -0
- package/dist/hosted-client/index.d.ts +11 -4
- package/dist/hosted-client/index.d.ts.map +1 -1
- package/dist/hosted-client/index.js +11 -4
- package/dist/hosted-client/index.js.map +1 -1
- package/dist/hosted-client/journal.d.ts +103 -0
- package/dist/hosted-client/journal.d.ts.map +1 -0
- package/dist/hosted-client/journal.js +464 -0
- package/dist/hosted-client/journal.js.map +1 -0
- package/dist/hosted-client/node.d.ts +5 -1
- package/dist/hosted-client/node.d.ts.map +1 -1
- package/dist/hosted-client/node.js +6 -1
- package/dist/hosted-client/node.js.map +1 -1
- package/dist/hosted-client/write.d.ts +28 -2
- package/dist/hosted-client/write.d.ts.map +1 -1
- package/dist/hosted-client/write.js +33 -11
- package/dist/hosted-client/write.js.map +1 -1
- package/dist/hosted-transport/answer-rows.d.ts +3 -2
- package/dist/hosted-transport/answer-rows.d.ts.map +1 -1
- package/dist/hosted-transport/answer-rows.js +1 -1
- package/dist/hosted-transport/answer-rows.js.map +1 -1
- package/dist/hosted-transport/carrier.d.ts +10 -0
- package/dist/hosted-transport/carrier.d.ts.map +1 -1
- package/dist/hosted-transport/carrier.js +22 -2
- package/dist/hosted-transport/carrier.js.map +1 -1
- package/dist/hosted-transport/whole-document-transport.d.ts +1 -1
- package/dist/hosted-transport/whole-document-transport.d.ts.map +1 -1
- package/dist/hosted-transport/whole-document-transport.js +20 -12
- package/dist/hosted-transport/whole-document-transport.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/kind-authoring.d.ts +170 -0
- package/dist/kind-authoring.d.ts.map +1 -0
- package/dist/kind-authoring.js +451 -0
- package/dist/kind-authoring.js.map +1 -0
- package/dist/kind-conformance-error.d.ts +15 -0
- package/dist/kind-conformance-error.d.ts.map +1 -0
- package/dist/kind-conformance-error.js +20 -0
- package/dist/kind-conformance-error.js.map +1 -0
- package/dist/kinds-load.js +4 -4
- package/dist/kinds-load.js.map +1 -1
- package/dist/kinds.d.ts +2 -0
- package/dist/kinds.d.ts.map +1 -1
- package/dist/kinds.js +10 -2
- package/dist/kinds.js.map +1 -1
- package/dist/paths.d.ts +16 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +25 -0
- package/dist/paths.js.map +1 -1
- package/dist/query-filter.d.ts +9 -0
- package/dist/query-filter.d.ts.map +1 -1
- package/dist/query-filter.js +19 -3
- package/dist/query-filter.js.map +1 -1
- package/dist/recipe-lifecycle/stamp.d.ts +11 -0
- package/dist/recipe-lifecycle/stamp.d.ts.map +1 -1
- package/dist/recipe-lifecycle/stamp.js +6 -0
- package/dist/recipe-lifecycle/stamp.js.map +1 -1
- package/dist/record-overlay/apply.d.ts +43 -0
- package/dist/record-overlay/apply.d.ts.map +1 -0
- package/dist/record-overlay/apply.js +527 -0
- package/dist/record-overlay/apply.js.map +1 -0
- package/dist/record-overlay/canonical.d.ts +22 -0
- package/dist/record-overlay/canonical.d.ts.map +1 -0
- package/dist/record-overlay/canonical.js +47 -0
- package/dist/record-overlay/canonical.js.map +1 -0
- package/dist/record-overlay/digest.d.ts +4 -0
- package/dist/record-overlay/digest.d.ts.map +1 -0
- package/dist/record-overlay/digest.js +11 -0
- package/dist/record-overlay/digest.js.map +1 -0
- package/dist/record-overlay/errors.d.ts +44 -0
- package/dist/record-overlay/errors.d.ts.map +1 -0
- package/dist/record-overlay/errors.js +55 -0
- package/dist/record-overlay/errors.js.map +1 -0
- package/dist/record-overlay/findings.d.ts +5 -0
- package/dist/record-overlay/findings.d.ts.map +1 -0
- package/dist/record-overlay/findings.js +83 -0
- package/dist/record-overlay/findings.js.map +1 -0
- package/dist/record-overlay/index.d.ts +23 -0
- package/dist/record-overlay/index.d.ts.map +1 -0
- package/dist/record-overlay/index.js +21 -0
- package/dist/record-overlay/index.js.map +1 -0
- package/dist/record-overlay/plan.d.ts +12 -0
- package/dist/record-overlay/plan.d.ts.map +1 -0
- package/dist/record-overlay/plan.js +285 -0
- package/dist/record-overlay/plan.js.map +1 -0
- package/dist/record-overlay/policy.d.ts +69 -0
- package/dist/record-overlay/policy.d.ts.map +1 -0
- package/dist/record-overlay/policy.js +228 -0
- package/dist/record-overlay/policy.js.map +1 -0
- package/dist/record-overlay/redact.d.ts +3 -0
- package/dist/record-overlay/redact.d.ts.map +1 -0
- package/dist/record-overlay/redact.js +27 -0
- package/dist/record-overlay/redact.js.map +1 -0
- package/dist/record-overlay/signal-kind.d.ts +30 -0
- package/dist/record-overlay/signal-kind.d.ts.map +1 -0
- package/dist/record-overlay/signal-kind.js +38 -0
- package/dist/record-overlay/signal-kind.js.map +1 -0
- package/dist/record-overlay/signal-text.d.ts +45 -0
- package/dist/record-overlay/signal-text.d.ts.map +1 -0
- package/dist/record-overlay/signal-text.js +116 -0
- package/dist/record-overlay/signal-text.js.map +1 -0
- package/dist/record-overlay/source-index.d.ts +19 -0
- package/dist/record-overlay/source-index.d.ts.map +1 -0
- package/dist/record-overlay/source-index.js +102 -0
- package/dist/record-overlay/source-index.js.map +1 -0
- package/dist/record-overlay/types.d.ts +291 -0
- package/dist/record-overlay/types.d.ts.map +1 -0
- package/dist/record-overlay/types.js +2 -0
- package/dist/record-overlay/types.js.map +1 -0
- package/dist/remote-operations.js +5 -2
- package/dist/remote-operations.js.map +1 -1
- package/dist/search/contract.d.ts +151 -0
- package/dist/search/contract.d.ts.map +1 -0
- package/dist/search/contract.js +78 -0
- package/dist/search/contract.js.map +1 -0
- package/dist/search/errors.d.ts +30 -0
- package/dist/search/errors.d.ts.map +1 -0
- package/dist/search/errors.js +50 -0
- package/dist/search/errors.js.map +1 -0
- package/dist/search/identity.d.ts +12 -0
- package/dist/search/identity.d.ts.map +1 -0
- package/dist/search/identity.js +90 -0
- package/dist/search/identity.js.map +1 -0
- package/dist/search/index.d.ts +15 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +14 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/memory-source.d.ts +25 -0
- package/dist/search/memory-source.d.ts.map +1 -0
- package/dist/search/memory-source.js +230 -0
- package/dist/search/memory-source.js.map +1 -0
- package/dist/search/rank.d.ts +34 -0
- package/dist/search/rank.d.ts.map +1 -0
- package/dist/search/rank.js +129 -0
- package/dist/search/rank.js.map +1 -0
- package/dist/search/row-text.d.ts +38 -0
- package/dist/search/row-text.d.ts.map +1 -0
- package/dist/search/row-text.js +88 -0
- package/dist/search/row-text.js.map +1 -0
- package/dist/search/search.d.ts +28 -0
- package/dist/search/search.d.ts.map +1 -0
- package/dist/search/search.js +240 -0
- package/dist/search/search.js.map +1 -0
- package/dist/search/source.d.ts +67 -0
- package/dist/search/source.d.ts.map +1 -0
- package/dist/search/source.js +2 -0
- package/dist/search/source.js.map +1 -0
- package/dist/search/text.d.ts +47 -0
- package/dist/search/text.d.ts.map +1 -0
- package/dist/search/text.js +148 -0
- package/dist/search/text.js.map +1 -0
- package/dist/source-engine/guard.d.ts +82 -0
- package/dist/source-engine/guard.d.ts.map +1 -0
- package/dist/source-engine/guard.js +396 -0
- package/dist/source-engine/guard.js.map +1 -0
- package/dist/source-engine/index.d.ts +24 -0
- package/dist/source-engine/index.d.ts.map +1 -0
- package/dist/source-engine/index.js +20 -0
- package/dist/source-engine/index.js.map +1 -0
- package/dist/source-engine/machine-state.d.ts +74 -0
- package/dist/source-engine/machine-state.d.ts.map +1 -0
- package/dist/source-engine/machine-state.js +48 -0
- package/dist/source-engine/machine-state.js.map +1 -0
- package/dist/source-engine/observe.d.ts +18 -0
- package/dist/source-engine/observe.d.ts.map +1 -0
- package/dist/source-engine/observe.js +598 -0
- package/dist/source-engine/observe.js.map +1 -0
- package/dist/source-engine/robots.d.ts +53 -0
- package/dist/source-engine/robots.d.ts.map +1 -0
- package/dist/source-engine/robots.js +158 -0
- package/dist/source-engine/robots.js.map +1 -0
- package/dist/source-engine/types.d.ts +285 -0
- package/dist/source-engine/types.d.ts.map +1 -0
- package/dist/source-engine/types.js +2 -0
- package/dist/source-engine/types.js.map +1 -0
- package/dist/source-harness/conformance.d.ts +16 -0
- package/dist/source-harness/conformance.d.ts.map +1 -0
- package/dist/source-harness/conformance.js +265 -0
- package/dist/source-harness/conformance.js.map +1 -0
- package/dist/source-harness/fixture.d.ts +95 -0
- package/dist/source-harness/fixture.d.ts.map +1 -0
- package/dist/source-harness/fixture.js +261 -0
- package/dist/source-harness/fixture.js.map +1 -0
- package/dist/source-harness/index.d.ts +22 -0
- package/dist/source-harness/index.d.ts.map +1 -0
- package/dist/source-harness/index.js +19 -0
- package/dist/source-harness/index.js.map +1 -0
- package/dist/source-harness/peer.d.ts +74 -0
- package/dist/source-harness/peer.d.ts.map +1 -0
- package/dist/source-harness/peer.js +106 -0
- package/dist/source-harness/peer.js.map +1 -0
- package/dist/storage.d.ts +2 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +1 -1
- package/dist/storage.js.map +1 -1
- package/dist/uncertain-write.d.ts +39 -6
- package/dist/uncertain-write.d.ts.map +1 -1
- package/dist/uncertain-write.js +25 -3
- package/dist/uncertain-write.js.map +1 -1
- package/package.json +33 -1
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The guarded transport a profile sees. It checks every URL and every redirect hop against the
|
|
3
|
+
* run's host set (the profile's hosts within the connector's credential hosts and keyless domains)
|
|
4
|
+
* and the address rule, reads and follows robots.txt for keyless hosts, applies the method rule and
|
|
5
|
+
* the header allowlist, follows redirects itself with the guard re-run per hop, counts the request
|
|
6
|
+
* budget, honours the deadline and maps statuses to outcomes. Any refusal or error status stops
|
|
7
|
+
* the run: the call throws and the stop is recorded here, so a profile cannot swallow it.
|
|
8
|
+
*/
|
|
9
|
+
import { credentialHosts } from "../connectors.js";
|
|
10
|
+
import { redactUrl } from "../record-overlay/redact.js";
|
|
11
|
+
import { challenged, refusedAddress, robotsDecision } from "./robots.js";
|
|
12
|
+
export const DEFAULT_SOURCE_BUDGET = Object.freeze({
|
|
13
|
+
requests: 100,
|
|
14
|
+
maxBytes: 2 * 1024 * 1024,
|
|
15
|
+
redirects: 5,
|
|
16
|
+
pages: 50,
|
|
17
|
+
deadlineMs: 300_000,
|
|
18
|
+
requestTimeoutMs: 20_000,
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* The engine's status sets. 503 is not deferred: it ends `provider_unavailable` with a retry and
|
|
22
|
+
* any `retry_after`; a declaration's `errors` rows pass their own sets.
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_STATUS_RULES = Object.freeze({
|
|
25
|
+
deferred: Object.freeze([429]),
|
|
26
|
+
credential_refused: Object.freeze([401, 403]),
|
|
27
|
+
not_found: Object.freeze([404, 410]),
|
|
28
|
+
});
|
|
29
|
+
const REDIRECTS = new Set([301, 302, 303, 307, 308]);
|
|
30
|
+
/** RFC 9309 2.5: parse at least 500 KiB. A longer file is read whole and parsed up to here. */
|
|
31
|
+
const MAX_ROBOTS_BYTES = 512 * 1024;
|
|
32
|
+
/** RFC 9309 2.3.1.2: follow at least five redirects for robots.txt. */
|
|
33
|
+
const MAX_ROBOTS_REDIRECTS = 5;
|
|
34
|
+
const MAX_URL = 8192;
|
|
35
|
+
const MAX_HEADERS = 32;
|
|
36
|
+
const BASE_HEADERS = new Set(["accept"]);
|
|
37
|
+
const VALIDATOR_HEADERS = new Set(["if-none-match", "if-modified-since"]);
|
|
38
|
+
const NEVER_SENT = new Set([
|
|
39
|
+
"authorization", "proxy-authorization", "cookie", "host", "user-agent",
|
|
40
|
+
"x-http-method-override", "x-http-method", "x-method-override",
|
|
41
|
+
"content-length", "transfer-encoding", "connection",
|
|
42
|
+
]);
|
|
43
|
+
const HEADER_NAME = /^[a-z0-9!#$%&'*+.^_`|~-]{1,64}$/;
|
|
44
|
+
const HEADER_VALUE = /^[\t\x20-\x7e]{0,8192}$/;
|
|
45
|
+
/** Thrown through a profile when the run stops. */
|
|
46
|
+
export class SourceStop extends Error {
|
|
47
|
+
stop;
|
|
48
|
+
constructor(stop) {
|
|
49
|
+
super(`source run stopped: ${stop.outcome}${stop.reason ? ` (${stop.reason})` : ""}`);
|
|
50
|
+
this.name = "SourceStop";
|
|
51
|
+
this.stop = stop;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The run's host set: the profile's hosts, each of which must be a credential host of the auth
|
|
56
|
+
* kind or a declared keyless domain. A host outside both is returned as undeclared.
|
|
57
|
+
*/
|
|
58
|
+
export function sourceHostSet(connector, hosts) {
|
|
59
|
+
const credential = new Set(credentialHosts(connector.auth));
|
|
60
|
+
const domains = new Set(connector.domains);
|
|
61
|
+
const undeclared = hosts.filter((host) => !credential.has(host) && !domains.has(host));
|
|
62
|
+
if (undeclared.length)
|
|
63
|
+
return { ok: false, undeclared: [...new Set(undeclared)].sort() };
|
|
64
|
+
const allowed = new Set(hosts);
|
|
65
|
+
return {
|
|
66
|
+
ok: true,
|
|
67
|
+
hosts: {
|
|
68
|
+
allowed,
|
|
69
|
+
credential: new Set([...allowed].filter((host) => credential.has(host))),
|
|
70
|
+
keyless: new Set([...allowed].filter((host) => domains.has(host) && !credential.has(host))),
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
75
|
+
/** The first 512 KiB of a robots.txt, cut back to the last whole line so no rule is shortened. */
|
|
76
|
+
function robotsPrefix(text) {
|
|
77
|
+
if (text.length <= MAX_ROBOTS_BYTES)
|
|
78
|
+
return text;
|
|
79
|
+
const cut = text.slice(0, MAX_ROBOTS_BYTES);
|
|
80
|
+
const end = Math.max(cut.lastIndexOf("\n"), cut.lastIndexOf("\r"));
|
|
81
|
+
return end === -1 ? "" : cut.slice(0, end);
|
|
82
|
+
}
|
|
83
|
+
/** `promise`, or a rejection once `signal` aborts; the abandoned promise's later failure is ignored. */
|
|
84
|
+
export function raceAbort(promise, signal) {
|
|
85
|
+
if (!signal)
|
|
86
|
+
return promise;
|
|
87
|
+
// A request abandoned at the deadline may still fail later; that is not this run's error.
|
|
88
|
+
promise.catch(() => { });
|
|
89
|
+
if (signal.aborted)
|
|
90
|
+
return Promise.reject(new Error("aborted"));
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
const onAbort = () => reject(new Error("aborted"));
|
|
93
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
94
|
+
promise.then((value) => { signal.removeEventListener("abort", onAbort); resolve(value); }, (error) => { signal.removeEventListener("abort", onAbort); reject(error); });
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/** A transport answer in the contract's shape, header names lowercased, or undefined. */
|
|
98
|
+
function readResult(result, maxBytes) {
|
|
99
|
+
if (!record(result))
|
|
100
|
+
return undefined;
|
|
101
|
+
if (result.ok === false)
|
|
102
|
+
return result.refused === "too_large" ? { ok: false, refused: "too_large" } : undefined;
|
|
103
|
+
if (result.ok !== true)
|
|
104
|
+
return undefined;
|
|
105
|
+
const { status, headers, body, bytes } = result;
|
|
106
|
+
if (typeof status !== "number" || !Number.isInteger(status) || status < 100 || status > 599)
|
|
107
|
+
return undefined;
|
|
108
|
+
if (typeof body !== "string" || typeof bytes !== "number" || !Number.isInteger(bytes) || bytes < 0 || !record(headers))
|
|
109
|
+
return undefined;
|
|
110
|
+
const lower = {};
|
|
111
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
112
|
+
if (typeof value !== "string")
|
|
113
|
+
return undefined;
|
|
114
|
+
lower[name.toLowerCase()] = value;
|
|
115
|
+
}
|
|
116
|
+
// A decoded body never holds more UTF-16 units than the bytes it came from.
|
|
117
|
+
if (bytes > maxBytes || body.length > maxBytes)
|
|
118
|
+
return { ok: false, refused: "too_large" };
|
|
119
|
+
return { ok: true, status, headers: lower, body, bytes };
|
|
120
|
+
}
|
|
121
|
+
export function guardTransport(ctx) {
|
|
122
|
+
const { hosts, identity, budget, rules, statuses, signal } = ctx;
|
|
123
|
+
const requests = [];
|
|
124
|
+
const robots = new Map();
|
|
125
|
+
let left = budget.requests;
|
|
126
|
+
let stop;
|
|
127
|
+
let closed = false;
|
|
128
|
+
function halt(next) {
|
|
129
|
+
stop ??= next;
|
|
130
|
+
throw new SourceStop(stop);
|
|
131
|
+
}
|
|
132
|
+
const retryAfter = (value) => {
|
|
133
|
+
if (value === undefined)
|
|
134
|
+
return {};
|
|
135
|
+
const text = value.trim();
|
|
136
|
+
if (/^\d{1,9}$/.test(text))
|
|
137
|
+
return { retry_after: new Date(ctx.now().getTime() + Number(text) * 1000).toISOString() };
|
|
138
|
+
const at = Date.parse(text);
|
|
139
|
+
return Number.isFinite(at) ? { retry_after: new Date(at).toISOString() } : {};
|
|
140
|
+
};
|
|
141
|
+
const statusStop = (status, headers) => {
|
|
142
|
+
if (status >= 200 && status < 300)
|
|
143
|
+
return undefined;
|
|
144
|
+
if (status === 304)
|
|
145
|
+
return ctx.conditional ? undefined : { outcome: "provider_unavailable", reason: "not_modified", status, retry: true };
|
|
146
|
+
if (statuses.credential_refused.includes(status))
|
|
147
|
+
return { outcome: "credential_refused", status, retry: false };
|
|
148
|
+
if (statuses.not_found.includes(status))
|
|
149
|
+
return { outcome: "not_found", status, retry: false };
|
|
150
|
+
if (statuses.deferred.includes(status))
|
|
151
|
+
return { outcome: "deferred", reason: "rate_limited", status, retry: true, ...retryAfter(headers["retry-after"]) };
|
|
152
|
+
return { outcome: "provider_unavailable", reason: status >= 500 ? "server_error" : "status", status, retry: status >= 500, ...retryAfter(headers["retry-after"]) };
|
|
153
|
+
};
|
|
154
|
+
/** Why `url` may not be requested at all, coming from `from` on a redirect. */
|
|
155
|
+
const hopRefusal = (url, from) => {
|
|
156
|
+
if (url.protocol !== "https:")
|
|
157
|
+
return { reason: "scheme_refused", detail: url.protocol };
|
|
158
|
+
const address = refusedAddress(url);
|
|
159
|
+
if (address)
|
|
160
|
+
return { reason: "address_refused", detail: address };
|
|
161
|
+
if (!hosts.allowed.has(url.hostname))
|
|
162
|
+
return { reason: "host_refused", detail: url.hostname };
|
|
163
|
+
// A credential never crosses hosts, and no other host may steer a credentialed request's path.
|
|
164
|
+
if (from && from.hostname !== url.hostname && (hosts.credential.has(from.hostname) || hosts.credential.has(url.hostname))) {
|
|
165
|
+
return { reason: "redirect_refused", detail: `${from.hostname} to ${url.hostname}` };
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
};
|
|
169
|
+
const refuseRow = (method, url, purpose, refused) => {
|
|
170
|
+
requests.push({ method, url: redactUrl(typeof url === "string" ? url : url.href), purpose, refused });
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* One transport call. Budget and deadline stop the run; a failed call returns "timeout" or
|
|
174
|
+
* "failed".
|
|
175
|
+
*/
|
|
176
|
+
const send = async (url, method, headers, body, maxBytes, purpose) => {
|
|
177
|
+
if (signal?.aborted)
|
|
178
|
+
halt({ outcome: "deferred", reason: "deadline", retry: true });
|
|
179
|
+
if (left <= 0)
|
|
180
|
+
halt({ outcome: "deferred", reason: "budget", retry: true });
|
|
181
|
+
left -= 1;
|
|
182
|
+
const row = { method, url: redactUrl(url.href), purpose };
|
|
183
|
+
requests.push(row);
|
|
184
|
+
let requestSignal = signal;
|
|
185
|
+
let timer;
|
|
186
|
+
let timedOut = false;
|
|
187
|
+
let onRunAbort;
|
|
188
|
+
if (ctx.requestTimeoutMs !== undefined) {
|
|
189
|
+
const controller = new AbortController();
|
|
190
|
+
timer = setTimeout(() => { timedOut = true; controller.abort(); }, ctx.requestTimeoutMs);
|
|
191
|
+
if (signal)
|
|
192
|
+
signal.addEventListener("abort", onRunAbort = () => controller.abort(), { once: true });
|
|
193
|
+
requestSignal = controller.signal;
|
|
194
|
+
}
|
|
195
|
+
let raw;
|
|
196
|
+
try {
|
|
197
|
+
raw = await raceAbort(ctx.transport.request({
|
|
198
|
+
url: url.href, method, headers: { ...headers, "user-agent": identity.userAgent }, maxBytes,
|
|
199
|
+
credentialHost: hosts.credential.has(url.hostname),
|
|
200
|
+
...(body !== undefined ? { body } : {}), ...(requestSignal ? { signal: requestSignal } : {}),
|
|
201
|
+
}), requestSignal);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
if (signal?.aborted) {
|
|
205
|
+
row.refused = "deadline";
|
|
206
|
+
halt({ outcome: "deferred", reason: "deadline", retry: true });
|
|
207
|
+
}
|
|
208
|
+
row.refused = timedOut ? "timeout" : "transport";
|
|
209
|
+
return timedOut ? "timeout" : "failed";
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
if (timer !== undefined)
|
|
213
|
+
clearTimeout(timer);
|
|
214
|
+
if (onRunAbort)
|
|
215
|
+
signal.removeEventListener("abort", onRunAbort);
|
|
216
|
+
}
|
|
217
|
+
const result = readResult(raw, maxBytes);
|
|
218
|
+
if (!result) {
|
|
219
|
+
row.refused = "transport_invalid";
|
|
220
|
+
return "failed";
|
|
221
|
+
}
|
|
222
|
+
if (!result.ok) {
|
|
223
|
+
row.refused = "too_large";
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
row.status = result.status;
|
|
227
|
+
return result;
|
|
228
|
+
};
|
|
229
|
+
const readRobots = async (origin) => {
|
|
230
|
+
let url = new URL("/robots.txt", origin);
|
|
231
|
+
let from;
|
|
232
|
+
for (let hop = 0; hop <= MAX_ROBOTS_REDIRECTS; hop++) {
|
|
233
|
+
const refusal = hopRefusal(url, from);
|
|
234
|
+
if (refusal) {
|
|
235
|
+
refuseRow("GET", url, "robots", refusal.reason);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
const result = await send(url, "GET", { accept: "text/plain, */*;q=0.1" }, undefined, Math.max(budget.maxBytes, MAX_ROBOTS_BYTES), "robots");
|
|
239
|
+
if (typeof result === "string" || !result.ok)
|
|
240
|
+
break;
|
|
241
|
+
if (REDIRECTS.has(result.status)) {
|
|
242
|
+
const location = result.headers.location;
|
|
243
|
+
if (!location)
|
|
244
|
+
break;
|
|
245
|
+
let next;
|
|
246
|
+
try {
|
|
247
|
+
next = new URL(location, url);
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
next.hash = "";
|
|
253
|
+
from = url;
|
|
254
|
+
url = next;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (challenged(result.status, result.headers, result.body))
|
|
258
|
+
return { status: result.status, text: "", challenged: true };
|
|
259
|
+
return { status: result.status, text: result.status >= 200 && result.status < 300 ? robotsPrefix(result.body) : "" };
|
|
260
|
+
}
|
|
261
|
+
return { status: 0, text: "" };
|
|
262
|
+
};
|
|
263
|
+
const robotsGate = async (url, method) => {
|
|
264
|
+
let pending = robots.get(url.origin);
|
|
265
|
+
if (!pending)
|
|
266
|
+
robots.set(url.origin, pending = readRobots(url.origin));
|
|
267
|
+
const entry = await pending;
|
|
268
|
+
const refuse = (next) => {
|
|
269
|
+
refuseRow(method, url, "page", next.reason);
|
|
270
|
+
return halt(next);
|
|
271
|
+
};
|
|
272
|
+
if (entry.challenged)
|
|
273
|
+
refuse({ outcome: "refused", reason: "bot_challenge", status: entry.status, retry: false });
|
|
274
|
+
if (entry.status >= 400 && entry.status < 500)
|
|
275
|
+
return;
|
|
276
|
+
if (entry.status === 0 || entry.status >= 500) {
|
|
277
|
+
refuse({ outcome: "refused", reason: "robots_unavailable", retry: true, ...(entry.status ? { status: entry.status } : {}) });
|
|
278
|
+
}
|
|
279
|
+
const decision = robotsDecision(entry.text, url.pathname + url.search, identity.productToken);
|
|
280
|
+
if (!decision.allow)
|
|
281
|
+
refuse({ outcome: "refused", reason: "robots_disallowed", retry: false, ...(decision.rule ? { detail: decision.rule } : {}) });
|
|
282
|
+
};
|
|
283
|
+
const headersFor = (entries, url, method) => {
|
|
284
|
+
const out = {};
|
|
285
|
+
if (entries === null || entries.length > MAX_HEADERS)
|
|
286
|
+
halt({ outcome: "refused", reason: "header_refused", retry: false });
|
|
287
|
+
for (const [rawName, value] of entries) {
|
|
288
|
+
const name = rawName.toLowerCase();
|
|
289
|
+
const admitted = HEADER_NAME.test(name) && !NEVER_SENT.has(name) && typeof value === "string" && HEADER_VALUE.test(value)
|
|
290
|
+
&& (BASE_HEADERS.has(name) || (VALIDATOR_HEADERS.has(name) ? ctx.conditional : rules.header?.(name, url) === true));
|
|
291
|
+
if (!admitted) {
|
|
292
|
+
refuseRow(method, url, "page", "header_refused");
|
|
293
|
+
halt({ outcome: "refused", reason: "header_refused", detail: name.slice(0, 64), retry: false });
|
|
294
|
+
}
|
|
295
|
+
out[name] = value;
|
|
296
|
+
}
|
|
297
|
+
return out;
|
|
298
|
+
};
|
|
299
|
+
const request = async (input) => {
|
|
300
|
+
if (stop)
|
|
301
|
+
throw new SourceStop(stop);
|
|
302
|
+
if (closed)
|
|
303
|
+
throw new SourceStop({ outcome: "refused", reason: "run_ended", retry: false });
|
|
304
|
+
if (!record(input))
|
|
305
|
+
halt({ outcome: "refused", reason: "url_invalid", retry: false });
|
|
306
|
+
// Each field is read once: a getter answering differently on a second read changes nothing.
|
|
307
|
+
const { url: rawUrl, method: rawMethod, headers: rawHeaders, body, maxBytes: rawMaxBytes } = input;
|
|
308
|
+
const headerEntries = rawHeaders === undefined ? [] : record(rawHeaders) ? Object.entries(rawHeaders) : null;
|
|
309
|
+
if (typeof rawUrl !== "string" || rawUrl.length > MAX_URL)
|
|
310
|
+
halt({ outcome: "refused", reason: "url_invalid", retry: false });
|
|
311
|
+
const method = rawMethod ?? "GET";
|
|
312
|
+
if (method !== "GET" && method !== "POST")
|
|
313
|
+
halt({ outcome: "refused", reason: "method_refused", retry: false });
|
|
314
|
+
if (body !== undefined && typeof body !== "string")
|
|
315
|
+
halt({ outcome: "refused", reason: "body_refused", retry: false });
|
|
316
|
+
if (rawMaxBytes !== undefined && !(typeof rawMaxBytes === "number" && Number.isInteger(rawMaxBytes) && rawMaxBytes > 0)) {
|
|
317
|
+
halt({ outcome: "refused", reason: "request_invalid", detail: "maxBytes", retry: false });
|
|
318
|
+
}
|
|
319
|
+
const maxBytes = Math.min(rawMaxBytes ?? budget.maxBytes, budget.maxBytes);
|
|
320
|
+
let url;
|
|
321
|
+
try {
|
|
322
|
+
url = new URL(rawUrl);
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
refuseRow(method, rawUrl.slice(0, 256), "page", "url_invalid");
|
|
326
|
+
halt({ outcome: "refused", reason: "url_invalid", retry: false });
|
|
327
|
+
}
|
|
328
|
+
url.hash = "";
|
|
329
|
+
if (method === "GET" && body !== undefined) {
|
|
330
|
+
refuseRow(method, url, "page", "body_refused");
|
|
331
|
+
halt({ outcome: "refused", reason: "body_refused", retry: false });
|
|
332
|
+
}
|
|
333
|
+
// A keyless host is read with GET only, whatever a rule says.
|
|
334
|
+
if (method === "POST" && (!hosts.credential.has(url.hostname) || rules.post?.(url, body) !== true)) {
|
|
335
|
+
refuseRow(method, url, "page", "method_refused");
|
|
336
|
+
halt({ outcome: "refused", reason: "method_refused", retry: false });
|
|
337
|
+
}
|
|
338
|
+
let from;
|
|
339
|
+
for (let hop = 0;; hop++) {
|
|
340
|
+
const refusal = hopRefusal(url, from);
|
|
341
|
+
if (refusal) {
|
|
342
|
+
refuseRow(method, url, "page", refusal.reason);
|
|
343
|
+
halt({ outcome: "refused", ...refusal, retry: false });
|
|
344
|
+
}
|
|
345
|
+
if (rules.url && rules.url(url, { method, redirect: hop > 0 }) !== true) {
|
|
346
|
+
refuseRow(method, url, "page", "url_refused");
|
|
347
|
+
halt({ outcome: "refused", reason: "url_refused", retry: false });
|
|
348
|
+
}
|
|
349
|
+
const headers = headersFor(headerEntries, url, method);
|
|
350
|
+
if (hosts.keyless.has(url.hostname))
|
|
351
|
+
await robotsGate(url, method);
|
|
352
|
+
const result = await send(url, method, headers, body, maxBytes, "page");
|
|
353
|
+
if (result === "failed" || result === "timeout")
|
|
354
|
+
halt({ outcome: "provider_unavailable", reason: result === "timeout" ? "timeout" : "transport", retry: true });
|
|
355
|
+
if (!result.ok)
|
|
356
|
+
halt({ outcome: "too_large", retry: false });
|
|
357
|
+
const { status, headers: responseHeaders, body: responseBody } = result;
|
|
358
|
+
// A bot-mitigation page is never content and never retried around.
|
|
359
|
+
if (hosts.keyless.has(url.hostname) && challenged(status, responseHeaders, responseBody)) {
|
|
360
|
+
halt({ outcome: "refused", reason: "bot_challenge", status, retry: false });
|
|
361
|
+
}
|
|
362
|
+
if (REDIRECTS.has(status)) {
|
|
363
|
+
if (method !== "GET")
|
|
364
|
+
halt({ outcome: "refused", reason: "redirect_refused", detail: method, status, retry: false });
|
|
365
|
+
const location = responseHeaders.location;
|
|
366
|
+
if (!location)
|
|
367
|
+
halt({ outcome: "refused", reason: "redirect_invalid", status, retry: false });
|
|
368
|
+
if (hop >= budget.redirects)
|
|
369
|
+
halt({ outcome: "refused", reason: "redirect_limit", status, retry: false });
|
|
370
|
+
let next;
|
|
371
|
+
try {
|
|
372
|
+
next = new URL(location, url);
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
halt({ outcome: "refused", reason: "url_invalid", status, retry: false });
|
|
376
|
+
}
|
|
377
|
+
next.hash = "";
|
|
378
|
+
from = url;
|
|
379
|
+
url = next;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
const stopped = statusStop(status, responseHeaders);
|
|
383
|
+
if (stopped)
|
|
384
|
+
halt(stopped);
|
|
385
|
+
return { status, headers: responseHeaders, body: responseBody, url: url.href };
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
return {
|
|
389
|
+
transport: { request },
|
|
390
|
+
requests,
|
|
391
|
+
stopped: () => stop,
|
|
392
|
+
remaining: () => left,
|
|
393
|
+
close: () => { closed = true; },
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/source-engine/guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@superbee/core/source-engine`: the portable half of the integration source engine.
|
|
3
|
+
*
|
|
4
|
+
* A {@link SourceProfile} turns a bound Source Feed, a cursor and a transport into pages of
|
|
5
|
+
* normalized records; it never opens a socket, never sees a credential and never writes. A
|
|
6
|
+
* {@link Transport} is the one network port: it never follows a redirect and refuses a body over
|
|
7
|
+
* its byte bound. {@link observeSource} wraps the transport before a profile sees it and owns the
|
|
8
|
+
* host guard (every URL and redirect hop within the profile's hosts, the auth kind's credential
|
|
9
|
+
* hosts and the declared keyless domains, plus the address rule), robots.txt for keyless hosts,
|
|
10
|
+
* the method rule and header allowlist, the budget and deadline, the status-to-outcome mapping,
|
|
11
|
+
* the cursor rule (a cursor is stored only after its page commits), completeness, and the diff into
|
|
12
|
+
* record-overlay changes, with disappearance only from a complete observation.
|
|
13
|
+
*
|
|
14
|
+
* Storage-neutral and Worker-free: no Node globals or builtins, and nothing here calls `fetch`.
|
|
15
|
+
*/
|
|
16
|
+
export { canonicalRobotsPath, fetchIdentity, parseRobots, refusedAddress, robotsDecision, robotsRuleMatches, } from "./robots.js";
|
|
17
|
+
export type { FetchIdentity, RobotsGroup } from "./robots.js";
|
|
18
|
+
export { DEFAULT_SOURCE_BUDGET, DEFAULT_STATUS_RULES, sourceHostSet } from "./guard.js";
|
|
19
|
+
export type { HostSet } from "./guard.js";
|
|
20
|
+
export { DEFAULT_MISSING_THRESHOLD, MAX_CURSOR_CHARS, MAX_REPLAY_FAILURES, observeSource, unsupportedContent } from "./observe.js";
|
|
21
|
+
export { isSourceState, MachineStateConflict, MemoryMachineState } from "./machine-state.js";
|
|
22
|
+
export type { MachineState, PendingChange, RecordEntry, SourceState } from "./machine-state.js";
|
|
23
|
+
export type { CommitResult, HttpMethod, NormalizedRecord, ObserveContext, ObservePage, ObserveSourceOptions, PageCommit, ProfileDiagnostic, ProfileRequest, ProfileResponse, ProfileTransport, RequestRules, SourceBudget, SourceOutcome, SourceProfile, SourceRequestRow, SourceRunReceipt, SpecResult, StatusRules, Transport, TransportRequest, TransportResult, } from "./types.js";
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/source-engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxF,YAAY,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnI,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7F,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAChG,YAAY,EACV,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@superbee/core/source-engine`: the portable half of the integration source engine.
|
|
3
|
+
*
|
|
4
|
+
* A {@link SourceProfile} turns a bound Source Feed, a cursor and a transport into pages of
|
|
5
|
+
* normalized records; it never opens a socket, never sees a credential and never writes. A
|
|
6
|
+
* {@link Transport} is the one network port: it never follows a redirect and refuses a body over
|
|
7
|
+
* its byte bound. {@link observeSource} wraps the transport before a profile sees it and owns the
|
|
8
|
+
* host guard (every URL and redirect hop within the profile's hosts, the auth kind's credential
|
|
9
|
+
* hosts and the declared keyless domains, plus the address rule), robots.txt for keyless hosts,
|
|
10
|
+
* the method rule and header allowlist, the budget and deadline, the status-to-outcome mapping,
|
|
11
|
+
* the cursor rule (a cursor is stored only after its page commits), completeness, and the diff into
|
|
12
|
+
* record-overlay changes, with disappearance only from a complete observation.
|
|
13
|
+
*
|
|
14
|
+
* Storage-neutral and Worker-free: no Node globals or builtins, and nothing here calls `fetch`.
|
|
15
|
+
*/
|
|
16
|
+
export { canonicalRobotsPath, fetchIdentity, parseRobots, refusedAddress, robotsDecision, robotsRuleMatches, } from "./robots.js";
|
|
17
|
+
export { DEFAULT_SOURCE_BUDGET, DEFAULT_STATUS_RULES, sourceHostSet } from "./guard.js";
|
|
18
|
+
export { DEFAULT_MISSING_THRESHOLD, MAX_CURSOR_CHARS, MAX_REPLAY_FAILURES, observeSource, unsupportedContent } from "./observe.js";
|
|
19
|
+
export { isSourceState, MachineStateConflict, MemoryMachineState } from "./machine-state.js";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/source-engine/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExF,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnI,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The machine-state port: one JSON document per Source Feed holding the stored cursor, the last
|
|
3
|
+
* accepted values of every record and the changes still pending a write, written with a
|
|
4
|
+
* compare-and-swap on its version. The managed runner keeps it in its own store;
|
|
5
|
+
* `MemoryMachineState` serves tests and local runs.
|
|
6
|
+
*/
|
|
7
|
+
import type { RecordChange } from "../record-overlay/types.js";
|
|
8
|
+
/** One record's last accepted state. */
|
|
9
|
+
export interface RecordEntry {
|
|
10
|
+
/** The last accepted `after`, carried values included. */
|
|
11
|
+
after: Record<string, unknown>;
|
|
12
|
+
digest: string;
|
|
13
|
+
/** Consecutive complete observations without the record. */
|
|
14
|
+
missing: number;
|
|
15
|
+
first_missing_at?: string;
|
|
16
|
+
/** Reported `disappeared`; a later sighting is `new` again. */
|
|
17
|
+
gone?: true;
|
|
18
|
+
seen_at: string;
|
|
19
|
+
}
|
|
20
|
+
/** A change a commit asked to retry: planned again at the start of every run until written. */
|
|
21
|
+
export interface PendingChange {
|
|
22
|
+
change: RecordChange;
|
|
23
|
+
/** The record's entry once the change is written. */
|
|
24
|
+
entry: RecordEntry;
|
|
25
|
+
held_at: string;
|
|
26
|
+
/** Replays whose commit threw. */
|
|
27
|
+
replay_failures?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface SourceState {
|
|
30
|
+
v: 1;
|
|
31
|
+
/** The profile that wrote `cursor`; a cursor from another id or version is never handed back. */
|
|
32
|
+
profile: {
|
|
33
|
+
id: string;
|
|
34
|
+
version: number;
|
|
35
|
+
};
|
|
36
|
+
cursor: unknown;
|
|
37
|
+
/** The last committed page left its pass open. */
|
|
38
|
+
open: boolean;
|
|
39
|
+
validators?: Record<string, string>;
|
|
40
|
+
records: Record<string, RecordEntry>;
|
|
41
|
+
pending?: Record<string, PendingChange>;
|
|
42
|
+
complete_observations: number;
|
|
43
|
+
last_complete_at?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface MachineState {
|
|
46
|
+
/** The state stored under `key` and the version a write must name, or null. */
|
|
47
|
+
read(key: string): Promise<{
|
|
48
|
+
state: SourceState;
|
|
49
|
+
version: string;
|
|
50
|
+
} | null>;
|
|
51
|
+
/**
|
|
52
|
+
* Store `state` when the stored version is still `expected` (null: nothing stored) and return the
|
|
53
|
+
* new version; otherwise throw a {@link MachineStateConflict}.
|
|
54
|
+
*/
|
|
55
|
+
write(key: string, state: SourceState, expected: string | null): Promise<string>;
|
|
56
|
+
}
|
|
57
|
+
export declare class MachineStateConflict extends Error {
|
|
58
|
+
readonly code = "MACHINE_STATE_CONFLICT";
|
|
59
|
+
constructor(key: string);
|
|
60
|
+
}
|
|
61
|
+
/** Machine state in memory. Values are copied in and out, so a caller never aliases the store. */
|
|
62
|
+
export declare class MemoryMachineState implements MachineState {
|
|
63
|
+
private readonly entries;
|
|
64
|
+
private counter;
|
|
65
|
+
read(key: string): Promise<{
|
|
66
|
+
state: SourceState;
|
|
67
|
+
version: string;
|
|
68
|
+
} | null>;
|
|
69
|
+
write(key: string, state: SourceState, expected: string | null): Promise<string>;
|
|
70
|
+
/** Every key stored. */
|
|
71
|
+
keys(): string[];
|
|
72
|
+
}
|
|
73
|
+
export declare function isSourceState(value: unknown): value is SourceState;
|
|
74
|
+
//# sourceMappingURL=machine-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state.d.ts","sourceRoot":"","sources":["../../src/source-engine/machine-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,+FAA+F;AAC/F,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,CAAC;IACrB,qDAAqD;IACrD,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,iGAAiG;IACjG,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,kDAAkD;IAClD,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACxC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC3E;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAClF;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,4BAA4B;gBAC7B,GAAG,EAAE,MAAM;CAIxB;AAED,kGAAkG;AAClG,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwD;IAChF,OAAO,CAAC,OAAO,CAAK;IAEd,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAK1E,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAQtF,wBAAwB;IACxB,IAAI,IAAI,MAAM,EAAE;CAGjB;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CASlE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export class MachineStateConflict extends Error {
|
|
2
|
+
code = "MACHINE_STATE_CONFLICT";
|
|
3
|
+
constructor(key) {
|
|
4
|
+
super(`machine state for ${key} changed since it was read`);
|
|
5
|
+
this.name = "MachineStateConflict";
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
/** Machine state in memory. Values are copied in and out, so a caller never aliases the store. */
|
|
9
|
+
export class MemoryMachineState {
|
|
10
|
+
entries = new Map();
|
|
11
|
+
counter = 0;
|
|
12
|
+
async read(key) {
|
|
13
|
+
const entry = this.entries.get(key);
|
|
14
|
+
return entry ? { state: JSON.parse(entry.json), version: entry.version } : null;
|
|
15
|
+
}
|
|
16
|
+
async write(key, state, expected) {
|
|
17
|
+
const current = this.entries.get(key)?.version ?? null;
|
|
18
|
+
if (current !== expected)
|
|
19
|
+
throw new MachineStateConflict(key);
|
|
20
|
+
const version = String(++this.counter);
|
|
21
|
+
this.entries.set(key, { json: JSON.stringify(state), version });
|
|
22
|
+
return version;
|
|
23
|
+
}
|
|
24
|
+
/** Every key stored. */
|
|
25
|
+
keys() {
|
|
26
|
+
return [...this.entries.keys()].sort();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const record = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30
|
+
/** Whether a stored value has the shape the engine writes. */
|
|
31
|
+
const isEntry = (entry) => record(entry) && record(entry.after) && typeof entry.digest === "string"
|
|
32
|
+
&& Number.isInteger(entry.missing) && typeof entry.seen_at === "string";
|
|
33
|
+
export function isSourceState(value) {
|
|
34
|
+
if (!record(value) || value.v !== 1 || typeof value.open !== "boolean" || !record(value.records))
|
|
35
|
+
return false;
|
|
36
|
+
if (!record(value.profile) || typeof value.profile.id !== "string" || !Number.isInteger(value.profile.version))
|
|
37
|
+
return false;
|
|
38
|
+
if (!Number.isInteger(value.complete_observations))
|
|
39
|
+
return false;
|
|
40
|
+
if (value.validators !== undefined && !record(value.validators))
|
|
41
|
+
return false;
|
|
42
|
+
if (value.pending !== undefined && !(record(value.pending) && Object.entries(value.pending).every(([id, pending]) => record(pending)
|
|
43
|
+
&& isEntry(pending.entry) && typeof pending.held_at === "string" && record(pending.change) && pending.change.external_id === id
|
|
44
|
+
&& typeof pending.change.change_kind === "string")))
|
|
45
|
+
return false;
|
|
46
|
+
return Object.values(value.records).every(isEntry);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=machine-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-state.js","sourceRoot":"","sources":["../../src/source-engine/machine-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ObserveSourceOptions, SourceRunReceipt } from "./types.js";
|
|
2
|
+
/** Complete observations without a record before it is `disappeared`, when the feed names none. */
|
|
3
|
+
export declare const DEFAULT_MISSING_THRESHOLD = 2;
|
|
4
|
+
/** The largest stored cursor, as canonical JSON characters. */
|
|
5
|
+
export declare const MAX_CURSOR_CHARS = 8192;
|
|
6
|
+
/**
|
|
7
|
+
* Replays of a pending change whose commit threw, after which the change is dropped with a finding:
|
|
8
|
+
* the record is planned again when it is next observed.
|
|
9
|
+
*/
|
|
10
|
+
export declare const MAX_REPLAY_FAILURES = 5;
|
|
11
|
+
/** Thrown by a profile that cannot read a provider's body; the run ends `unsupported_content`. */
|
|
12
|
+
export declare function unsupportedContent(detail: string): never;
|
|
13
|
+
/**
|
|
14
|
+
* Run one observation of a bound Source Feed. Returns a receipt; never throws for a provider,
|
|
15
|
+
* profile, guard or commit problem, which all end the run with an outcome and a finding.
|
|
16
|
+
*/
|
|
17
|
+
export declare function observeSource<Spec, Cursor>(options: ObserveSourceOptions<Spec, Cursor>): Promise<SourceRunReceipt>;
|
|
18
|
+
//# sourceMappingURL=observe.d.ts.map
|