@the-open-engine/zeroshot 6.29.0 → 6.30.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/CHANGELOG.md +4 -0
- package/cli/index.js +2 -4
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +0 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/agent-cli-provider/contract-actions.d.ts +1 -1
- package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-actions.js +5 -5
- package/lib/agent-cli-provider/contract-actions.js.map +1 -1
- package/lib/agent-cli-provider/contract-invoke.d.ts +1 -1
- package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-invoke.js +2 -2
- package/lib/agent-cli-provider/contract-invoke.js.map +1 -1
- package/lib/agent-cli-provider/contract-support.d.ts +1 -1
- package/lib/agent-cli-provider/contract-support.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract-support.js +2 -2
- package/lib/agent-cli-provider/contract-support.js.map +1 -1
- package/lib/agent-cli-provider/contract.d.ts +1 -0
- package/lib/agent-cli-provider/contract.d.ts.map +1 -1
- package/lib/agent-cli-provider/contract.js +1 -1
- package/lib/agent-cli-provider/contract.js.map +1 -1
- package/lib/agent-cli-provider/index.d.ts +1 -1
- package/lib/agent-cli-provider/index.d.ts.map +1 -1
- package/lib/agent-cli-provider/index.js +2 -1
- package/lib/agent-cli-provider/index.js.map +1 -1
- package/lib/agent-cli-provider/provider-registry.d.ts +1 -0
- package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
- package/lib/agent-cli-provider/provider-registry.js +4 -0
- package/lib/agent-cli-provider/provider-registry.js.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.d.ts +3 -3
- package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -1
- package/lib/agent-cli-provider/single-agent-runtime.js +22 -48
- package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -1
- package/lib/cluster/client.cjs +30 -7
- package/lib/cluster/client.d.cts +52 -0
- package/lib/cluster/client.d.mts +52 -0
- package/lib/cluster/client.d.ts +4 -6
- package/lib/cluster/client.mjs +32 -9
- package/lib/cluster/connection-state.cjs +25 -0
- package/lib/cluster/connection-state.d.cts +13 -0
- package/lib/cluster/connection-state.d.mts +13 -0
- package/lib/cluster/connection-state.d.ts +13 -0
- package/lib/cluster/connection-state.mjs +21 -0
- package/lib/{target/hosted-run/contracts.js → cluster/connection-types.cjs} +0 -1
- package/lib/cluster/connection-types.d.cts +33 -0
- package/lib/cluster/connection-types.d.mts +33 -0
- package/lib/cluster/connection-types.d.ts +33 -0
- package/lib/cluster/connection-types.mjs +1 -0
- package/lib/cluster/connection.cjs +18 -46
- package/lib/cluster/connection.d.cts +26 -0
- package/lib/cluster/connection.d.mts +26 -0
- package/lib/cluster/connection.d.ts +7 -25
- package/lib/cluster/connection.mjs +12 -42
- package/lib/cluster/errors.cjs +9 -1
- package/lib/cluster/errors.d.cts +29 -0
- package/lib/cluster/errors.d.mts +29 -0
- package/lib/cluster/errors.d.ts +4 -0
- package/lib/cluster/errors.mjs +7 -0
- package/lib/cluster/frames.d.cts +12 -0
- package/lib/cluster/frames.d.mts +12 -0
- package/lib/cluster/generated/protocol-schema.d.cts +1 -0
- package/lib/cluster/generated/protocol-schema.d.mts +1 -0
- package/lib/cluster/generated/protocol.d.cts +781 -0
- package/lib/cluster/generated/protocol.d.mts +781 -0
- package/lib/cluster/index.cjs +2 -2
- package/lib/cluster/index.d.cts +13 -0
- package/lib/cluster/index.d.mts +13 -0
- package/lib/cluster/index.d.ts +3 -3
- package/lib/cluster/index.mjs +2 -2
- package/lib/cluster/json-source.cjs +1 -0
- package/lib/cluster/json-source.d.cts +5 -0
- package/lib/cluster/json-source.d.mts +5 -0
- package/lib/cluster/json-source.d.ts +1 -0
- package/lib/cluster/json-source.mjs +1 -0
- package/lib/cluster/payload-value.cjs +1 -0
- package/lib/cluster/payload-value.d.cts +8 -0
- package/lib/cluster/payload-value.d.mts +8 -0
- package/lib/cluster/payload-value.d.ts +1 -0
- package/lib/cluster/payload-value.mjs +1 -0
- package/lib/cluster/queue.d.cts +15 -0
- package/lib/cluster/queue.d.mts +15 -0
- package/lib/cluster/socket.cjs +8 -0
- package/lib/cluster/socket.d.cts +13 -0
- package/lib/cluster/socket.d.mts +13 -0
- package/lib/cluster/socket.d.ts +2 -0
- package/lib/cluster/socket.mjs +7 -0
- package/lib/cluster/subscriptions.d.cts +73 -0
- package/lib/cluster/subscriptions.d.mts +73 -0
- package/lib/cluster/subscriptions.d.ts +5 -1
- package/lib/cluster/validators.cjs +1 -0
- package/lib/cluster/validators.d.cts +7 -0
- package/lib/cluster/validators.d.mts +7 -0
- package/lib/cluster/validators.d.ts +1 -0
- package/lib/cluster/validators.mjs +1 -0
- package/lib/cluster-worker/engine-adapter-common.js +37 -0
- package/lib/cluster-worker/engine-adapter.js +24 -30
- package/lib/cluster-worker/engine-start.js +59 -0
- package/lib/cluster-worker/index.js +49 -67
- package/lib/cluster-worker/profiles.js +1 -42
- package/lib/cluster-worker/runtime-dependencies.js +49 -0
- package/lib/cluster-worker/runtime-support.js +2 -34
- package/lib/cluster-worker/terminal-normalizer.js +9 -10
- package/lib/hosted-session/authority.cjs +61 -0
- package/lib/hosted-session/authority.d.cts +3 -0
- package/lib/hosted-session/authority.d.mts +3 -0
- package/lib/hosted-session/authority.d.ts +3 -0
- package/lib/hosted-session/authority.mjs +57 -0
- package/lib/hosted-session/coordinator.cjs +78 -51
- package/lib/hosted-session/coordinator.d.cts +11 -0
- package/lib/hosted-session/coordinator.d.mts +11 -0
- package/lib/hosted-session/coordinator.d.ts +4 -2
- package/lib/hosted-session/coordinator.mjs +75 -51
- package/lib/hosted-session/errors.cjs +25 -0
- package/lib/hosted-session/errors.d.cts +10 -0
- package/lib/hosted-session/errors.d.mts +10 -0
- package/lib/hosted-session/errors.d.ts +10 -0
- package/lib/hosted-session/errors.mjs +19 -0
- package/lib/hosted-session/index.cjs +4 -1
- package/lib/hosted-session/index.d.cts +2 -0
- package/lib/hosted-session/index.d.mts +2 -0
- package/lib/hosted-session/index.d.ts +2 -2
- package/lib/hosted-session/index.mjs +1 -1
- package/lib/hosted-session/reconnecting-watch.cjs +131 -0
- package/lib/hosted-session/reconnecting-watch.d.cts +13 -0
- package/lib/hosted-session/reconnecting-watch.d.mts +13 -0
- package/lib/hosted-session/reconnecting-watch.d.ts +13 -0
- package/lib/hosted-session/reconnecting-watch.mjs +127 -0
- package/lib/hosted-session/types.d.cts +32 -0
- package/lib/hosted-session/types.d.mts +32 -0
- package/lib/hosted-session/types.d.ts +19 -7
- package/lib/hosted-target/access-url.cjs +44 -0
- package/lib/hosted-target/access-url.d.cts +2 -0
- package/lib/hosted-target/access-url.d.mts +2 -0
- package/lib/hosted-target/access-url.d.ts +2 -0
- package/lib/hosted-target/access-url.mjs +41 -0
- package/lib/hosted-target/adapter-request.cjs +12 -0
- package/lib/hosted-target/adapter-request.d.cts +17 -0
- package/lib/hosted-target/adapter-request.d.mts +17 -0
- package/lib/hosted-target/adapter-request.d.ts +17 -0
- package/lib/hosted-target/adapter-request.mjs +9 -0
- package/lib/hosted-target/adapter-types.cjs +2 -0
- package/lib/hosted-target/adapter-types.d.cts +27 -0
- package/lib/hosted-target/adapter-types.d.mts +27 -0
- package/lib/hosted-target/adapter-types.d.ts +27 -0
- package/lib/hosted-target/adapter-types.mjs +1 -0
- package/lib/hosted-target/bounds.cjs +10 -0
- package/lib/hosted-target/bounds.d.cts +7 -0
- package/lib/hosted-target/bounds.d.mts +7 -0
- package/lib/hosted-target/bounds.d.ts +7 -0
- package/lib/hosted-target/bounds.mjs +7 -0
- package/lib/hosted-target/capsule-error-response.cjs +76 -0
- package/lib/hosted-target/capsule-error-response.d.cts +2 -0
- package/lib/hosted-target/capsule-error-response.d.mts +2 -0
- package/lib/hosted-target/capsule-error-response.d.ts +2 -0
- package/lib/hosted-target/capsule-error-response.mjs +73 -0
- package/lib/hosted-target/errors.cjs +88 -0
- package/lib/hosted-target/errors.d.cts +36 -0
- package/lib/hosted-target/errors.d.mts +36 -0
- package/lib/hosted-target/errors.d.ts +36 -0
- package/lib/hosted-target/errors.mjs +75 -0
- package/lib/hosted-target/index.cjs +16 -0
- package/lib/hosted-target/index.d.cts +3 -0
- package/lib/hosted-target/index.d.mts +3 -0
- package/lib/hosted-target/index.d.ts +3 -0
- package/lib/hosted-target/index.mjs +2 -0
- package/lib/hosted-target/response-validation.cjs +169 -0
- package/lib/hosted-target/response-validation.d.cts +5 -0
- package/lib/hosted-target/response-validation.d.mts +5 -0
- package/lib/hosted-target/response-validation.d.ts +5 -0
- package/lib/hosted-target/response-validation.mjs +163 -0
- package/lib/hosted-target/retry-executor.cjs +51 -0
- package/lib/hosted-target/retry-executor.d.cts +8 -0
- package/lib/hosted-target/retry-executor.d.mts +8 -0
- package/lib/hosted-target/retry-executor.d.ts +8 -0
- package/lib/hosted-target/retry-executor.mjs +48 -0
- package/lib/hosted-target/retry.cjs +78 -0
- package/lib/hosted-target/retry.d.cts +9 -0
- package/lib/hosted-target/retry.d.mts +9 -0
- package/lib/hosted-target/retry.d.ts +9 -0
- package/lib/hosted-target/retry.mjs +73 -0
- package/lib/hosted-target/target-adapter.cjs +10 -0
- package/lib/hosted-target/target-adapter.d.cts +3 -0
- package/lib/hosted-target/target-adapter.d.mts +3 -0
- package/lib/hosted-target/target-adapter.d.ts +3 -0
- package/lib/hosted-target/target-adapter.mjs +7 -0
- package/lib/hosted-target/types.cjs +4 -0
- package/lib/hosted-target/types.d.cts +50 -0
- package/lib/hosted-target/types.d.mts +50 -0
- package/lib/hosted-target/types.d.ts +50 -0
- package/lib/hosted-target/types.mjs +1 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.cjs +185 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +13 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +13 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +13 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.mjs +181 -0
- package/lib/start-cluster.js +3 -3
- package/lib/target/bounded-response.cjs +51 -0
- package/lib/target/bounded-response.d.cts +1 -0
- package/lib/target/bounded-response.d.mts +1 -0
- package/lib/target/bounded-response.d.ts +1 -0
- package/lib/target/bounded-response.js +51 -0
- package/lib/target/bounded-response.mjs +48 -0
- package/lib/target/credential-lock.js +1 -3
- package/lib/target/credential-store.js +9 -4
- package/lib/target/device-flow.cjs +213 -0
- package/lib/target/device-flow.d.cts +54 -0
- package/lib/target/device-flow.d.mts +54 -0
- package/lib/target/device-flow.d.ts +26 -14
- package/lib/target/device-flow.js +162 -58
- package/lib/target/device-flow.mjs +203 -0
- package/lib/target/discovery-errors.cjs +10 -0
- package/lib/target/discovery-errors.d.cts +3 -0
- package/lib/target/discovery-errors.d.mts +3 -0
- package/lib/target/discovery-errors.d.ts +3 -0
- package/lib/target/discovery-errors.js +10 -0
- package/lib/target/discovery-errors.mjs +6 -0
- package/lib/target/discovery-sections.cjs +191 -0
- package/lib/target/discovery-sections.d.cts +52 -0
- package/lib/target/discovery-sections.d.mts +52 -0
- package/lib/target/discovery-sections.d.ts +52 -0
- package/lib/target/discovery-sections.js +191 -0
- package/lib/target/discovery-sections.mjs +179 -0
- package/lib/target/discovery-validation.cjs +109 -0
- package/lib/target/discovery-validation.d.cts +28 -0
- package/lib/target/discovery-validation.d.mts +28 -0
- package/lib/target/discovery-validation.d.ts +28 -0
- package/lib/target/discovery-validation.js +109 -0
- package/lib/target/discovery-validation.mjs +99 -0
- package/lib/target/discovery.cjs +112 -0
- package/lib/target/discovery.d.cts +74 -0
- package/lib/target/discovery.d.mts +74 -0
- package/lib/target/discovery.d.ts +67 -5
- package/lib/target/discovery.js +94 -79
- package/lib/target/discovery.mjs +105 -0
- package/lib/target/index.d.ts +6 -6
- package/lib/target/index.js +36 -36
- package/lib/target/oauth-http.d.ts +2 -0
- package/lib/target/oauth-http.js +25 -0
- package/lib/target/refresh-exchange.d.ts +11 -0
- package/lib/target/refresh-exchange.js +24 -0
- package/lib/target/refresh-revocation.d.ts +8 -0
- package/lib/target/refresh-revocation.js +19 -0
- package/lib/target/route-template.cjs +85 -0
- package/lib/target/route-template.d.cts +7 -0
- package/lib/target/route-template.d.mts +7 -0
- package/lib/target/route-template.d.ts +7 -0
- package/lib/target/route-template.js +85 -0
- package/lib/target/route-template.mjs +81 -0
- package/lib/target/session-errors.d.ts +4 -0
- package/lib/target/session-errors.js +12 -0
- package/lib/target/session-verification.d.ts +10 -0
- package/lib/target/session-verification.js +42 -0
- package/lib/target/target-registry.d.ts +7 -3
- package/lib/target/target-registry.js +41 -10
- package/lib/target/target-session-manager.d.ts +48 -0
- package/lib/target/target-session-manager.js +226 -0
- package/lib/target/target-session.d.ts +39 -32
- package/lib/target/target-session.js +63 -151
- package/lib/target/token-response.cjs +51 -0
- package/lib/target/token-response.d.cts +7 -0
- package/lib/target/token-response.d.mts +7 -0
- package/lib/target/token-response.d.ts +7 -0
- package/lib/target/token-response.js +51 -0
- package/lib/target/token-response.mjs +48 -0
- package/package.json +14 -7
- package/protocol/openengine-cluster/v1/worker.schema.json +171 -9
- package/scripts/build-cluster.js +23 -3
- package/scripts/opcore-introduced-check.js +0 -2
- package/src/agent-cli-provider/adapters/codex.ts +0 -1
- package/src/agent-cli-provider/contract-actions.ts +9 -5
- package/src/agent-cli-provider/contract-invoke.ts +3 -2
- package/src/agent-cli-provider/contract-support.ts +12 -6
- package/src/agent-cli-provider/contract.ts +6 -1
- package/src/agent-cli-provider/index.ts +1 -0
- package/src/agent-cli-provider/provider-registry.ts +4 -0
- package/src/agent-cli-provider/single-agent-runtime.ts +32 -45
- package/src/cluster/client.ts +42 -15
- package/src/cluster/connection-state.ts +33 -0
- package/src/cluster/connection-types.ts +28 -0
- package/src/cluster/connection.ts +37 -68
- package/src/cluster/errors.ts +5 -0
- package/src/cluster/index.ts +3 -1
- package/src/cluster/json-source.ts +1 -0
- package/src/cluster/payload-value.ts +1 -0
- package/src/cluster/socket.ts +13 -0
- package/src/cluster/subscriptions.ts +7 -2
- package/src/cluster/validators.ts +1 -0
- package/src/cluster/ws.d.ts +1 -1
- package/src/hosted-session/authority.ts +77 -0
- package/src/hosted-session/coordinator.ts +113 -56
- package/src/hosted-session/errors.ts +21 -0
- package/src/hosted-session/index.ts +14 -2
- package/src/hosted-session/reconnecting-watch.ts +148 -0
- package/src/hosted-session/types.ts +22 -8
- package/src/hosted-target/access-url.ts +46 -0
- package/src/hosted-target/adapter-request.ts +28 -0
- package/src/hosted-target/adapter-types.ts +39 -0
- package/src/hosted-target/bounds.ts +1 -0
- package/src/hosted-target/capsule-error-response.ts +107 -0
- package/src/hosted-target/errors.ts +36 -35
- package/src/hosted-target/index.ts +10 -23
- package/src/hosted-target/response-validation.ts +170 -62
- package/src/hosted-target/retry-executor.ts +62 -0
- package/src/hosted-target/retry.ts +47 -11
- package/src/hosted-target/target-adapter.ts +12 -8
- package/src/hosted-target/types.ts +19 -18
- package/src/hosted-target/zero-cloud-v1-adapter.ts +229 -316
- package/src/isolation-manager.js +1 -16
- package/src/target/bounded-response.ts +68 -0
- package/src/target/credential-lock.ts +1 -3
- package/src/target/credential-store.ts +14 -10
- package/src/target/device-flow.ts +209 -85
- package/src/target/discovery-errors.ts +6 -0
- package/src/target/discovery-sections.ts +251 -0
- package/src/target/discovery-validation.ts +144 -0
- package/src/target/discovery.ts +163 -97
- package/src/target/index.ts +15 -11
- package/src/target/oauth-http.ts +27 -0
- package/src/target/refresh-exchange.ts +36 -0
- package/src/target/refresh-revocation.ts +29 -0
- package/src/target/route-template.ts +105 -0
- package/src/target/session-errors.ts +9 -0
- package/src/target/session-verification.ts +51 -0
- package/src/target/target-registry.ts +60 -27
- package/src/target/target-session-manager.ts +285 -0
- package/src/target/target-session.ts +105 -226
- package/src/target/token-response.ts +62 -0
- package/docker/zeroshot-oecp/Cargo.toml +0 -12
- package/docker/zeroshot-oecp/Dockerfile +0 -65
- package/docker/zeroshot-oecp/src/main.rs +0 -32
- package/lib/target/bounded-json.d.ts +0 -6
- package/lib/target/bounded-json.js +0 -43
- package/lib/target/hosted-run/client.d.ts +0 -26
- package/lib/target/hosted-run/client.js +0 -158
- package/lib/target/hosted-run/commands.d.ts +0 -4
- package/lib/target/hosted-run/commands.js +0 -113
- package/lib/target/hosted-run/contracts.d.ts +0 -49
- package/lib/target/hosted-run/input.d.ts +0 -5
- package/lib/target/hosted-run/input.js +0 -200
- package/lib/target/hosted-run.d.ts +0 -4
- package/lib/target/hosted-run.js +0 -12
- package/src/target/bounded-json.ts +0 -48
- package/src/target/hosted-run/client.ts +0 -198
- package/src/target/hosted-run/commands.ts +0 -140
- package/src/target/hosted-run/contracts.ts +0 -53
- package/src/target/hosted-run/input.ts +0 -199
- package/src/target/hosted-run.ts +0 -8
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertCapsule = assertCapsule;
|
|
4
|
+
exports.assertCapsuleAccess = assertCapsuleAccess;
|
|
5
|
+
exports.assertCapsuleLimits = assertCapsuleLimits;
|
|
6
|
+
exports.assertCapsuleListPage = assertCapsuleListPage;
|
|
7
|
+
const errors_js_1 = require("./errors.cjs");
|
|
8
|
+
const types_js_1 = require("./types.cjs");
|
|
9
|
+
function closedObject(body, fields, context) {
|
|
10
|
+
if (body === null || typeof body !== 'object' || Array.isArray(body)) {
|
|
11
|
+
throw new errors_js_1.TargetProtocolError(`${context} response is malformed`);
|
|
12
|
+
}
|
|
13
|
+
const record = body;
|
|
14
|
+
if (Object.keys(record).length !== fields.length || fields.some((field) => !(field in record))) {
|
|
15
|
+
throw new errors_js_1.TargetProtocolError(`${context} response is malformed`);
|
|
16
|
+
}
|
|
17
|
+
return record;
|
|
18
|
+
}
|
|
19
|
+
function nonempty(value) {
|
|
20
|
+
return typeof value === 'string' && value.length > 0;
|
|
21
|
+
}
|
|
22
|
+
function decimal(value, length) {
|
|
23
|
+
if (value.length !== length)
|
|
24
|
+
return null;
|
|
25
|
+
for (const character of value) {
|
|
26
|
+
if (character < '0' || character > '9')
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return Number(value);
|
|
30
|
+
}
|
|
31
|
+
function parseDate(value) {
|
|
32
|
+
const fields = value.split('-');
|
|
33
|
+
if (fields.length !== 3)
|
|
34
|
+
return null;
|
|
35
|
+
const year = decimal(fields[0] ?? '', 4);
|
|
36
|
+
const month = decimal(fields[1] ?? '', 2);
|
|
37
|
+
const day = decimal(fields[2] ?? '', 2);
|
|
38
|
+
if (year === null || month === null || day === null)
|
|
39
|
+
return null;
|
|
40
|
+
return { year, month, day };
|
|
41
|
+
}
|
|
42
|
+
function parseZone(value) {
|
|
43
|
+
if (value.endsWith('Z')) {
|
|
44
|
+
return { clock: value.slice(0, -1), offsetHour: 0, offsetMinute: 0 };
|
|
45
|
+
}
|
|
46
|
+
const marker = value.at(-6);
|
|
47
|
+
if ((marker !== '+' && marker !== '-') || value.at(-3) !== ':')
|
|
48
|
+
return null;
|
|
49
|
+
const offsetHour = decimal(value.slice(-5, -3), 2);
|
|
50
|
+
const offsetMinute = decimal(value.slice(-2), 2);
|
|
51
|
+
if (offsetHour === null || offsetMinute === null)
|
|
52
|
+
return null;
|
|
53
|
+
return { clock: value.slice(0, -6), offsetHour, offsetMinute };
|
|
54
|
+
}
|
|
55
|
+
function parseFractionalClock(value) {
|
|
56
|
+
const fields = value.split('.');
|
|
57
|
+
if (fields.length > 2)
|
|
58
|
+
return null;
|
|
59
|
+
const fraction = fields[1];
|
|
60
|
+
if (fraction !== undefined &&
|
|
61
|
+
(fraction.length === 0 || decimal(fraction, fraction.length) === null)) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return fields[0] ?? null;
|
|
65
|
+
}
|
|
66
|
+
function parseHms(value) {
|
|
67
|
+
const fields = value.split(':');
|
|
68
|
+
if (fields.length !== 3)
|
|
69
|
+
return null;
|
|
70
|
+
const hour = decimal(fields[0] ?? '', 2);
|
|
71
|
+
const minute = decimal(fields[1] ?? '', 2);
|
|
72
|
+
const second = decimal(fields[2] ?? '', 2);
|
|
73
|
+
return hour === null || minute === null || second === null ? null : { hour, minute, second };
|
|
74
|
+
}
|
|
75
|
+
function parseClock(value) {
|
|
76
|
+
const zone = parseZone(value);
|
|
77
|
+
if (zone === null)
|
|
78
|
+
return null;
|
|
79
|
+
const clock = parseFractionalClock(zone.clock);
|
|
80
|
+
if (clock === null)
|
|
81
|
+
return null;
|
|
82
|
+
const parts = parseHms(clock);
|
|
83
|
+
if (parts === null)
|
|
84
|
+
return null;
|
|
85
|
+
return { ...parts, offsetHour: zone.offsetHour, offsetMinute: zone.offsetMinute };
|
|
86
|
+
}
|
|
87
|
+
function parseTimestamp(value) {
|
|
88
|
+
if (value.at(10) !== 'T')
|
|
89
|
+
return null;
|
|
90
|
+
const date = parseDate(value.slice(0, 10));
|
|
91
|
+
const clock = parseClock(value.slice(11));
|
|
92
|
+
return date === null || clock === null ? null : { ...date, ...clock };
|
|
93
|
+
}
|
|
94
|
+
function validClock(parts) {
|
|
95
|
+
return parts.hour <= 23 && parts.minute <= 59 && parts.second <= 59 &&
|
|
96
|
+
parts.offsetHour <= 23 && parts.offsetMinute <= 59;
|
|
97
|
+
}
|
|
98
|
+
function validCalendar(parts) {
|
|
99
|
+
if (parts.month < 1 || parts.month > 12)
|
|
100
|
+
return false;
|
|
101
|
+
const leap = parts.year % 4 === 0 && (parts.year % 100 !== 0 || parts.year % 400 === 0);
|
|
102
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
103
|
+
return parts.day >= 1 && parts.day <= (days[parts.month - 1] ?? 0);
|
|
104
|
+
}
|
|
105
|
+
function timestamp(value) {
|
|
106
|
+
if (!nonempty(value))
|
|
107
|
+
return false;
|
|
108
|
+
const parts = parseTimestamp(value);
|
|
109
|
+
return parts !== null &&
|
|
110
|
+
validClock(parts) &&
|
|
111
|
+
validCalendar(parts) &&
|
|
112
|
+
Number.isFinite(Date.parse(value));
|
|
113
|
+
}
|
|
114
|
+
function uint(value) {
|
|
115
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
116
|
+
}
|
|
117
|
+
function assertCapsule(body) {
|
|
118
|
+
const value = closedObject(body, ['capsule_id', 'state', 'label', 'created_at'], 'Capsule');
|
|
119
|
+
if (!nonempty(value.capsule_id) ||
|
|
120
|
+
typeof value.state !== 'string' ||
|
|
121
|
+
!types_js_1.KNOWN_CAPSULE_STATES.includes(value.state) ||
|
|
122
|
+
(value.label !== null && typeof value.label !== 'string') ||
|
|
123
|
+
!timestamp(value.created_at)) {
|
|
124
|
+
throw new errors_js_1.TargetProtocolError('Capsule response is malformed');
|
|
125
|
+
}
|
|
126
|
+
return Object.freeze({
|
|
127
|
+
id: value.capsule_id,
|
|
128
|
+
state: value.state,
|
|
129
|
+
label: value.label,
|
|
130
|
+
createdAt: value.created_at,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function assertCapsuleAccess(body) {
|
|
134
|
+
const value = closedObject(body, ['protocol', 'websocket_url', 'access_token', 'token_type', 'expires_at'], 'CapsuleAccess');
|
|
135
|
+
if (value.protocol !== 'openengine.cluster/v1' ||
|
|
136
|
+
!nonempty(value.websocket_url) ||
|
|
137
|
+
!nonempty(value.access_token) ||
|
|
138
|
+
value.token_type !== 'Bearer' ||
|
|
139
|
+
!timestamp(value.expires_at)) {
|
|
140
|
+
throw new errors_js_1.TargetProtocolError('CapsuleAccess response is malformed');
|
|
141
|
+
}
|
|
142
|
+
return Object.freeze({
|
|
143
|
+
protocol: 'openengine.cluster/v1',
|
|
144
|
+
websocketUrl: value.websocket_url,
|
|
145
|
+
accessToken: value.access_token,
|
|
146
|
+
tokenType: 'Bearer',
|
|
147
|
+
expiresAt: value.expires_at,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function assertCapsuleLimits(body) {
|
|
151
|
+
const value = closedObject(body, ['active_capsules', 'max_active_capsules'], 'CapsuleLimits');
|
|
152
|
+
if (!uint(value.active_capsules) || (value.max_active_capsules !== null && !uint(value.max_active_capsules))) {
|
|
153
|
+
throw new errors_js_1.TargetProtocolError('CapsuleLimits response is malformed');
|
|
154
|
+
}
|
|
155
|
+
return Object.freeze({
|
|
156
|
+
activeCapsules: value.active_capsules,
|
|
157
|
+
maxActiveCapsules: value.max_active_capsules,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function assertCapsuleListPage(body) {
|
|
161
|
+
const value = closedObject(body, ['capsules', 'next_cursor'], 'CapsulePage');
|
|
162
|
+
if (!Array.isArray(value.capsules) || (value.next_cursor !== null && typeof value.next_cursor !== 'string')) {
|
|
163
|
+
throw new errors_js_1.TargetProtocolError('CapsulePage response is malformed');
|
|
164
|
+
}
|
|
165
|
+
return Object.freeze({
|
|
166
|
+
capsules: Object.freeze(value.capsules.map((item) => assertCapsule(item))),
|
|
167
|
+
nextCursor: value.next_cursor,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage } from './types.js';
|
|
2
|
+
export declare function assertCapsule(body: unknown): Capsule;
|
|
3
|
+
export declare function assertCapsuleAccess(body: unknown): CapsuleAccess;
|
|
4
|
+
export declare function assertCapsuleLimits(body: unknown): CapsuleLimits;
|
|
5
|
+
export declare function assertCapsuleListPage(body: unknown): CapsuleListPage;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage } from './types.js';
|
|
2
|
+
export declare function assertCapsule(body: unknown): Capsule;
|
|
3
|
+
export declare function assertCapsuleAccess(body: unknown): CapsuleAccess;
|
|
4
|
+
export declare function assertCapsuleLimits(body: unknown): CapsuleLimits;
|
|
5
|
+
export declare function assertCapsuleListPage(body: unknown): CapsuleListPage;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Capsule, CapsuleAccess, CapsuleLimits, CapsuleListPage } from './types.js';
|
|
2
|
+
export declare function assertCapsule(body: unknown): Capsule;
|
|
3
|
+
export declare function assertCapsuleAccess(body: unknown): CapsuleAccess;
|
|
4
|
+
export declare function assertCapsuleLimits(body: unknown): CapsuleLimits;
|
|
5
|
+
export declare function assertCapsuleListPage(body: unknown): CapsuleListPage;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { TargetProtocolError } from './errors.mjs';
|
|
2
|
+
import { KNOWN_CAPSULE_STATES } from './types.mjs';
|
|
3
|
+
function closedObject(body, fields, context) {
|
|
4
|
+
if (body === null || typeof body !== 'object' || Array.isArray(body)) {
|
|
5
|
+
throw new TargetProtocolError(`${context} response is malformed`);
|
|
6
|
+
}
|
|
7
|
+
const record = body;
|
|
8
|
+
if (Object.keys(record).length !== fields.length || fields.some((field) => !(field in record))) {
|
|
9
|
+
throw new TargetProtocolError(`${context} response is malformed`);
|
|
10
|
+
}
|
|
11
|
+
return record;
|
|
12
|
+
}
|
|
13
|
+
function nonempty(value) {
|
|
14
|
+
return typeof value === 'string' && value.length > 0;
|
|
15
|
+
}
|
|
16
|
+
function decimal(value, length) {
|
|
17
|
+
if (value.length !== length)
|
|
18
|
+
return null;
|
|
19
|
+
for (const character of value) {
|
|
20
|
+
if (character < '0' || character > '9')
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return Number(value);
|
|
24
|
+
}
|
|
25
|
+
function parseDate(value) {
|
|
26
|
+
const fields = value.split('-');
|
|
27
|
+
if (fields.length !== 3)
|
|
28
|
+
return null;
|
|
29
|
+
const year = decimal(fields[0] ?? '', 4);
|
|
30
|
+
const month = decimal(fields[1] ?? '', 2);
|
|
31
|
+
const day = decimal(fields[2] ?? '', 2);
|
|
32
|
+
if (year === null || month === null || day === null)
|
|
33
|
+
return null;
|
|
34
|
+
return { year, month, day };
|
|
35
|
+
}
|
|
36
|
+
function parseZone(value) {
|
|
37
|
+
if (value.endsWith('Z')) {
|
|
38
|
+
return { clock: value.slice(0, -1), offsetHour: 0, offsetMinute: 0 };
|
|
39
|
+
}
|
|
40
|
+
const marker = value.at(-6);
|
|
41
|
+
if ((marker !== '+' && marker !== '-') || value.at(-3) !== ':')
|
|
42
|
+
return null;
|
|
43
|
+
const offsetHour = decimal(value.slice(-5, -3), 2);
|
|
44
|
+
const offsetMinute = decimal(value.slice(-2), 2);
|
|
45
|
+
if (offsetHour === null || offsetMinute === null)
|
|
46
|
+
return null;
|
|
47
|
+
return { clock: value.slice(0, -6), offsetHour, offsetMinute };
|
|
48
|
+
}
|
|
49
|
+
function parseFractionalClock(value) {
|
|
50
|
+
const fields = value.split('.');
|
|
51
|
+
if (fields.length > 2)
|
|
52
|
+
return null;
|
|
53
|
+
const fraction = fields[1];
|
|
54
|
+
if (fraction !== undefined &&
|
|
55
|
+
(fraction.length === 0 || decimal(fraction, fraction.length) === null)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return fields[0] ?? null;
|
|
59
|
+
}
|
|
60
|
+
function parseHms(value) {
|
|
61
|
+
const fields = value.split(':');
|
|
62
|
+
if (fields.length !== 3)
|
|
63
|
+
return null;
|
|
64
|
+
const hour = decimal(fields[0] ?? '', 2);
|
|
65
|
+
const minute = decimal(fields[1] ?? '', 2);
|
|
66
|
+
const second = decimal(fields[2] ?? '', 2);
|
|
67
|
+
return hour === null || minute === null || second === null ? null : { hour, minute, second };
|
|
68
|
+
}
|
|
69
|
+
function parseClock(value) {
|
|
70
|
+
const zone = parseZone(value);
|
|
71
|
+
if (zone === null)
|
|
72
|
+
return null;
|
|
73
|
+
const clock = parseFractionalClock(zone.clock);
|
|
74
|
+
if (clock === null)
|
|
75
|
+
return null;
|
|
76
|
+
const parts = parseHms(clock);
|
|
77
|
+
if (parts === null)
|
|
78
|
+
return null;
|
|
79
|
+
return { ...parts, offsetHour: zone.offsetHour, offsetMinute: zone.offsetMinute };
|
|
80
|
+
}
|
|
81
|
+
function parseTimestamp(value) {
|
|
82
|
+
if (value.at(10) !== 'T')
|
|
83
|
+
return null;
|
|
84
|
+
const date = parseDate(value.slice(0, 10));
|
|
85
|
+
const clock = parseClock(value.slice(11));
|
|
86
|
+
return date === null || clock === null ? null : { ...date, ...clock };
|
|
87
|
+
}
|
|
88
|
+
function validClock(parts) {
|
|
89
|
+
return parts.hour <= 23 && parts.minute <= 59 && parts.second <= 59 &&
|
|
90
|
+
parts.offsetHour <= 23 && parts.offsetMinute <= 59;
|
|
91
|
+
}
|
|
92
|
+
function validCalendar(parts) {
|
|
93
|
+
if (parts.month < 1 || parts.month > 12)
|
|
94
|
+
return false;
|
|
95
|
+
const leap = parts.year % 4 === 0 && (parts.year % 100 !== 0 || parts.year % 400 === 0);
|
|
96
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
97
|
+
return parts.day >= 1 && parts.day <= (days[parts.month - 1] ?? 0);
|
|
98
|
+
}
|
|
99
|
+
function timestamp(value) {
|
|
100
|
+
if (!nonempty(value))
|
|
101
|
+
return false;
|
|
102
|
+
const parts = parseTimestamp(value);
|
|
103
|
+
return parts !== null &&
|
|
104
|
+
validClock(parts) &&
|
|
105
|
+
validCalendar(parts) &&
|
|
106
|
+
Number.isFinite(Date.parse(value));
|
|
107
|
+
}
|
|
108
|
+
function uint(value) {
|
|
109
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
110
|
+
}
|
|
111
|
+
export function assertCapsule(body) {
|
|
112
|
+
const value = closedObject(body, ['capsule_id', 'state', 'label', 'created_at'], 'Capsule');
|
|
113
|
+
if (!nonempty(value.capsule_id) ||
|
|
114
|
+
typeof value.state !== 'string' ||
|
|
115
|
+
!KNOWN_CAPSULE_STATES.includes(value.state) ||
|
|
116
|
+
(value.label !== null && typeof value.label !== 'string') ||
|
|
117
|
+
!timestamp(value.created_at)) {
|
|
118
|
+
throw new TargetProtocolError('Capsule response is malformed');
|
|
119
|
+
}
|
|
120
|
+
return Object.freeze({
|
|
121
|
+
id: value.capsule_id,
|
|
122
|
+
state: value.state,
|
|
123
|
+
label: value.label,
|
|
124
|
+
createdAt: value.created_at,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
export function assertCapsuleAccess(body) {
|
|
128
|
+
const value = closedObject(body, ['protocol', 'websocket_url', 'access_token', 'token_type', 'expires_at'], 'CapsuleAccess');
|
|
129
|
+
if (value.protocol !== 'openengine.cluster/v1' ||
|
|
130
|
+
!nonempty(value.websocket_url) ||
|
|
131
|
+
!nonempty(value.access_token) ||
|
|
132
|
+
value.token_type !== 'Bearer' ||
|
|
133
|
+
!timestamp(value.expires_at)) {
|
|
134
|
+
throw new TargetProtocolError('CapsuleAccess response is malformed');
|
|
135
|
+
}
|
|
136
|
+
return Object.freeze({
|
|
137
|
+
protocol: 'openengine.cluster/v1',
|
|
138
|
+
websocketUrl: value.websocket_url,
|
|
139
|
+
accessToken: value.access_token,
|
|
140
|
+
tokenType: 'Bearer',
|
|
141
|
+
expiresAt: value.expires_at,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
export function assertCapsuleLimits(body) {
|
|
145
|
+
const value = closedObject(body, ['active_capsules', 'max_active_capsules'], 'CapsuleLimits');
|
|
146
|
+
if (!uint(value.active_capsules) || (value.max_active_capsules !== null && !uint(value.max_active_capsules))) {
|
|
147
|
+
throw new TargetProtocolError('CapsuleLimits response is malformed');
|
|
148
|
+
}
|
|
149
|
+
return Object.freeze({
|
|
150
|
+
activeCapsules: value.active_capsules,
|
|
151
|
+
maxActiveCapsules: value.max_active_capsules,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
export function assertCapsuleListPage(body) {
|
|
155
|
+
const value = closedObject(body, ['capsules', 'next_cursor'], 'CapsulePage');
|
|
156
|
+
if (!Array.isArray(value.capsules) || (value.next_cursor !== null && typeof value.next_cursor !== 'string')) {
|
|
157
|
+
throw new TargetProtocolError('CapsulePage response is malformed');
|
|
158
|
+
}
|
|
159
|
+
return Object.freeze({
|
|
160
|
+
capsules: Object.freeze(value.capsules.map((item) => assertCapsule(item))),
|
|
161
|
+
nextCursor: value.next_cursor,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withTargetRetry = withTargetRetry;
|
|
4
|
+
const bounds_js_1 = require("./bounds.cjs");
|
|
5
|
+
const errors_js_1 = require("./errors.cjs");
|
|
6
|
+
function throwIfAborted(signal) {
|
|
7
|
+
if (signal?.aborted) {
|
|
8
|
+
throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
async function wait(delayMs, signal) {
|
|
12
|
+
throwIfAborted(signal);
|
|
13
|
+
if (delayMs <= 0)
|
|
14
|
+
return;
|
|
15
|
+
await new Promise((resolve, reject) => {
|
|
16
|
+
const timer = setTimeout(resolve, delayMs);
|
|
17
|
+
signal?.addEventListener('abort', () => {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
reject(signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError'));
|
|
20
|
+
}, { once: true });
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function retryableError(value) {
|
|
24
|
+
return value instanceof errors_js_1.TargetAdapterError && value.retryable;
|
|
25
|
+
}
|
|
26
|
+
function validRetryDelay(retry, delayMs, remaining) {
|
|
27
|
+
return retry && Number.isFinite(delayMs) && delayMs >= 0 && delayMs < remaining;
|
|
28
|
+
}
|
|
29
|
+
async function withTargetRetry(operation, effect, signal, context) {
|
|
30
|
+
const retrySafe = operation !== 'access';
|
|
31
|
+
const started = context.clock.now();
|
|
32
|
+
let attempt = 0;
|
|
33
|
+
while (true) {
|
|
34
|
+
throwIfAborted(signal);
|
|
35
|
+
try {
|
|
36
|
+
return await effect();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throwIfAborted(signal);
|
|
40
|
+
if (!retrySafe || !retryableError(error))
|
|
41
|
+
throw error;
|
|
42
|
+
attempt += 1;
|
|
43
|
+
const elapsed = context.clock.now() - started;
|
|
44
|
+
const decision = context.policy.shouldRetry(attempt, elapsed, error);
|
|
45
|
+
const remaining = bounds_js_1.MAX_RETRY_ELAPSED_MS - elapsed;
|
|
46
|
+
if (!validRetryDelay(decision.retry, decision.delayMs, remaining))
|
|
47
|
+
throw error;
|
|
48
|
+
await wait(decision.delayMs, signal);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Clock, RetryPolicy } from './types.js';
|
|
2
|
+
export type TargetOperation = 'allocate' | 'list' | 'inspect' | 'terminate' | 'limits' | 'access';
|
|
3
|
+
type RetryContext = {
|
|
4
|
+
readonly clock: Clock;
|
|
5
|
+
readonly policy: RetryPolicy;
|
|
6
|
+
};
|
|
7
|
+
export declare function withTargetRetry<T>(operation: TargetOperation, effect: () => Promise<T>, signal: AbortSignal | undefined, context: RetryContext): Promise<T>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Clock, RetryPolicy } from './types.js';
|
|
2
|
+
export type TargetOperation = 'allocate' | 'list' | 'inspect' | 'terminate' | 'limits' | 'access';
|
|
3
|
+
type RetryContext = {
|
|
4
|
+
readonly clock: Clock;
|
|
5
|
+
readonly policy: RetryPolicy;
|
|
6
|
+
};
|
|
7
|
+
export declare function withTargetRetry<T>(operation: TargetOperation, effect: () => Promise<T>, signal: AbortSignal | undefined, context: RetryContext): Promise<T>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Clock, RetryPolicy } from './types.js';
|
|
2
|
+
export type TargetOperation = 'allocate' | 'list' | 'inspect' | 'terminate' | 'limits' | 'access';
|
|
3
|
+
type RetryContext = {
|
|
4
|
+
readonly clock: Clock;
|
|
5
|
+
readonly policy: RetryPolicy;
|
|
6
|
+
};
|
|
7
|
+
export declare function withTargetRetry<T>(operation: TargetOperation, effect: () => Promise<T>, signal: AbortSignal | undefined, context: RetryContext): Promise<T>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { MAX_RETRY_ELAPSED_MS } from './bounds.mjs';
|
|
2
|
+
import { TargetAdapterError } from './errors.mjs';
|
|
3
|
+
function throwIfAborted(signal) {
|
|
4
|
+
if (signal?.aborted) {
|
|
5
|
+
throw signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError');
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
async function wait(delayMs, signal) {
|
|
9
|
+
throwIfAborted(signal);
|
|
10
|
+
if (delayMs <= 0)
|
|
11
|
+
return;
|
|
12
|
+
await new Promise((resolve, reject) => {
|
|
13
|
+
const timer = setTimeout(resolve, delayMs);
|
|
14
|
+
signal?.addEventListener('abort', () => {
|
|
15
|
+
clearTimeout(timer);
|
|
16
|
+
reject(signal.reason ?? new globalThis.DOMException('The operation was aborted', 'AbortError'));
|
|
17
|
+
}, { once: true });
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function retryableError(value) {
|
|
21
|
+
return value instanceof TargetAdapterError && value.retryable;
|
|
22
|
+
}
|
|
23
|
+
function validRetryDelay(retry, delayMs, remaining) {
|
|
24
|
+
return retry && Number.isFinite(delayMs) && delayMs >= 0 && delayMs < remaining;
|
|
25
|
+
}
|
|
26
|
+
export async function withTargetRetry(operation, effect, signal, context) {
|
|
27
|
+
const retrySafe = operation !== 'access';
|
|
28
|
+
const started = context.clock.now();
|
|
29
|
+
let attempt = 0;
|
|
30
|
+
while (true) {
|
|
31
|
+
throwIfAborted(signal);
|
|
32
|
+
try {
|
|
33
|
+
return await effect();
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
throwIfAborted(signal);
|
|
37
|
+
if (!retrySafe || !retryableError(error))
|
|
38
|
+
throw error;
|
|
39
|
+
attempt += 1;
|
|
40
|
+
const elapsed = context.clock.now() - started;
|
|
41
|
+
const decision = context.policy.shouldRetry(attempt, elapsed, error);
|
|
42
|
+
const remaining = MAX_RETRY_ELAPSED_MS - elapsed;
|
|
43
|
+
if (!validRetryDelay(decision.retry, decision.delayMs, remaining))
|
|
44
|
+
throw error;
|
|
45
|
+
await wait(decision.delayMs, signal);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultRetryPolicy = void 0;
|
|
4
|
+
exports.parseRetryAfter = parseRetryAfter;
|
|
5
|
+
const bounds_js_1 = require("./bounds.cjs");
|
|
6
|
+
const errors_js_1 = require("./errors.cjs");
|
|
7
|
+
const IMF_WEEKDAYS = new Set(['Mon,', 'Tue,', 'Wed,', 'Thu,', 'Fri,', 'Sat,', 'Sun,']);
|
|
8
|
+
const IMF_MONTHS = new Set([
|
|
9
|
+
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
10
|
+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
|
|
11
|
+
]);
|
|
12
|
+
function fixedDigits(value, length) {
|
|
13
|
+
if (value.length !== length)
|
|
14
|
+
return false;
|
|
15
|
+
for (const character of value) {
|
|
16
|
+
if (character < '0' || character > '9')
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
function validImfDate(weekday, day, month, year) {
|
|
22
|
+
return IMF_WEEKDAYS.has(weekday) &&
|
|
23
|
+
fixedDigits(day, 2) &&
|
|
24
|
+
IMF_MONTHS.has(month) &&
|
|
25
|
+
fixedDigits(year, 4);
|
|
26
|
+
}
|
|
27
|
+
function validImfTime(value) {
|
|
28
|
+
const parts = value.split(':');
|
|
29
|
+
return parts.length === 3 && parts.every((part) => fixedDigits(part, 2));
|
|
30
|
+
}
|
|
31
|
+
function isImfFixdate(value) {
|
|
32
|
+
const parts = value.split(' ');
|
|
33
|
+
if (parts.length !== 6)
|
|
34
|
+
return false;
|
|
35
|
+
const [weekday = '', day = '', month = '', year = '', time = '', zone = ''] = parts;
|
|
36
|
+
return validImfDate(weekday, day, month, year) && validImfTime(time) && zone === 'GMT';
|
|
37
|
+
}
|
|
38
|
+
class DefaultRetryPolicy {
|
|
39
|
+
shouldRetry(attempt, elapsed, error) {
|
|
40
|
+
if (error instanceof errors_js_1.TargetAuthError)
|
|
41
|
+
return { retry: false, delayMs: 0 };
|
|
42
|
+
if (!error.retryable)
|
|
43
|
+
return { retry: false, delayMs: 0 };
|
|
44
|
+
if (attempt >= bounds_js_1.MAX_RETRY_ATTEMPTS)
|
|
45
|
+
return { retry: false, delayMs: 0 };
|
|
46
|
+
if (elapsed >= bounds_js_1.MAX_RETRY_ELAPSED_MS)
|
|
47
|
+
return { retry: false, delayMs: 0 };
|
|
48
|
+
const requestedDelay = (error instanceof errors_js_1.TargetRateLimitError || error instanceof errors_js_1.TargetServerError) &&
|
|
49
|
+
error.retryAfterMs !== undefined
|
|
50
|
+
? Math.max(0, error.retryAfterMs)
|
|
51
|
+
: Math.min(1000 * Math.pow(2, attempt), 10_000);
|
|
52
|
+
const remaining = bounds_js_1.MAX_RETRY_ELAPSED_MS - elapsed;
|
|
53
|
+
if (!Number.isFinite(requestedDelay) || requestedDelay >= remaining) {
|
|
54
|
+
return { retry: false, delayMs: 0 };
|
|
55
|
+
}
|
|
56
|
+
return { retry: true, delayMs: requestedDelay };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.DefaultRetryPolicy = DefaultRetryPolicy;
|
|
60
|
+
function parseRetryAfter(header, clock) {
|
|
61
|
+
if (header === null)
|
|
62
|
+
return null;
|
|
63
|
+
const trimmed = header.trim();
|
|
64
|
+
if (trimmed.length === 0)
|
|
65
|
+
return null;
|
|
66
|
+
if (/^\d+$/.test(trimmed)) {
|
|
67
|
+
const delayMs = Number(trimmed) * 1000;
|
|
68
|
+
return Number.isSafeInteger(delayMs) ? delayMs : null;
|
|
69
|
+
}
|
|
70
|
+
if (!isImfFixdate(trimmed)) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const date = Date.parse(trimmed);
|
|
74
|
+
if (!Number.isFinite(date) || new Date(date).toUTCString() !== trimmed)
|
|
75
|
+
return null;
|
|
76
|
+
const delayMs = date - clock.now();
|
|
77
|
+
return delayMs > 0 ? delayMs : 0;
|
|
78
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TargetAdapterError } from './errors.js';
|
|
2
|
+
import type { Clock, RetryPolicy } from './types.js';
|
|
3
|
+
export declare class DefaultRetryPolicy implements RetryPolicy {
|
|
4
|
+
shouldRetry(attempt: number, elapsed: number, error: TargetAdapterError): {
|
|
5
|
+
retry: boolean;
|
|
6
|
+
delayMs: number;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare function parseRetryAfter(header: string | null, clock: Clock): number | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TargetAdapterError } from './errors.js';
|
|
2
|
+
import type { Clock, RetryPolicy } from './types.js';
|
|
3
|
+
export declare class DefaultRetryPolicy implements RetryPolicy {
|
|
4
|
+
shouldRetry(attempt: number, elapsed: number, error: TargetAdapterError): {
|
|
5
|
+
retry: boolean;
|
|
6
|
+
delayMs: number;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare function parseRetryAfter(header: string | null, clock: Clock): number | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TargetAdapterError } from './errors.js';
|
|
2
|
+
import type { Clock, RetryPolicy } from './types.js';
|
|
3
|
+
export declare class DefaultRetryPolicy implements RetryPolicy {
|
|
4
|
+
shouldRetry(attempt: number, elapsed: number, error: TargetAdapterError): {
|
|
5
|
+
retry: boolean;
|
|
6
|
+
delayMs: number;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export declare function parseRetryAfter(header: string | null, clock: Clock): number | null;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { MAX_RETRY_ATTEMPTS, MAX_RETRY_ELAPSED_MS } from './bounds.mjs';
|
|
2
|
+
import { TargetAuthError, TargetRateLimitError, TargetServerError } from './errors.mjs';
|
|
3
|
+
const IMF_WEEKDAYS = new Set(['Mon,', 'Tue,', 'Wed,', 'Thu,', 'Fri,', 'Sat,', 'Sun,']);
|
|
4
|
+
const IMF_MONTHS = new Set([
|
|
5
|
+
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
6
|
+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
|
|
7
|
+
]);
|
|
8
|
+
function fixedDigits(value, length) {
|
|
9
|
+
if (value.length !== length)
|
|
10
|
+
return false;
|
|
11
|
+
for (const character of value) {
|
|
12
|
+
if (character < '0' || character > '9')
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
function validImfDate(weekday, day, month, year) {
|
|
18
|
+
return IMF_WEEKDAYS.has(weekday) &&
|
|
19
|
+
fixedDigits(day, 2) &&
|
|
20
|
+
IMF_MONTHS.has(month) &&
|
|
21
|
+
fixedDigits(year, 4);
|
|
22
|
+
}
|
|
23
|
+
function validImfTime(value) {
|
|
24
|
+
const parts = value.split(':');
|
|
25
|
+
return parts.length === 3 && parts.every((part) => fixedDigits(part, 2));
|
|
26
|
+
}
|
|
27
|
+
function isImfFixdate(value) {
|
|
28
|
+
const parts = value.split(' ');
|
|
29
|
+
if (parts.length !== 6)
|
|
30
|
+
return false;
|
|
31
|
+
const [weekday = '', day = '', month = '', year = '', time = '', zone = ''] = parts;
|
|
32
|
+
return validImfDate(weekday, day, month, year) && validImfTime(time) && zone === 'GMT';
|
|
33
|
+
}
|
|
34
|
+
export class DefaultRetryPolicy {
|
|
35
|
+
shouldRetry(attempt, elapsed, error) {
|
|
36
|
+
if (error instanceof TargetAuthError)
|
|
37
|
+
return { retry: false, delayMs: 0 };
|
|
38
|
+
if (!error.retryable)
|
|
39
|
+
return { retry: false, delayMs: 0 };
|
|
40
|
+
if (attempt >= MAX_RETRY_ATTEMPTS)
|
|
41
|
+
return { retry: false, delayMs: 0 };
|
|
42
|
+
if (elapsed >= MAX_RETRY_ELAPSED_MS)
|
|
43
|
+
return { retry: false, delayMs: 0 };
|
|
44
|
+
const requestedDelay = (error instanceof TargetRateLimitError || error instanceof TargetServerError) &&
|
|
45
|
+
error.retryAfterMs !== undefined
|
|
46
|
+
? Math.max(0, error.retryAfterMs)
|
|
47
|
+
: Math.min(1000 * Math.pow(2, attempt), 10_000);
|
|
48
|
+
const remaining = MAX_RETRY_ELAPSED_MS - elapsed;
|
|
49
|
+
if (!Number.isFinite(requestedDelay) || requestedDelay >= remaining) {
|
|
50
|
+
return { retry: false, delayMs: 0 };
|
|
51
|
+
}
|
|
52
|
+
return { retry: true, delayMs: requestedDelay };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function parseRetryAfter(header, clock) {
|
|
56
|
+
if (header === null)
|
|
57
|
+
return null;
|
|
58
|
+
const trimmed = header.trim();
|
|
59
|
+
if (trimmed.length === 0)
|
|
60
|
+
return null;
|
|
61
|
+
if (/^\d+$/.test(trimmed)) {
|
|
62
|
+
const delayMs = Number(trimmed) * 1000;
|
|
63
|
+
return Number.isSafeInteger(delayMs) ? delayMs : null;
|
|
64
|
+
}
|
|
65
|
+
if (!isImfFixdate(trimmed)) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const date = Date.parse(trimmed);
|
|
69
|
+
if (!Number.isFinite(date) || new Date(date).toUTCString() !== trimmed)
|
|
70
|
+
return null;
|
|
71
|
+
const delayMs = date - clock.now();
|
|
72
|
+
return delayMs > 0 ? delayMs : 0;
|
|
73
|
+
}
|