@apifuse/provider-sdk 2.2.0-beta.36 → 2.2.0-beta.37
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 +4 -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/define.d.ts +39 -21
- package/dist/define.js +28 -9
- package/dist/index.d.ts +2 -2
- package/dist/provider.d.ts +2 -1
- 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.js +25 -0
- package/dist/types.d.ts +25 -17
- 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/define.ts +135 -51
- package/src/index.ts +4 -2
- package/src/provider.ts +6 -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 +41 -17
package/src/runtime/resolver.ts
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
type ResolverVendorTransport,
|
|
36
36
|
ResolverVendorUnavailableError,
|
|
37
37
|
type ResolverVendorUnavailableReason,
|
|
38
|
+
resolveProviderResolverVendors,
|
|
38
39
|
resolverVendorSupports,
|
|
39
40
|
} from "./resolver-vendors/types.js";
|
|
40
41
|
import {
|
|
@@ -64,6 +65,10 @@ export {
|
|
|
64
65
|
APIFUSE__RESOLVER__TIMEOUT_MS,
|
|
65
66
|
DEFAULT_RESOLVER_TIMEOUT_MS,
|
|
66
67
|
} from "./resolver-config.js";
|
|
68
|
+
export {
|
|
69
|
+
DEFAULT_RESOLVER_VENDOR_PREFERENCE,
|
|
70
|
+
resolveProviderResolverVendors,
|
|
71
|
+
} from "./resolver-vendors/types.js";
|
|
67
72
|
|
|
68
73
|
type EnvLike = Record<string, string | undefined>;
|
|
69
74
|
|
|
@@ -340,10 +345,12 @@ function assertKnownResolverVendor(vendor: string): asserts vendor is ProviderRe
|
|
|
340
345
|
throw new Error(`Unknown resolver vendor "${vendor}" in resolver configuration`);
|
|
341
346
|
}
|
|
342
347
|
|
|
343
|
-
function throwUnsupportedKind(kind: ProviderChallengeKind): never {
|
|
348
|
+
function throwUnsupportedKind(kind: ProviderChallengeKind, usingDefaultVendors: boolean): never {
|
|
344
349
|
throw new ProviderError(`Resolver vendor chain does not support kind "${kind}"`, {
|
|
345
350
|
code: "RESOLVER_KIND_UNSUPPORTED_BY_CHAIN",
|
|
346
|
-
fix:
|
|
351
|
+
fix: usingDefaultVendors
|
|
352
|
+
? `No SDK default resolver vendor supports "${kind}". Declare an explicit resolver.vendors override with a supporting vendor.`
|
|
353
|
+
: `Add a resolver vendor that supports "${kind}" to the provider's resolver.vendors declaration.`,
|
|
347
354
|
});
|
|
348
355
|
}
|
|
349
356
|
|
|
@@ -814,6 +821,7 @@ function createResolverChainClient(options: {
|
|
|
814
821
|
readonly kinds: readonly ProviderChallengeKind[];
|
|
815
822
|
readonly entries: readonly ResolverChainEntry[];
|
|
816
823
|
readonly unavailableReason?: string;
|
|
824
|
+
readonly usingDefaultVendors?: boolean;
|
|
817
825
|
readonly cache?: ProviderCache;
|
|
818
826
|
readonly identity?: ResolverIdentity;
|
|
819
827
|
readonly proxyIntent?: ResolverRuntimeOptions["proxyIntent"];
|
|
@@ -839,7 +847,9 @@ function createResolverChainClient(options: {
|
|
|
839
847
|
}
|
|
840
848
|
|
|
841
849
|
const supportingEntries = options.entries.filter((entry) => entry.supports(challenge.kind));
|
|
842
|
-
if (supportingEntries.length === 0)
|
|
850
|
+
if (supportingEntries.length === 0) {
|
|
851
|
+
throwUnsupportedKind(challenge.kind, options.usingDefaultVendors ?? false);
|
|
852
|
+
}
|
|
843
853
|
signal.throwIfAborted();
|
|
844
854
|
const identityResolution = options.proxyIntent
|
|
845
855
|
? await resolveResolverIdentity(options.proxyIntent)
|
|
@@ -1033,7 +1043,8 @@ function createResolverClientFromEnvInternal(
|
|
|
1033
1043
|
}
|
|
1034
1044
|
assertClientProfileTransportContract(config.clientProfile, options.transport);
|
|
1035
1045
|
|
|
1036
|
-
|
|
1046
|
+
const vendors = resolveProviderResolverVendors(config);
|
|
1047
|
+
if (config.vendors !== undefined && config.vendors.length === 0) {
|
|
1037
1048
|
return createResolverChainClient({
|
|
1038
1049
|
kinds: config.kinds,
|
|
1039
1050
|
entries: [],
|
|
@@ -1047,7 +1058,7 @@ function createResolverClientFromEnvInternal(
|
|
|
1047
1058
|
|
|
1048
1059
|
return createResolverChainClient({
|
|
1049
1060
|
kinds: config.kinds,
|
|
1050
|
-
entries:
|
|
1061
|
+
entries: vendors.map((configuredVendor) => {
|
|
1051
1062
|
assertKnownResolverVendor(configuredVendor);
|
|
1052
1063
|
const vendor = configuredVendor;
|
|
1053
1064
|
return {
|
|
@@ -1062,6 +1073,7 @@ function createResolverClientFromEnvInternal(
|
|
|
1062
1073
|
),
|
|
1063
1074
|
};
|
|
1064
1075
|
}),
|
|
1076
|
+
usingDefaultVendors: config.vendors === undefined,
|
|
1065
1077
|
cache: options.cache,
|
|
1066
1078
|
proxyIntent: options.proxyIntent,
|
|
1067
1079
|
identityScope: options.identityScope,
|
|
@@ -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";
|
|
@@ -745,7 +746,7 @@ function createProviderContext(
|
|
|
745
746
|
...event,
|
|
746
747
|
}),
|
|
747
748
|
}),
|
|
748
|
-
});
|
|
749
|
+
} as ProviderContext);
|
|
749
750
|
wrappedContext = context;
|
|
750
751
|
return context;
|
|
751
752
|
}
|
|
@@ -1441,6 +1442,41 @@ function extractRequestId(raw: unknown): string | undefined {
|
|
|
1441
1442
|
return typeof value === "string" ? value : undefined;
|
|
1442
1443
|
}
|
|
1443
1444
|
|
|
1445
|
+
type ProviderErrorCauseFrame = {
|
|
1446
|
+
errorClass: string;
|
|
1447
|
+
code?: string;
|
|
1448
|
+
messageLength: number;
|
|
1449
|
+
messageFingerprint: string;
|
|
1450
|
+
};
|
|
1451
|
+
|
|
1452
|
+
const MAX_PROVIDER_ERROR_CAUSE_FRAMES = 5;
|
|
1453
|
+
|
|
1454
|
+
function providerErrorCauseChain(error: unknown): ProviderErrorCauseFrame[] | undefined {
|
|
1455
|
+
if (!(error instanceof Error) && !isProviderError(error)) return undefined;
|
|
1456
|
+
|
|
1457
|
+
const seen = new Set<object>([error]);
|
|
1458
|
+
const frames: ProviderErrorCauseFrame[] = [];
|
|
1459
|
+
let cause = error.cause;
|
|
1460
|
+
|
|
1461
|
+
while (
|
|
1462
|
+
frames.length < MAX_PROVIDER_ERROR_CAUSE_FRAMES &&
|
|
1463
|
+
(cause instanceof Error || isProviderError(cause)) &&
|
|
1464
|
+
!seen.has(cause)
|
|
1465
|
+
) {
|
|
1466
|
+
seen.add(cause);
|
|
1467
|
+
const message = cause.message;
|
|
1468
|
+
frames.push({
|
|
1469
|
+
errorClass: cause.name,
|
|
1470
|
+
...(isProviderError(cause) && typeof cause.code === "string" ? { code: cause.code } : {}),
|
|
1471
|
+
messageLength: message.length,
|
|
1472
|
+
messageFingerprint: createHash("sha256").update(message).digest("hex").slice(0, 12),
|
|
1473
|
+
});
|
|
1474
|
+
cause = cause.cause;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
return frames.length > 0 ? frames : undefined;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1444
1480
|
function logProviderError(
|
|
1445
1481
|
logger: ProviderServerLogger | unknown,
|
|
1446
1482
|
provider: ProviderDefinition,
|
|
@@ -1461,6 +1497,7 @@ function logProviderError(
|
|
|
1461
1497
|
: "internal_error";
|
|
1462
1498
|
const errorClass = error instanceof Error ? error.name : typeof error;
|
|
1463
1499
|
const message = error instanceof Error ? error.message : String(error);
|
|
1500
|
+
const causeChain = providerErrorCauseChain(error);
|
|
1464
1501
|
const details = errorObservabilityDetails(error, declaredErrorCode);
|
|
1465
1502
|
const isUnregisteredProviderErrorCode =
|
|
1466
1503
|
status === 500 &&
|
|
@@ -1482,6 +1519,7 @@ function logProviderError(
|
|
|
1482
1519
|
code,
|
|
1483
1520
|
errorClass,
|
|
1484
1521
|
message,
|
|
1522
|
+
...(causeChain ? { causeChain } : {}),
|
|
1485
1523
|
...(details.upstreamStatus ? { upstreamStatus: details.upstreamStatus } : {}),
|
|
1486
1524
|
errorCategory: details.category,
|
|
1487
1525
|
taxonomyVersion: details.taxonomyVersion,
|
package/src/testing/run.ts
CHANGED
|
@@ -525,7 +525,7 @@ function createUpstreamContext(
|
|
|
525
525
|
...(provider.native
|
|
526
526
|
? {
|
|
527
527
|
native: {
|
|
528
|
-
|
|
528
|
+
network: {
|
|
529
529
|
connectTcp: async (options) => {
|
|
530
530
|
const request = snapshotNativeConnectInput(options);
|
|
531
531
|
requireNativeEgress().assertConnect(request, "disabled");
|
|
@@ -578,7 +578,7 @@ function createUpstreamContext(
|
|
|
578
578
|
credential,
|
|
579
579
|
state,
|
|
580
580
|
}),
|
|
581
|
-
};
|
|
581
|
+
} as ProviderContext;
|
|
582
582
|
}
|
|
583
583
|
|
|
584
584
|
function createNativeConnection(
|
|
@@ -709,7 +709,7 @@ export function createSnapshotContext(rawFixture: unknown): ProviderContext {
|
|
|
709
709
|
credential,
|
|
710
710
|
state,
|
|
711
711
|
}),
|
|
712
|
-
};
|
|
712
|
+
} satisfies Omit<ProviderContext, "native"> as unknown as ProviderContext;
|
|
713
713
|
snapshotCaptureStates.set(context, {
|
|
714
714
|
assertConsumed() {
|
|
715
715
|
if (streamCaptureGroup && nextCaptureItem !== streamCaptureGroup.items.length) {
|
package/src/types.ts
CHANGED
|
@@ -308,16 +308,16 @@ export interface ProviderSttConfig {
|
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
/**
|
|
311
|
-
*
|
|
312
|
-
* `createBrowserClient`) and is a first-class vendor rather than an escape hatch:
|
|
313
|
-
* for fingerprint-family kinds, it was measured faster than a paid vendor
|
|
314
|
-
* (4.5 s vs 17.5 s) at zero marginal cost.
|
|
311
|
+
* Union order is documentation only.
|
|
315
312
|
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
313
|
+
* The SDK owns the default hosted-vendor fallback policy and derives the chain
|
|
314
|
+
* from each provider's declared challenge kinds. Hosted solvers are preferred
|
|
315
|
+
* with `capsolver` ahead of `2captcha` in that policy.
|
|
318
316
|
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
317
|
+
* `browser` is the in-house CDP pool and remains opt-in; it is excluded from the
|
|
318
|
+
* default chain. `custom` is likewise reserved for provider-specific configuration.
|
|
319
|
+
*
|
|
320
|
+
* `ProviderResolverConfig.vendors` overrides the SDK policy when declared.
|
|
321
321
|
*/
|
|
322
322
|
export type ProviderResolverVendor =
|
|
323
323
|
| "browser"
|
|
@@ -411,8 +411,8 @@ export type ChallengeSolution =
|
|
|
411
411
|
};
|
|
412
412
|
|
|
413
413
|
export interface ProviderResolverConfig {
|
|
414
|
-
/**
|
|
415
|
-
readonly vendors
|
|
414
|
+
/** Optional ordered override for the SDK-owned vendor fallback chain. */
|
|
415
|
+
readonly vendors?: readonly ProviderResolverVendor[];
|
|
416
416
|
/** Challenge kinds this provider is permitted to request. */
|
|
417
417
|
readonly kinds: readonly ProviderChallengeKind[];
|
|
418
418
|
/**
|
|
@@ -1636,9 +1636,6 @@ export interface NativeContext {
|
|
|
1636
1636
|
readonly network: NativeNetworkClient;
|
|
1637
1637
|
}
|
|
1638
1638
|
|
|
1639
|
-
/** Consumer-facing alias for the native capability on provider contexts. */
|
|
1640
|
-
export type NativeProviderContext = NativeContext;
|
|
1641
|
-
|
|
1642
1639
|
export interface NativeProviderConfig {
|
|
1643
1640
|
readonly network?: {
|
|
1644
1641
|
readonly tcp?: readonly NativeTcpEgressRule[];
|
|
@@ -1816,6 +1813,10 @@ export interface BrowserPage extends BrowserFrame {
|
|
|
1816
1813
|
cookies(): Promise<readonly BrowserCookie[]>;
|
|
1817
1814
|
fill(selector: string, text: string): Promise<void>;
|
|
1818
1815
|
goto(url: string): Promise<void>;
|
|
1816
|
+
goto(
|
|
1817
|
+
url: string,
|
|
1818
|
+
options?: { readonly timeout?: number; readonly waitUntil?: "load" | "domcontentloaded" },
|
|
1819
|
+
): Promise<void>;
|
|
1819
1820
|
pageId?: string;
|
|
1820
1821
|
screenshot(options?: { fullPage?: boolean }): Promise<Buffer>;
|
|
1821
1822
|
click(selector: string): Promise<void>;
|
|
@@ -2139,7 +2140,7 @@ export interface FlowContext {
|
|
|
2139
2140
|
* un-keyed entries would be shared across all connectionless ceremonies. */
|
|
2140
2141
|
readonly state?: ProviderRuntimeState;
|
|
2141
2142
|
/** Present when the selected runtime supplies native network capabilities. */
|
|
2142
|
-
readonly native?:
|
|
2143
|
+
readonly native?: NativeContext;
|
|
2143
2144
|
stealth: StealthClient;
|
|
2144
2145
|
env: EnvContext;
|
|
2145
2146
|
credential?: CredentialContext;
|
|
@@ -2275,8 +2276,8 @@ export interface ProviderContext {
|
|
|
2275
2276
|
http: HttpClient;
|
|
2276
2277
|
/** Present for requests carrying runtime-resolvable file references. */
|
|
2277
2278
|
readonly files?: ProviderFilesContext;
|
|
2278
|
-
/**
|
|
2279
|
-
readonly native
|
|
2279
|
+
/** Native network capability selected by declaration-derived contexts. */
|
|
2280
|
+
readonly native: NativeContext;
|
|
2280
2281
|
cache: ProviderCache;
|
|
2281
2282
|
state: ProviderRuntimeState;
|
|
2282
2283
|
stealth: StealthClient;
|
|
@@ -2289,6 +2290,28 @@ export interface ProviderContext {
|
|
|
2289
2290
|
choice: ProviderChoiceContext;
|
|
2290
2291
|
}
|
|
2291
2292
|
|
|
2293
|
+
/**
|
|
2294
|
+
* The operation context exposed for one provider declaration. Capability
|
|
2295
|
+
* bindings are present only when their corresponding declaration is present;
|
|
2296
|
+
* trace and request remain ambient runtime bindings.
|
|
2297
|
+
*/
|
|
2298
|
+
export type ProviderContextFor<TConfig> =
|
|
2299
|
+
Pick<ProviderContext, "trace" | "request">
|
|
2300
|
+
& ("env" extends keyof TConfig ? Pick<ProviderContext, "env"> : Record<never, never>)
|
|
2301
|
+
& ("credential" extends keyof TConfig ? Pick<ProviderContext, "credential"> : Record<never, never>)
|
|
2302
|
+
& ("http" extends keyof TConfig ? Pick<ProviderContext, "http"> : Record<never, never>)
|
|
2303
|
+
& ("files" extends keyof TConfig ? Pick<ProviderContext, "files"> : Record<never, never>)
|
|
2304
|
+
& ("native" extends keyof TConfig ? Pick<ProviderContext, "native"> : Record<never, never>)
|
|
2305
|
+
& ("cache" extends keyof TConfig ? Pick<ProviderContext, "cache"> : Record<never, never>)
|
|
2306
|
+
& ("state" extends keyof TConfig ? Pick<ProviderContext, "state"> : Record<never, never>)
|
|
2307
|
+
& ("stealth" extends keyof TConfig ? Pick<ProviderContext, "stealth"> : Record<never, never>)
|
|
2308
|
+
& ("browser" extends keyof TConfig ? Pick<ProviderContext, "browser"> : Record<never, never>)
|
|
2309
|
+
& ("auth" extends keyof TConfig ? Pick<ProviderContext, "auth"> : Record<never, never>)
|
|
2310
|
+
& ("ocr" extends keyof TConfig ? Pick<ProviderContext, "ocr"> : Record<never, never>)
|
|
2311
|
+
& ("stt" extends keyof TConfig ? Pick<ProviderContext, "stt"> : Record<never, never>)
|
|
2312
|
+
& ("resolver" extends keyof TConfig ? Pick<ProviderContext, "resolver"> : Record<never, never>)
|
|
2313
|
+
& ("choice" extends keyof TConfig ? Pick<ProviderContext, "choice"> : Record<never, never>);
|
|
2314
|
+
|
|
2292
2315
|
export interface ProxiedOAuthConfig {
|
|
2293
2316
|
authorizeUrl: string;
|
|
2294
2317
|
tokenUrl: string;
|
|
@@ -2345,6 +2368,7 @@ export interface OperationContractMetadata {
|
|
|
2345
2368
|
export interface OperationDefinition<
|
|
2346
2369
|
TInput extends SchemaLike = SchemaLike,
|
|
2347
2370
|
TOutput extends SchemaLike = SchemaLike,
|
|
2371
|
+
TContext = ProviderContext,
|
|
2348
2372
|
> {
|
|
2349
2373
|
/**
|
|
2350
2374
|
* Short English display title for the operation. The SDK passes it through
|
|
@@ -2376,7 +2400,7 @@ export interface OperationDefinition<
|
|
|
2376
2400
|
input: TInput;
|
|
2377
2401
|
output: TOutput;
|
|
2378
2402
|
handler(
|
|
2379
|
-
ctx:
|
|
2403
|
+
ctx: TContext,
|
|
2380
2404
|
input: InferSchemaOutput<TInput>,
|
|
2381
2405
|
):
|
|
2382
2406
|
| OperationHandlerResult<InferSchemaOutput<TOutput>>
|