@apifuse/provider-sdk 2.2.0-beta.36 → 2.2.0-beta.38
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/AUTHORING.md +22 -8
- package/CHANGELOG.md +8 -0
- package/README.md +20 -8
- package/bin/apifuse-dev.ts +1 -1
- package/bin/apifuse-pack-types.ts +6 -5
- package/bin/apifuse-record.ts +1 -1
- package/bin/apifuse-submit-check.ts +23 -10
- package/dist/cli/templates/provider/index.ts.tpl +6 -3
- package/dist/cli/templates/provider/operations/ping.ts.tpl +2 -1
- package/dist/declaration-validation.d.ts +2 -0
- package/dist/declaration-validation.js +29 -3
- package/dist/define.d.ts +39 -21
- package/dist/define.js +33 -9
- package/dist/health-scenario.d.ts +1842 -0
- package/dist/health-scenario.js +624 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -0
- package/dist/provider.d.ts +5 -1
- package/dist/provider.js +1 -0
- package/dist/runtime/browser.js +19 -11
- package/dist/runtime/resolver-public.d.ts +1 -1
- package/dist/runtime/resolver-public.js +1 -1
- package/dist/runtime/resolver-vendors/browser.js +57 -14
- package/dist/runtime/resolver-vendors/types.d.ts +9 -1
- package/dist/runtime/resolver-vendors/types.js +15 -0
- package/dist/runtime/resolver.d.ts +1 -0
- package/dist/runtime/resolver.js +13 -7
- package/dist/server/serve-implementation.d.ts +1 -1
- package/dist/server/serve-implementation.js +25 -0
- package/dist/server/types.d.ts +4 -4
- package/dist/types.d.ts +35 -25
- package/package.json +1 -1
- package/src/cli/templates/provider/index.ts.tpl +6 -3
- package/src/cli/templates/provider/operations/ping.ts.tpl +2 -1
- package/src/declaration-validation.ts +30 -3
- package/src/define.ts +144 -51
- package/src/health-scenario.ts +875 -0
- package/src/index.ts +78 -2
- package/src/provider.ts +81 -1
- package/src/runtime/browser.ts +34 -11
- package/src/runtime/resolver-public.ts +2 -0
- package/src/runtime/resolver-vendors/browser.ts +69 -11
- package/src/runtime/resolver-vendors/types.ts +21 -0
- package/src/runtime/resolver.ts +17 -5
- package/src/server/serve-implementation.ts +39 -1
- package/src/testing/run.ts +3 -3
- package/src/types.ts +52 -25
package/dist/provider.d.ts
CHANGED
|
@@ -3,11 +3,15 @@ export type { CredentialsAuthChallengeDefinition, CredentialsAuthChallengeReques
|
|
|
3
3
|
export { createFormCeremony } from "./ceremonies/index.js";
|
|
4
4
|
export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, type ProviderChoiceTokenErrorReason, type ProviderChoiceTokenPayload, parseProviderChoiceToken, } from "./choice-token.js";
|
|
5
5
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
|
|
6
|
+
export type { ProviderBuilder, ProviderContextOf, ProviderDeclaration, } from "./define.js";
|
|
7
|
+
export type { JsonPrimitive, JsonValue } from "./contract-json.js";
|
|
8
|
+
export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
|
|
9
|
+
export type { AssertionExpression, AssertionPredicate, AttemptReference, AssertResult, AssertStep, BoundedJsonPath, CandidateBlock, CandidatePolicy, CandidateReference, CredentialReference, CredentialRefDeclaration, EstablishedConnectionReference, ExtractStep, FindFirst, GuardAttribution, GuardReasonCode, GuardResult, GuardStep, HealthScenario, HealthStep, JsonTemplate, JournalPolicy, ManualTriggerPolicy, NonEmpty, OperationResult, OperationStep, Operand, Quantifier, ReferenceNode, Reference, RelativeDateNode, RetryPolicy, SafeRegex, ScopedAssertionExpression, ScopedAssertionPredicate, ScopedItemReference, ScopedOperand, StepBase, StepReference, ExtractResult, ValueType, } from "./health-scenario.js";
|
|
6
10
|
export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
|
|
7
11
|
export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
|
|
8
12
|
export { type CreateProviderChoiceContextOptions, createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
|
|
9
13
|
export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema.js";
|
|
10
|
-
export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig,
|
|
14
|
+
export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDocMeta, OperationErrorCode, ProviderErrorStatus, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceConsumeMode, ProviderChoiceConsumeResult, ProviderChoiceContext, ProviderChoiceExplicitParseResult, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderContextFor, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProxiedOAuthConfig, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateNamespaceScope, StateValue, StateWriteOptions, } from "./types.js";
|
|
11
15
|
export { NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, } from "./runtime/native-network-errors.js";
|
|
12
16
|
export type { NativeGatewayProxy, NativeGatewayProxyResolutionInput, NativeGatewayProxySkipReason, NativeGatewayProxySynthesizer, NativeGatewayProxySynthesisResult, NativeGatewayProxySynthesisInput, NativeNetworkClientOptions, NativeNetworkErrorCode, VendorCredentialLookup, VendorCredentialResolver, } from "./runtime/native-network.js";
|
|
13
17
|
export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
|
package/dist/provider.js
CHANGED
|
@@ -2,6 +2,7 @@ export { AuthAbortError, credentialsAuthChallenge, createAuthFlowHelpers, define
|
|
|
2
2
|
export { createFormCeremony } from "./ceremonies/index.js";
|
|
3
3
|
export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, parseProviderChoiceToken, } from "./choice-token.js";
|
|
4
4
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
|
|
5
|
+
export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
|
|
5
6
|
export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
|
|
6
7
|
export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
|
|
7
8
|
export { createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
|
package/dist/runtime/browser.js
CHANGED
|
@@ -548,8 +548,8 @@ class PlaywrightBrowserPage {
|
|
|
548
548
|
this.page = page;
|
|
549
549
|
this.proxy = proxy;
|
|
550
550
|
}
|
|
551
|
-
async goto(url) {
|
|
552
|
-
await this.page.goto(url);
|
|
551
|
+
async goto(url, options) {
|
|
552
|
+
await this.page.goto(url, options);
|
|
553
553
|
}
|
|
554
554
|
async evaluate(fn) {
|
|
555
555
|
if (typeof fn === "string") {
|
|
@@ -1101,16 +1101,22 @@ class CdpPoolBrowserPage {
|
|
|
1101
1101
|
get id() {
|
|
1102
1102
|
return this.pageId;
|
|
1103
1103
|
}
|
|
1104
|
-
async goto(url) {
|
|
1104
|
+
async goto(url, options) {
|
|
1105
1105
|
await this.initialize();
|
|
1106
1106
|
const startedAt = Date.now();
|
|
1107
|
-
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1107
|
+
const timeout = options?.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
1108
|
+
const waitUntil = options?.waitUntil ?? "load";
|
|
1109
|
+
let expectedEventSeen = false;
|
|
1110
|
+
const eventName = waitUntil === "domcontentloaded" ? "Page.domContentEventFired" : "Page.loadEventFired";
|
|
1111
|
+
const unsubscribe = this.pageClient.on(eventName, () => {
|
|
1112
|
+
expectedEventSeen = true;
|
|
1110
1113
|
});
|
|
1111
1114
|
try {
|
|
1112
|
-
await this.pageClient.send("Page.navigate", { url });
|
|
1113
|
-
|
|
1115
|
+
const navigation = (await this.pageClient.send("Page.navigate", { url }));
|
|
1116
|
+
if (typeof navigation.errorText === "string" && navigation.errorText.length > 0) {
|
|
1117
|
+
throw new Error(`Page.navigate failed: ${navigation.errorText} at ${url}`);
|
|
1118
|
+
}
|
|
1119
|
+
await this.waitForDocumentReady(startedAt + timeout, () => expectedEventSeen, waitUntil);
|
|
1114
1120
|
}
|
|
1115
1121
|
finally {
|
|
1116
1122
|
unsubscribe();
|
|
@@ -1397,11 +1403,13 @@ class CdpPoolBrowserPage {
|
|
|
1397
1403
|
this.frameExecutionContexts.set(frameId, contextId);
|
|
1398
1404
|
return contextId;
|
|
1399
1405
|
}
|
|
1400
|
-
async waitForDocumentReady(deadline,
|
|
1406
|
+
async waitForDocumentReady(deadline, isExpectedEventSeen, waitUntil) {
|
|
1401
1407
|
while (Date.now() < deadline) {
|
|
1402
1408
|
const readyState = await this.evaluate("document.readyState");
|
|
1403
|
-
|
|
1404
|
-
|
|
1409
|
+
const documentReady = readyState === "complete" ||
|
|
1410
|
+
(waitUntil === "domcontentloaded" && readyState === "interactive");
|
|
1411
|
+
if (documentReady) {
|
|
1412
|
+
if (isExpectedEventSeen() || readyState === "complete") {
|
|
1405
1413
|
return;
|
|
1406
1414
|
}
|
|
1407
1415
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, bindResolverSignal, createResolverClient, createResolverClientFromEnv, createUnsupportedResolverClient, DEFAULT_RESOLVER_TIMEOUT_MS, invalidateResolverSolution, RESOLVER_ADAPTER_REGISTRY, RESOLVER_INSTRUMENTATION_METADATA, type ResolverAdapterFactory, type ResolverInstrumentationMetadata, type ResolverRuntimeOptions, } from "./resolver.js";
|
|
1
|
+
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, bindResolverSignal, createResolverClient, createResolverClientFromEnv, createUnsupportedResolverClient, DEFAULT_RESOLVER_VENDOR_PREFERENCE, DEFAULT_RESOLVER_TIMEOUT_MS, invalidateResolverSolution, RESOLVER_ADAPTER_REGISTRY, RESOLVER_INSTRUMENTATION_METADATA, resolveProviderResolverVendors, type ResolverAdapterFactory, type ResolverInstrumentationMetadata, type ResolverRuntimeOptions, } from "./resolver.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, bindResolverSignal, createResolverClient, createResolverClientFromEnv, createUnsupportedResolverClient, DEFAULT_RESOLVER_TIMEOUT_MS, invalidateResolverSolution, RESOLVER_ADAPTER_REGISTRY, RESOLVER_INSTRUMENTATION_METADATA, } from "./resolver.js";
|
|
1
|
+
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, bindResolverSignal, createResolverClient, createResolverClientFromEnv, createUnsupportedResolverClient, DEFAULT_RESOLVER_VENDOR_PREFERENCE, DEFAULT_RESOLVER_TIMEOUT_MS, invalidateResolverSolution, RESOLVER_ADAPTER_REGISTRY, RESOLVER_INSTRUMENTATION_METADATA, resolveProviderResolverVendors, } from "./resolver.js";
|
|
@@ -5,6 +5,7 @@ import { assertResolverHostAllowed, normalizedResolverHostname } from "./hosts.j
|
|
|
5
5
|
import { ResolverVendorUnavailableError, } from "./types.js";
|
|
6
6
|
const BROWSER_VENDOR_ID = "browser";
|
|
7
7
|
const DEFAULT_COOKIE_POLL_INTERVAL_MS = 100;
|
|
8
|
+
const NAVIGATION_BLOCKED_ERROR_TEXT = "net::ERR_BLOCKED_BY_CLIENT";
|
|
8
9
|
const AWS_WAF_CHALLENGE_INFRASTRUCTURE_HOST_SUFFIX = ".awswaf.com";
|
|
9
10
|
const RESOLVER_DOCUMENT_CONTENT_SECURITY_POLICY = "connect-src http: https:; worker-src 'none'";
|
|
10
11
|
const SUCCESS_COOKIE_NAMES = {
|
|
@@ -25,11 +26,32 @@ export function swapBrowserResolverClientFactoryForTests(factory) {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
class BrowserSolveTimeoutError extends Error {
|
|
28
|
-
constructor() {
|
|
29
|
-
super(
|
|
29
|
+
constructor(blockedRequests) {
|
|
30
|
+
super(`Browser resolver solve budget elapsed${formatBlockedRequests(blockedRequests)}`);
|
|
30
31
|
this.name = "BrowserSolveTimeoutError";
|
|
31
32
|
}
|
|
32
33
|
}
|
|
34
|
+
class BrowserNavigationBlockedError extends Error {
|
|
35
|
+
navigationUrl;
|
|
36
|
+
blockedUrls;
|
|
37
|
+
code = "RESOLVER_BROWSER_NAVIGATION_BLOCKED";
|
|
38
|
+
constructor(navigationUrl, blockedUrls, options) {
|
|
39
|
+
super(`Browser resolver navigation was blocked for ${navigationUrl}${formatBlockedRequests(blockedUrls)}`, options);
|
|
40
|
+
this.navigationUrl = navigationUrl;
|
|
41
|
+
this.blockedUrls = blockedUrls;
|
|
42
|
+
this.name = "BrowserNavigationBlockedError";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function formatBlockedRequests(blockedRequests) {
|
|
46
|
+
if (blockedRequests.length === 0)
|
|
47
|
+
return "";
|
|
48
|
+
const displayed = blockedRequests.slice(0, 5);
|
|
49
|
+
const remainder = blockedRequests.length - displayed.length;
|
|
50
|
+
return `; blocked ${blockedRequests.length} requests: [${displayed.join(", ")}]${remainder > 0 ? ` (+${remainder} more)` : ""}`;
|
|
51
|
+
}
|
|
52
|
+
function isNavigationBlockedError(error) {
|
|
53
|
+
return error instanceof Error && error.message.includes(NAVIGATION_BLOCKED_ERROR_TEXT);
|
|
54
|
+
}
|
|
33
55
|
class BrowserCleanupTimeoutError extends Error {
|
|
34
56
|
constructor(timeoutMs) {
|
|
35
57
|
super(`Browser resolver cleanup exceeded ${timeoutMs}ms`);
|
|
@@ -141,23 +163,35 @@ function selectSuccessCookie(cookies, successCookieName, pageUrl) {
|
|
|
141
163
|
cookieDomainSpecificity(right) - cookieDomainSpecificity(left) ||
|
|
142
164
|
right.path.length - left.path.length)[0];
|
|
143
165
|
}
|
|
144
|
-
async function solveInPage(page, challengeKind, pageUrl, allowedHosts, successCookieName, pollIntervalMs, signal) {
|
|
166
|
+
async function solveInPage(page, challengeKind, pageUrl, allowedHosts, successCookieName, pollIntervalMs, gotoTimeoutMs, blockedRequests, signal) {
|
|
145
167
|
return await page.withResourcePolicy({
|
|
146
168
|
allowedMethods: ["GET", "HEAD", "POST"],
|
|
147
169
|
documentContentSecurityPolicy: RESOLVER_DOCUMENT_CONTENT_SECURITY_POLICY,
|
|
148
170
|
routes: [
|
|
149
171
|
{
|
|
150
172
|
match: () => true,
|
|
151
|
-
handle: (request) =>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
173
|
+
handle: (request) => {
|
|
174
|
+
if (isResolverBrowserRequestAllowed(request.url, challengeKind, allowedHosts)) {
|
|
175
|
+
return { action: "continue" };
|
|
176
|
+
}
|
|
177
|
+
blockedRequests.add(request.url);
|
|
178
|
+
return { action: "block" };
|
|
179
|
+
},
|
|
156
180
|
},
|
|
157
181
|
],
|
|
158
182
|
}, async () => {
|
|
159
183
|
const userAgent = await raceWithAbort(() => page.userAgent(), signal);
|
|
160
|
-
|
|
184
|
+
try {
|
|
185
|
+
await raceWithAbort(() => page.goto(pageUrl, {
|
|
186
|
+
timeout: gotoTimeoutMs,
|
|
187
|
+
waitUntil: "domcontentloaded",
|
|
188
|
+
}), signal);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (!isNavigationBlockedError(error))
|
|
192
|
+
throw error;
|
|
193
|
+
throw new BrowserNavigationBlockedError(pageUrl, [...blockedRequests], { cause: error });
|
|
194
|
+
}
|
|
161
195
|
while (true) {
|
|
162
196
|
const cookies = await raceWithAbort(() => page.cookies(), signal);
|
|
163
197
|
const successCookie = selectSuccessCookie(cookies, successCookieName, pageUrl);
|
|
@@ -203,7 +237,7 @@ function poolErrorCode(error) {
|
|
|
203
237
|
const code = error.code;
|
|
204
238
|
return typeof code === "number" ? code : undefined;
|
|
205
239
|
}
|
|
206
|
-
function knownUnavailableReason(error) {
|
|
240
|
+
function knownUnavailableReason(error, beforePageSolve = false) {
|
|
207
241
|
// Source-grounded mappings:
|
|
208
242
|
// - apps/cdp-pool/src/index.ts: the JSON-RPC codes and messages below.
|
|
209
243
|
// - src/runtime/browser.ts: BROWSER_CDP_POOL_REQUIRED and the two WebSocket messages.
|
|
@@ -230,7 +264,10 @@ function knownUnavailableReason(error) {
|
|
|
230
264
|
error.message.includes("WebSocket closed")) {
|
|
231
265
|
return "transport_failure";
|
|
232
266
|
}
|
|
233
|
-
|
|
267
|
+
// Browser creation, Playwright launch, and CDP connection all happen before the
|
|
268
|
+
// isolated-page handler is entered. Errors after that boundary belong to the
|
|
269
|
+
// challenge solve and must retain their existing classification.
|
|
270
|
+
return beforePageSolve ? "transport_failure" : undefined;
|
|
234
271
|
}
|
|
235
272
|
async function closeBrowserClient(client, timeoutMs, challengeKind, traceRecorder) {
|
|
236
273
|
const close = client?.close;
|
|
@@ -274,10 +311,11 @@ export function createBrowserResolverVendorAdapter(options) {
|
|
|
274
311
|
// Refuse so the chain can choose a vendor that can honor the resolved identity.
|
|
275
312
|
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "not_implemented");
|
|
276
313
|
}
|
|
314
|
+
const blockedRequests = new Set();
|
|
277
315
|
const solveController = new AbortController();
|
|
278
316
|
const onCallerAbort = () => solveController.abort(abortReason(callerSignal));
|
|
279
317
|
callerSignal.addEventListener("abort", onCallerAbort, { once: true });
|
|
280
|
-
const timeout = setTimeout(() => solveController.abort(new BrowserSolveTimeoutError()), options.timeoutMs);
|
|
318
|
+
const timeout = setTimeout(() => solveController.abort(new BrowserSolveTimeoutError([...blockedRequests])), options.timeoutMs);
|
|
281
319
|
let client;
|
|
282
320
|
let handlerEntered = false;
|
|
283
321
|
try {
|
|
@@ -290,7 +328,7 @@ export function createBrowserResolverVendorAdapter(options) {
|
|
|
290
328
|
});
|
|
291
329
|
const contextOperation = client.withIsolatedContext(async (page) => {
|
|
292
330
|
handlerEntered = true;
|
|
293
|
-
return await solveInPage(page, challengeKind, challenge.pageUrl, options.allowedHosts, SUCCESS_COOKIE_NAMES[challengeKind], pollIntervalMs, solveController.signal);
|
|
331
|
+
return await solveInPage(page, challengeKind, challenge.pageUrl, options.allowedHosts, SUCCESS_COOKIE_NAMES[challengeKind], pollIntervalMs, options.timeoutMs, blockedRequests, solveController.signal);
|
|
294
332
|
});
|
|
295
333
|
try {
|
|
296
334
|
return await raceWithAbort(() => contextOperation, solveController.signal);
|
|
@@ -315,10 +353,15 @@ export function createBrowserResolverVendorAdapter(options) {
|
|
|
315
353
|
cause: error,
|
|
316
354
|
});
|
|
317
355
|
}
|
|
356
|
+
if (error instanceof BrowserNavigationBlockedError) {
|
|
357
|
+
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, "transport_failure", {
|
|
358
|
+
cause: error,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
318
361
|
if (error instanceof ResolverVendorUnavailableError) {
|
|
319
362
|
throw error;
|
|
320
363
|
}
|
|
321
|
-
const reason = knownUnavailableReason(error);
|
|
364
|
+
const reason = knownUnavailableReason(error, !handlerEntered);
|
|
322
365
|
if (reason) {
|
|
323
366
|
throw new ResolverVendorUnavailableError(BROWSER_VENDOR_ID, reason, { cause: error });
|
|
324
367
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChallengeSolution, ProviderChallenge, ProviderChallengeKind, ProviderResolverVendor } from "../../types.js";
|
|
1
|
+
import type { ChallengeSolution, ProviderChallenge, ProviderChallengeKind, ProviderResolverConfig, ProviderResolverVendor } from "../../types.js";
|
|
2
2
|
import type { TraceRecorder } from "../trace.js";
|
|
3
3
|
export declare const RESOLVER_VENDOR_CAPABILITIES: {
|
|
4
4
|
readonly browser: readonly ["aws_waf", "cloudflare_interstitial"];
|
|
@@ -7,7 +7,15 @@ export declare const RESOLVER_VENDOR_CAPABILITIES: {
|
|
|
7
7
|
readonly capmonster: readonly ["turnstile", "recaptcha_v2", "recaptcha_v3", "hcaptcha"];
|
|
8
8
|
readonly custom: readonly ["turnstile", "recaptcha_v2", "recaptcha_v3", "hcaptcha", "cloudflare_interstitial", "aws_waf", "akamai_sec_cpt", "akamai_sensor"];
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* SDK-owned fallback policy for hosted resolver vendors. Capability support is
|
|
12
|
+
* applied separately, so each provider receives only vendors that support one
|
|
13
|
+
* or more of its declared challenge kinds.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DEFAULT_RESOLVER_VENDOR_PREFERENCE: readonly ["capsolver", "2captcha"];
|
|
10
16
|
export declare function resolverVendorSupports(vendor: ProviderResolverVendor, kind: ProviderChallengeKind): boolean;
|
|
17
|
+
/** Resolves an explicit provider override or the SDK-owned default vendor chain. */
|
|
18
|
+
export declare function resolveProviderResolverVendors(config: ProviderResolverConfig): readonly ProviderResolverVendor[];
|
|
11
19
|
export interface ResolverIdentity {
|
|
12
20
|
readonly proxyUrl: string;
|
|
13
21
|
readonly userAgent: string;
|
|
@@ -33,9 +33,24 @@ export const RESOLVER_VENDOR_CAPABILITIES = {
|
|
|
33
33
|
"akamai_sensor",
|
|
34
34
|
],
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* SDK-owned fallback policy for hosted resolver vendors. Capability support is
|
|
38
|
+
* applied separately, so each provider receives only vendors that support one
|
|
39
|
+
* or more of its declared challenge kinds.
|
|
40
|
+
*/
|
|
41
|
+
export const DEFAULT_RESOLVER_VENDOR_PREFERENCE = [
|
|
42
|
+
"capsolver",
|
|
43
|
+
"2captcha",
|
|
44
|
+
];
|
|
36
45
|
export function resolverVendorSupports(vendor, kind) {
|
|
37
46
|
return RESOLVER_VENDOR_CAPABILITIES[vendor].includes(kind);
|
|
38
47
|
}
|
|
48
|
+
/** Resolves an explicit provider override or the SDK-owned default vendor chain. */
|
|
49
|
+
export function resolveProviderResolverVendors(config) {
|
|
50
|
+
if (config.vendors !== undefined)
|
|
51
|
+
return config.vendors;
|
|
52
|
+
return DEFAULT_RESOLVER_VENDOR_PREFERENCE.filter((vendor) => config.kinds.some((kind) => resolverVendorSupports(vendor, kind)));
|
|
53
|
+
}
|
|
39
54
|
export class ResolverVendorUnavailableError extends Error {
|
|
40
55
|
vendor;
|
|
41
56
|
reason;
|
|
@@ -4,6 +4,7 @@ import { type ResolverIdentity, type ResolverVendorAdapter, type ResolverVendorT
|
|
|
4
4
|
import type { TraceRecorder } from "./trace.js";
|
|
5
5
|
export { createUnsupportedResolverClient, RESOLVER_INSTRUMENTATION_METADATA, } from "./resolver-shared.js";
|
|
6
6
|
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./resolver-config.js";
|
|
7
|
+
export { DEFAULT_RESOLVER_VENDOR_PREFERENCE, resolveProviderResolverVendors, } from "./resolver-vendors/types.js";
|
|
7
8
|
type EnvLike = Record<string, string | undefined>;
|
|
8
9
|
type ResolverChainClient = ResolverContext & {
|
|
9
10
|
solve(challenge: ProviderChallenge, signal?: AbortSignal, traceRecorder?: TraceRecorder): Promise<ChallengeSolution>;
|
package/dist/runtime/resolver.js
CHANGED
|
@@ -7,12 +7,13 @@ import { createBrowserResolverVendorAdapter } from "./resolver-vendors/browser.j
|
|
|
7
7
|
import { createCapsolverResolverVendorAdapter } from "./resolver-vendors/capsolver.js";
|
|
8
8
|
import { assertResolverHostAllowed } from "./resolver-vendors/hosts.js";
|
|
9
9
|
import { createTwoCaptchaResolverVendorAdapter } from "./resolver-vendors/twocaptcha.js";
|
|
10
|
-
import { RESOLVER_VENDOR_CAPABILITIES, ResolverVendorUnavailableError, resolverVendorSupports, } from "./resolver-vendors/types.js";
|
|
10
|
+
import { RESOLVER_VENDOR_CAPABILITIES, ResolverVendorUnavailableError, resolveProviderResolverVendors, resolverVendorSupports, } from "./resolver-vendors/types.js";
|
|
11
11
|
import { createUnsupportedResolverClient, RESOLVER_INSTRUMENTATION_METADATA, } from "./resolver-shared.js";
|
|
12
12
|
import { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./resolver-config.js";
|
|
13
13
|
import { DEFAULT_PROFILE } from "./stealth.js";
|
|
14
14
|
export { createUnsupportedResolverClient, RESOLVER_INSTRUMENTATION_METADATA, } from "./resolver-shared.js";
|
|
15
15
|
export { APIFUSE__CDP_POOL__URL, APIFUSE__RESOLVER__2CAPTCHA__API_KEY, APIFUSE__RESOLVER__CAPMONSTER__API_KEY, APIFUSE__RESOLVER__CAPSOLVER__API_KEY, APIFUSE__RESOLVER__TIMEOUT_MS, DEFAULT_RESOLVER_TIMEOUT_MS, } from "./resolver-config.js";
|
|
16
|
+
export { DEFAULT_RESOLVER_VENDOR_PREFERENCE, resolveProviderResolverVendors, } from "./resolver-vendors/types.js";
|
|
16
17
|
const RESOLVER_SOLUTION_CACHE_NAMESPACE = "resolver-solution";
|
|
17
18
|
const RESOLVER_SOLUTION_INDEX_CACHE_NAMESPACE = "resolver-solution-index";
|
|
18
19
|
const MIN_RESOLVER_CACHE_TTL_MS = 1_000;
|
|
@@ -169,10 +170,12 @@ function assertKnownResolverVendor(vendor) {
|
|
|
169
170
|
return;
|
|
170
171
|
throw new Error(`Unknown resolver vendor "${vendor}" in resolver configuration`);
|
|
171
172
|
}
|
|
172
|
-
function throwUnsupportedKind(kind) {
|
|
173
|
+
function throwUnsupportedKind(kind, usingDefaultVendors) {
|
|
173
174
|
throw new ProviderError(`Resolver vendor chain does not support kind "${kind}"`, {
|
|
174
175
|
code: "RESOLVER_KIND_UNSUPPORTED_BY_CHAIN",
|
|
175
|
-
fix:
|
|
176
|
+
fix: usingDefaultVendors
|
|
177
|
+
? `No SDK default resolver vendor supports "${kind}". Declare an explicit resolver.vendors override with a supporting vendor.`
|
|
178
|
+
: `Add a resolver vendor that supports "${kind}" to the provider's resolver.vendors declaration.`,
|
|
176
179
|
});
|
|
177
180
|
}
|
|
178
181
|
function throwExhausted(attempts) {
|
|
@@ -542,8 +545,9 @@ function createResolverChainClient(options) {
|
|
|
542
545
|
});
|
|
543
546
|
}
|
|
544
547
|
const supportingEntries = options.entries.filter((entry) => entry.supports(challenge.kind));
|
|
545
|
-
if (supportingEntries.length === 0)
|
|
546
|
-
throwUnsupportedKind(challenge.kind);
|
|
548
|
+
if (supportingEntries.length === 0) {
|
|
549
|
+
throwUnsupportedKind(challenge.kind, options.usingDefaultVendors ?? false);
|
|
550
|
+
}
|
|
547
551
|
signal.throwIfAborted();
|
|
548
552
|
const identityResolution = options.proxyIntent
|
|
549
553
|
? await resolveResolverIdentity(options.proxyIntent)
|
|
@@ -692,7 +696,8 @@ function createResolverClientFromEnvInternal(config, env, options, adapterFactor
|
|
|
692
696
|
return createUnsupportedResolverClient("Provider does not declare resolver capability");
|
|
693
697
|
}
|
|
694
698
|
assertClientProfileTransportContract(config.clientProfile, options.transport);
|
|
695
|
-
|
|
699
|
+
const vendors = resolveProviderResolverVendors(config);
|
|
700
|
+
if (config.vendors !== undefined && config.vendors.length === 0) {
|
|
696
701
|
return createResolverChainClient({
|
|
697
702
|
kinds: config.kinds,
|
|
698
703
|
entries: [],
|
|
@@ -704,7 +709,7 @@ function createResolverClientFromEnvInternal(config, env, options, adapterFactor
|
|
|
704
709
|
const allowedHosts = [...(options.allowedHosts ?? [])];
|
|
705
710
|
return createResolverChainClient({
|
|
706
711
|
kinds: config.kinds,
|
|
707
|
-
entries:
|
|
712
|
+
entries: vendors.map((configuredVendor) => {
|
|
708
713
|
assertKnownResolverVendor(configuredVendor);
|
|
709
714
|
const vendor = configuredVendor;
|
|
710
715
|
return {
|
|
@@ -713,6 +718,7 @@ function createResolverClientFromEnvInternal(config, env, options, adapterFactor
|
|
|
713
718
|
createAdapter: () => createAdapter(resolveVendorAvailability(vendor, env), timeoutMs, allowedHosts, adapterFactories),
|
|
714
719
|
};
|
|
715
720
|
}),
|
|
721
|
+
usingDefaultVendors: config.vendors === undefined,
|
|
716
722
|
cache: options.cache,
|
|
717
723
|
proxyIntent: options.proxyIntent,
|
|
718
724
|
identityScope: options.identityScope,
|
|
@@ -34,8 +34,8 @@ export declare const ProviderServerStatefulForwardEnvelopeSchema: z.ZodObject<{
|
|
|
34
34
|
connection: z.ZodOptional<z.ZodObject<{
|
|
35
35
|
id: z.ZodString;
|
|
36
36
|
mode: z.ZodEnum<{
|
|
37
|
-
none: "none";
|
|
38
37
|
credentials: "credentials";
|
|
38
|
+
none: "none";
|
|
39
39
|
oauth2: "oauth2";
|
|
40
40
|
"platform-managed": "platform-managed";
|
|
41
41
|
oauth2_proxied: "oauth2_proxied";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import { join } from "node:path";
|
|
@@ -924,6 +925,28 @@ function extractRequestId(raw) {
|
|
|
924
925
|
const value = Object.getOwnPropertyDescriptor(raw, "requestId")?.value;
|
|
925
926
|
return typeof value === "string" ? value : undefined;
|
|
926
927
|
}
|
|
928
|
+
const MAX_PROVIDER_ERROR_CAUSE_FRAMES = 5;
|
|
929
|
+
function providerErrorCauseChain(error) {
|
|
930
|
+
if (!(error instanceof Error) && !isProviderError(error))
|
|
931
|
+
return undefined;
|
|
932
|
+
const seen = new Set([error]);
|
|
933
|
+
const frames = [];
|
|
934
|
+
let cause = error.cause;
|
|
935
|
+
while (frames.length < MAX_PROVIDER_ERROR_CAUSE_FRAMES &&
|
|
936
|
+
(cause instanceof Error || isProviderError(cause)) &&
|
|
937
|
+
!seen.has(cause)) {
|
|
938
|
+
seen.add(cause);
|
|
939
|
+
const message = cause.message;
|
|
940
|
+
frames.push({
|
|
941
|
+
errorClass: cause.name,
|
|
942
|
+
...(isProviderError(cause) && typeof cause.code === "string" ? { code: cause.code } : {}),
|
|
943
|
+
messageLength: message.length,
|
|
944
|
+
messageFingerprint: createHash("sha256").update(message).digest("hex").slice(0, 12),
|
|
945
|
+
});
|
|
946
|
+
cause = cause.cause;
|
|
947
|
+
}
|
|
948
|
+
return frames.length > 0 ? frames : undefined;
|
|
949
|
+
}
|
|
927
950
|
function logProviderError(logger, provider, kind, route, requestId, error, status, cost, declaredErrorCode) {
|
|
928
951
|
const code = isProviderError(error)
|
|
929
952
|
? (error.code ?? "provider_error")
|
|
@@ -934,6 +957,7 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
934
957
|
: "internal_error";
|
|
935
958
|
const errorClass = error instanceof Error ? error.name : typeof error;
|
|
936
959
|
const message = error instanceof Error ? error.message : String(error);
|
|
960
|
+
const causeChain = providerErrorCauseChain(error);
|
|
937
961
|
const details = errorObservabilityDetails(error, declaredErrorCode);
|
|
938
962
|
const isUnregisteredProviderErrorCode = status === 500 &&
|
|
939
963
|
isProviderError(error) &&
|
|
@@ -954,6 +978,7 @@ function logProviderError(logger, provider, kind, route, requestId, error, statu
|
|
|
954
978
|
code,
|
|
955
979
|
errorClass,
|
|
956
980
|
message,
|
|
981
|
+
...(causeChain ? { causeChain } : {}),
|
|
957
982
|
...(details.upstreamStatus ? { upstreamStatus: details.upstreamStatus } : {}),
|
|
958
983
|
errorCategory: details.category,
|
|
959
984
|
taxonomyVersion: details.taxonomyVersion,
|
package/dist/server/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const ConnectionModeSchema: z.ZodEnum<{
|
|
3
|
-
none: "none";
|
|
4
3
|
credentials: "credentials";
|
|
4
|
+
none: "none";
|
|
5
5
|
oauth2: "oauth2";
|
|
6
6
|
"platform-managed": "platform-managed";
|
|
7
7
|
oauth2_proxied: "oauth2_proxied";
|
|
@@ -9,8 +9,8 @@ export declare const ConnectionModeSchema: z.ZodEnum<{
|
|
|
9
9
|
export declare const OperationConnectionSchema: z.ZodObject<{
|
|
10
10
|
id: z.ZodString;
|
|
11
11
|
mode: z.ZodEnum<{
|
|
12
|
-
none: "none";
|
|
13
12
|
credentials: "credentials";
|
|
13
|
+
none: "none";
|
|
14
14
|
oauth2: "oauth2";
|
|
15
15
|
"platform-managed": "platform-managed";
|
|
16
16
|
oauth2_proxied: "oauth2_proxied";
|
|
@@ -27,8 +27,8 @@ export declare const OperationRequestSchema: z.ZodObject<{
|
|
|
27
27
|
connection: z.ZodOptional<z.ZodObject<{
|
|
28
28
|
id: z.ZodString;
|
|
29
29
|
mode: z.ZodEnum<{
|
|
30
|
-
none: "none";
|
|
31
30
|
credentials: "credentials";
|
|
31
|
+
none: "none";
|
|
32
32
|
oauth2: "oauth2";
|
|
33
33
|
"platform-managed": "platform-managed";
|
|
34
34
|
oauth2_proxied: "oauth2_proxied";
|
|
@@ -118,8 +118,8 @@ export declare const AuthFlowRequestSchema: z.ZodObject<{
|
|
|
118
118
|
connection: z.ZodOptional<z.ZodObject<{
|
|
119
119
|
id: z.ZodString;
|
|
120
120
|
mode: z.ZodEnum<{
|
|
121
|
-
none: "none";
|
|
122
121
|
credentials: "credentials";
|
|
122
|
+
none: "none";
|
|
123
123
|
oauth2: "oauth2";
|
|
124
124
|
"platform-managed": "platform-managed";
|
|
125
125
|
oauth2_proxied: "oauth2_proxied";
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type ms from "ms";
|
|
2
|
+
import type { HealthScenario } from "./health-scenario.js";
|
|
2
3
|
import type { SerializedCookieJar } from "tough-cookie";
|
|
3
4
|
import type { infer as ZodInfer, ZodType } from "zod";
|
|
4
5
|
/** Minimal Standard Schema v1 shape accepted by provider operations. */
|
|
@@ -252,16 +253,16 @@ export interface ProviderSttConfig {
|
|
|
252
253
|
mode: ProviderSttMode;
|
|
253
254
|
}
|
|
254
255
|
/**
|
|
255
|
-
*
|
|
256
|
-
* `createBrowserClient`) and is a first-class vendor rather than an escape hatch:
|
|
257
|
-
* for fingerprint-family kinds, it was measured faster than a paid vendor
|
|
258
|
-
* (4.5 s vs 17.5 s) at zero marginal cost.
|
|
256
|
+
* Union order is documentation only.
|
|
259
257
|
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
258
|
+
* The SDK owns the default hosted-vendor fallback policy and derives the chain
|
|
259
|
+
* from each provider's declared challenge kinds. Hosted solvers are preferred
|
|
260
|
+
* with `capsolver` ahead of `2captcha` in that policy.
|
|
262
261
|
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
262
|
+
* `browser` is the in-house CDP pool and remains opt-in; it is excluded from the
|
|
263
|
+
* default chain. `custom` is likewise reserved for provider-specific configuration.
|
|
264
|
+
*
|
|
265
|
+
* `ProviderResolverConfig.vendors` overrides the SDK policy when declared.
|
|
265
266
|
*/
|
|
266
267
|
export type ProviderResolverVendor = "browser" | "capsolver" | "capmonster" | "2captcha" | "custom";
|
|
267
268
|
/**
|
|
@@ -339,8 +340,8 @@ export type ChallengeSolution = {
|
|
|
339
340
|
readonly expires?: number;
|
|
340
341
|
};
|
|
341
342
|
export interface ProviderResolverConfig {
|
|
342
|
-
/**
|
|
343
|
-
readonly vendors
|
|
343
|
+
/** Optional ordered override for the SDK-owned vendor fallback chain. */
|
|
344
|
+
readonly vendors?: readonly ProviderResolverVendor[];
|
|
344
345
|
/** Challenge kinds this provider is permitted to request. */
|
|
345
346
|
readonly kinds: readonly ProviderChallengeKind[];
|
|
346
347
|
/**
|
|
@@ -549,7 +550,7 @@ export interface HealthJourneyRunResult {
|
|
|
549
550
|
label?: string;
|
|
550
551
|
metadata?: Record<string, unknown>;
|
|
551
552
|
}
|
|
552
|
-
|
|
553
|
+
interface HealthJourneyDefinitionBase {
|
|
553
554
|
id: string;
|
|
554
555
|
title?: string;
|
|
555
556
|
description?: string;
|
|
@@ -561,14 +562,14 @@ export interface HealthJourneyDefinition {
|
|
|
561
562
|
requiredSecrets?: readonly string[];
|
|
562
563
|
manualTrigger?: HealthJourneyManualTriggerPolicy;
|
|
563
564
|
steps: readonly [HealthJourneyStep, ...HealthJourneyStep[]];
|
|
564
|
-
/**
|
|
565
|
-
* Required: a journey always declares `coversOperations`, and the health
|
|
566
|
-
* monitor reports a run-less journey as `journey_run_missing`. Declaration
|
|
567
|
-
* validation rejects a missing `run` (`health-journey-executable`), so this
|
|
568
|
-
* is typed required to fail at compile time rather than at boot.
|
|
569
|
-
*/
|
|
570
|
-
run: (ctx: HealthJourneyRunContext) => Promise<HealthJourneyRunResult | undefined>;
|
|
571
565
|
}
|
|
566
|
+
export type HealthJourneyDefinition = HealthJourneyDefinitionBase & ({
|
|
567
|
+
run: (ctx: HealthJourneyRunContext) => Promise<HealthJourneyRunResult | undefined>;
|
|
568
|
+
scenario?: never;
|
|
569
|
+
} | {
|
|
570
|
+
scenario: HealthScenario;
|
|
571
|
+
run?: never;
|
|
572
|
+
});
|
|
572
573
|
/**
|
|
573
574
|
* Health-check authoring surface owned by `@apifuse/provider-sdk`.
|
|
574
575
|
*
|
|
@@ -1355,8 +1356,6 @@ export interface NativeNetworkClient {
|
|
|
1355
1356
|
export interface NativeContext {
|
|
1356
1357
|
readonly network: NativeNetworkClient;
|
|
1357
1358
|
}
|
|
1358
|
-
/** Consumer-facing alias for the native capability on provider contexts. */
|
|
1359
|
-
export type NativeProviderContext = NativeContext;
|
|
1360
1359
|
export interface NativeProviderConfig {
|
|
1361
1360
|
readonly network?: {
|
|
1362
1361
|
readonly tcp?: readonly NativeTcpEgressRule[];
|
|
@@ -1496,6 +1495,10 @@ export interface BrowserPage extends BrowserFrame {
|
|
|
1496
1495
|
cookies(): Promise<readonly BrowserCookie[]>;
|
|
1497
1496
|
fill(selector: string, text: string): Promise<void>;
|
|
1498
1497
|
goto(url: string): Promise<void>;
|
|
1498
|
+
goto(url: string, options?: {
|
|
1499
|
+
readonly timeout?: number;
|
|
1500
|
+
readonly waitUntil?: "load" | "domcontentloaded";
|
|
1501
|
+
}): Promise<void>;
|
|
1499
1502
|
pageId?: string;
|
|
1500
1503
|
screenshot(options?: {
|
|
1501
1504
|
fullPage?: boolean;
|
|
@@ -1762,7 +1765,7 @@ export interface FlowContext {
|
|
|
1762
1765
|
* un-keyed entries would be shared across all connectionless ceremonies. */
|
|
1763
1766
|
readonly state?: ProviderRuntimeState;
|
|
1764
1767
|
/** Present when the selected runtime supplies native network capabilities. */
|
|
1765
|
-
readonly native?:
|
|
1768
|
+
readonly native?: NativeContext;
|
|
1766
1769
|
stealth: StealthClient;
|
|
1767
1770
|
env: EnvContext;
|
|
1768
1771
|
credential?: CredentialContext;
|
|
@@ -1863,8 +1866,8 @@ export interface ProviderContext {
|
|
|
1863
1866
|
http: HttpClient;
|
|
1864
1867
|
/** Present for requests carrying runtime-resolvable file references. */
|
|
1865
1868
|
readonly files?: ProviderFilesContext;
|
|
1866
|
-
/**
|
|
1867
|
-
readonly native
|
|
1869
|
+
/** Native network capability selected by declaration-derived contexts. */
|
|
1870
|
+
readonly native: NativeContext;
|
|
1868
1871
|
cache: ProviderCache;
|
|
1869
1872
|
state: ProviderRuntimeState;
|
|
1870
1873
|
stealth: StealthClient;
|
|
@@ -1876,6 +1879,12 @@ export interface ProviderContext {
|
|
|
1876
1879
|
resolver: ResolverContext;
|
|
1877
1880
|
choice: ProviderChoiceContext;
|
|
1878
1881
|
}
|
|
1882
|
+
/**
|
|
1883
|
+
* The operation context exposed for one provider declaration. Capability
|
|
1884
|
+
* bindings are present only when their corresponding declaration is present;
|
|
1885
|
+
* trace and request remain ambient runtime bindings.
|
|
1886
|
+
*/
|
|
1887
|
+
export type ProviderContextFor<TConfig> = Pick<ProviderContext, "trace" | "request"> & ("env" extends keyof TConfig ? Pick<ProviderContext, "env"> : Record<never, never>) & ("credential" extends keyof TConfig ? Pick<ProviderContext, "credential"> : Record<never, never>) & ("http" extends keyof TConfig ? Pick<ProviderContext, "http"> : Record<never, never>) & ("files" extends keyof TConfig ? Pick<ProviderContext, "files"> : Record<never, never>) & ("native" extends keyof TConfig ? Pick<ProviderContext, "native"> : Record<never, never>) & ("cache" extends keyof TConfig ? Pick<ProviderContext, "cache"> : Record<never, never>) & ("state" extends keyof TConfig ? Pick<ProviderContext, "state"> : Record<never, never>) & ("stealth" extends keyof TConfig ? Pick<ProviderContext, "stealth"> : Record<never, never>) & ("browser" extends keyof TConfig ? Pick<ProviderContext, "browser"> : Record<never, never>) & ("auth" extends keyof TConfig ? Pick<ProviderContext, "auth"> : Record<never, never>) & ("ocr" extends keyof TConfig ? Pick<ProviderContext, "ocr"> : Record<never, never>) & ("stt" extends keyof TConfig ? Pick<ProviderContext, "stt"> : Record<never, never>) & ("resolver" extends keyof TConfig ? Pick<ProviderContext, "resolver"> : Record<never, never>) & ("choice" extends keyof TConfig ? Pick<ProviderContext, "choice"> : Record<never, never>);
|
|
1879
1888
|
export interface ProxiedOAuthConfig {
|
|
1880
1889
|
authorizeUrl: string;
|
|
1881
1890
|
tokenUrl: string;
|
|
@@ -1921,7 +1930,7 @@ export interface OperationContractMetadata {
|
|
|
1921
1930
|
lifecycle?: OperationLifecycle;
|
|
1922
1931
|
deprecation?: OperationDeprecationMetadata;
|
|
1923
1932
|
}
|
|
1924
|
-
export interface OperationDefinition<TInput extends SchemaLike = SchemaLike, TOutput extends SchemaLike = SchemaLike> {
|
|
1933
|
+
export interface OperationDefinition<TInput extends SchemaLike = SchemaLike, TOutput extends SchemaLike = SchemaLike, TContext = ProviderContext> {
|
|
1925
1934
|
/**
|
|
1926
1935
|
* Short English display title for the operation. The SDK passes it through
|
|
1927
1936
|
* verbatim; the APIFuse registry derives the operation's en locale title
|
|
@@ -1951,7 +1960,7 @@ export interface OperationDefinition<TInput extends SchemaLike = SchemaLike, TOu
|
|
|
1951
1960
|
retryOnAuthRefresh?: boolean;
|
|
1952
1961
|
input: TInput;
|
|
1953
1962
|
output: TOutput;
|
|
1954
|
-
handler(ctx:
|
|
1963
|
+
handler(ctx: TContext, input: InferSchemaOutput<TInput>): OperationHandlerResult<InferSchemaOutput<TOutput>> | Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
|
|
1955
1964
|
fixtures?: {
|
|
1956
1965
|
request: InferSchemaOutput<TInput>;
|
|
1957
1966
|
response: InferSchemaOutput<TOutput>;
|
|
@@ -2043,3 +2052,4 @@ export interface ProviderDefinition {
|
|
|
2043
2052
|
healthProbe?: ProviderHealthProbeConfig;
|
|
2044
2053
|
healthJourneys?: readonly HealthJourneyDefinition[];
|
|
2045
2054
|
}
|
|
2055
|
+
export {};
|
package/package.json
CHANGED