@apifuse/provider-sdk 2.2.0-beta.61 → 2.2.0-beta.63
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 +268 -9
- package/CHANGELOG.md +8 -0
- package/README.md +1 -0
- package/bin/apifuse-check.ts +84 -2
- package/bin/apifuse-dev.ts +11 -31
- package/bin/apifuse-migrate-deployment.ts +200 -0
- package/bin/apifuse-pack-check.ts +11 -4
- package/bin/apifuse-pack-types.ts +191 -4
- package/bin/apifuse-record.ts +44 -32
- package/bin/apifuse-test.ts +3 -1
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +11 -0
- package/dist/cli/deployment-intent.d.ts +178 -0
- package/dist/cli/deployment-intent.js +277 -0
- package/dist/cli/migrate-deployment-intent.d.ts +132 -0
- package/dist/cli/migrate-deployment-intent.js +1552 -0
- package/dist/cli/migrate-provider-shape.d.ts +5 -1
- package/dist/cli/migrate-provider-shape.js +4 -2
- package/dist/cli/resolver-runtime.d.ts +21 -0
- package/dist/cli/resolver-runtime.js +31 -0
- package/dist/define.d.ts +3 -0
- package/dist/define.js +5 -0
- package/dist/dev.d.ts +3 -1
- package/dist/dev.js +6 -1
- package/dist/engine.d.ts +35 -1
- package/dist/engine.js +21 -2
- package/dist/error-resolution.d.ts +1 -0
- package/dist/error-resolution.js +54 -0
- package/dist/errors.d.ts +39 -1
- package/dist/errors.js +50 -0
- package/dist/handle-meta.d.ts +18 -2
- package/dist/handle-meta.js +30 -2
- package/dist/handle.d.ts +33 -12
- package/dist/handle.js +69 -24
- package/dist/i18n/error-messages.d.ts +86 -0
- package/dist/i18n/error-messages.js +192 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/keys.d.ts +12 -0
- package/dist/i18n/keys.js +76 -5
- package/dist/index.d.ts +10 -2
- package/dist/index.js +9 -1
- package/dist/lint.d.ts +10 -0
- package/dist/lint.js +440 -57
- package/dist/provider.d.ts +7 -5
- package/dist/provider.js +4 -2
- package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
- package/dist/runtime/browser-telemetry-binding.js +83 -0
- package/dist/runtime/browser-telemetry.d.ts +76 -0
- package/dist/runtime/browser-telemetry.js +165 -0
- package/dist/runtime/browser.d.ts +3 -0
- package/dist/runtime/browser.js +208 -47
- package/dist/runtime/cache-telemetry.d.ts +71 -0
- package/dist/runtime/cache-telemetry.js +177 -0
- package/dist/runtime/cache.js +67 -7
- package/dist/runtime/capability-response.d.ts +3 -0
- package/dist/runtime/capability-response.js +56 -0
- package/dist/runtime/capability-telemetry.d.ts +46 -0
- package/dist/runtime/capability-telemetry.js +68 -0
- package/dist/runtime/diagnostic-env.d.ts +3 -0
- package/dist/runtime/diagnostic-env.js +10 -1
- package/dist/runtime/engine-mode.d.ts +74 -0
- package/dist/runtime/engine-mode.js +152 -0
- package/dist/runtime/handle.js +15 -10
- package/dist/runtime/http-telemetry-binding.d.ts +10 -0
- package/dist/runtime/http-telemetry-binding.js +152 -0
- package/dist/runtime/http-telemetry-guard.d.ts +16 -0
- package/dist/runtime/http-telemetry-guard.js +202 -0
- package/dist/runtime/http-telemetry.d.ts +104 -0
- package/dist/runtime/http-telemetry.js +190 -0
- package/dist/runtime/http.d.ts +31 -0
- package/dist/runtime/http.js +356 -174
- package/dist/runtime/instrumentation.js +92 -13
- package/dist/runtime/ocr-telemetry.d.ts +82 -0
- package/dist/runtime/ocr-telemetry.js +192 -0
- package/dist/runtime/ocr.js +30 -8
- package/dist/runtime/request-telemetry.d.ts +2 -0
- package/dist/runtime/request-telemetry.js +2 -1
- package/dist/runtime/resolver-runtime-options.d.ts +14 -0
- package/dist/runtime/resolver-runtime-options.js +33 -0
- package/dist/runtime/resolver-shared.d.ts +3 -2
- package/dist/runtime/resolver-shared.js +4 -4
- package/dist/runtime/resolver-telemetry.d.ts +1 -0
- package/dist/runtime/resolver-telemetry.js +1 -1
- package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
- package/dist/runtime/resolver-vendors/browser.js +46 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
- package/dist/runtime/resolver-vendors/hosts.js +35 -0
- package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
- package/dist/runtime/resolver-vendors/types.d.ts +5 -4
- package/dist/runtime/resolver.d.ts +4 -1
- package/dist/runtime/resolver.js +46 -13
- package/dist/runtime/state-telemetry.d.ts +79 -0
- package/dist/runtime/state-telemetry.js +194 -0
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +26 -7
- package/dist/runtime/stealth-cookies.d.ts +5 -1
- package/dist/runtime/stealth-cookies.js +21 -1
- package/dist/runtime/stealth-owned-headers.d.ts +26 -0
- package/dist/runtime/stealth-owned-headers.js +37 -0
- package/dist/runtime/stealth-telemetry.d.ts +92 -0
- package/dist/runtime/stealth-telemetry.js +179 -0
- package/dist/runtime/stealth.d.ts +4 -1
- package/dist/runtime/stealth.js +228 -85
- package/dist/runtime/stt-telemetry.d.ts +77 -0
- package/dist/runtime/stt-telemetry.js +176 -0
- package/dist/runtime/stt.js +15 -6
- package/dist/server/error-stack-frames.d.ts +35 -0
- package/dist/server/error-stack-frames.js +219 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +5 -0
- package/dist/server/sdk-version.d.ts +3 -0
- package/dist/server/sdk-version.js +19 -0
- package/dist/server/self-test.js +1 -18
- package/dist/server/sensitive-values.d.ts +1 -1
- package/dist/server/sensitive-values.js +9 -0
- package/dist/server/serve-implementation.d.ts +53 -2
- package/dist/server/serve-implementation.js +369 -123
- package/dist/server/types.d.ts +1 -0
- package/dist/server/types.js +7 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
- package/dist/stateful/stateful-provider-runtime-context.js +1 -0
- package/dist/types.d.ts +94 -1
- package/package.json +6 -1
- package/src/cli/commands.ts +14 -0
- package/src/cli/deployment-intent.ts +364 -0
- package/src/cli/migrate-deployment-intent.ts +1908 -0
- package/src/cli/migrate-provider-shape.ts +10 -4
- package/src/cli/resolver-runtime.ts +72 -0
- package/src/define.ts +13 -0
- package/src/dev.ts +9 -2
- package/src/engine.ts +38 -2
- package/src/error-resolution.ts +58 -0
- package/src/errors.ts +77 -1
- package/src/handle-meta.ts +39 -4
- package/src/handle.ts +121 -38
- package/src/i18n/error-messages.ts +255 -0
- package/src/i18n/index.ts +1 -0
- package/src/i18n/keys.ts +80 -6
- package/src/index.ts +91 -0
- package/src/lint.ts +552 -57
- package/src/provider.ts +20 -0
- package/src/runtime/browser-telemetry-binding.ts +92 -0
- package/src/runtime/browser-telemetry.ts +289 -0
- package/src/runtime/browser.ts +249 -65
- package/src/runtime/cache-telemetry.ts +247 -0
- package/src/runtime/cache.ts +68 -17
- package/src/runtime/capability-response.ts +53 -0
- package/src/runtime/capability-telemetry.ts +101 -0
- package/src/runtime/diagnostic-env.ts +11 -1
- package/src/runtime/engine-mode.ts +233 -0
- package/src/runtime/handle.ts +20 -10
- package/src/runtime/http-telemetry-binding.ts +162 -0
- package/src/runtime/http-telemetry-guard.ts +208 -0
- package/src/runtime/http-telemetry.ts +292 -0
- package/src/runtime/http.ts +457 -204
- package/src/runtime/instrumentation.ts +105 -16
- package/src/runtime/ocr-telemetry.ts +308 -0
- package/src/runtime/ocr.ts +109 -74
- package/src/runtime/request-telemetry.ts +2 -1
- package/src/runtime/resolver-runtime-options.ts +50 -0
- package/src/runtime/resolver-shared.ts +9 -4
- package/src/runtime/resolver-telemetry.ts +1 -1
- package/src/runtime/resolver-vendors/browser.ts +65 -7
- package/src/runtime/resolver-vendors/hosts.ts +43 -0
- package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
- package/src/runtime/resolver-vendors/types.ts +5 -4
- package/src/runtime/resolver.ts +64 -21
- package/src/runtime/state-telemetry.ts +298 -0
- package/src/runtime/state.ts +46 -45
- package/src/runtime/stealth-cookies.ts +24 -1
- package/src/runtime/stealth-owned-headers.ts +41 -0
- package/src/runtime/stealth-telemetry.ts +304 -0
- package/src/runtime/stealth.ts +355 -150
- package/src/runtime/stt-telemetry.ts +282 -0
- package/src/runtime/stt.ts +93 -71
- package/src/server/error-stack-frames.ts +214 -0
- package/src/server/index.ts +66 -0
- package/src/server/sdk-version.ts +22 -0
- package/src/server/self-test.ts +1 -21
- package/src/server/sensitive-values.ts +14 -0
- package/src/server/serve-implementation.ts +601 -157
- package/src/server/types.ts +7 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
- package/src/stateful/stateful-provider-runtime-context.ts +4 -0
- package/src/types.ts +99 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
package/src/runtime/resolver.ts
CHANGED
|
@@ -29,7 +29,10 @@ import {
|
|
|
29
29
|
import { createBrowserResolverVendorAdapter } from "./resolver-vendors/browser.js";
|
|
30
30
|
import { createCapsolverResolverVendorAdapter } from "./resolver-vendors/capsolver.js";
|
|
31
31
|
import { createHypersolutionsResolverVendorAdapter } from "./resolver-vendors/hypersolutions.js";
|
|
32
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
assertResolverHostAllowed,
|
|
34
|
+
assertResolverVendorTransportHosts,
|
|
35
|
+
} from "./resolver-vendors/hosts.js";
|
|
33
36
|
import { createTwoCaptchaResolverVendorAdapter } from "./resolver-vendors/twocaptcha.js";
|
|
34
37
|
import {
|
|
35
38
|
RESOLVER_VENDOR_CAPABILITIES,
|
|
@@ -63,6 +66,7 @@ import {
|
|
|
63
66
|
} from "./resolver-config.js";
|
|
64
67
|
import { DEFAULT_STEALTH_PROFILE } from "./stealth.js";
|
|
65
68
|
import type { TraceRecorder } from "./trace.js";
|
|
69
|
+
import type { BrowserTelemetrySink } from "./browser-telemetry.js";
|
|
66
70
|
import type {
|
|
67
71
|
ResolverTelemetryErrorClass,
|
|
68
72
|
ResolverTelemetryPhase,
|
|
@@ -127,6 +131,8 @@ export interface ResolverRuntimeOptions {
|
|
|
127
131
|
readonly cache?: ProviderCache;
|
|
128
132
|
/** Optional request-scoped observability sink; never used as resolver identity. */
|
|
129
133
|
readonly telemetry?: ResolverTelemetrySink;
|
|
134
|
+
/** Request-scoped browser sink used by the resolver-owned browser vendor. */
|
|
135
|
+
readonly browserTelemetry?: BrowserTelemetrySink;
|
|
130
136
|
/** Inputs for SDK-owned lazy proxy resolution. The SDK never accepts a caller-built identity. */
|
|
131
137
|
readonly proxyIntent?: {
|
|
132
138
|
readonly mode: ProviderProxyMode;
|
|
@@ -222,6 +228,7 @@ export type ResolverAdapterFactory = (
|
|
|
222
228
|
configuration: string | undefined,
|
|
223
229
|
timeoutMs: number,
|
|
224
230
|
allowedHosts: readonly string[],
|
|
231
|
+
telemetry?: BrowserTelemetrySink,
|
|
225
232
|
) => ResolverVendorAdapter;
|
|
226
233
|
|
|
227
234
|
const resolverAdapterRegistry: Partial<Record<ProviderResolverVendor, ResolverAdapterFactory>> = {
|
|
@@ -242,11 +249,12 @@ const resolverAdapterRegistry: Partial<Record<ProviderResolverVendor, ResolverAd
|
|
|
242
249
|
timeoutMs,
|
|
243
250
|
});
|
|
244
251
|
},
|
|
245
|
-
browser(configuration, timeoutMs, allowedHosts) {
|
|
252
|
+
browser(configuration, timeoutMs, allowedHosts, telemetry) {
|
|
246
253
|
return createBrowserResolverVendorAdapter({
|
|
247
254
|
allowedHosts,
|
|
248
255
|
cdpUrl: configuration,
|
|
249
256
|
timeoutMs,
|
|
257
|
+
telemetry,
|
|
250
258
|
});
|
|
251
259
|
},
|
|
252
260
|
hypersolutions(configuration, timeoutMs, allowedHosts) {
|
|
@@ -306,7 +314,7 @@ const KNOWN_UNIMPLEMENTED_RESOLVER_VENDORS: ReadonlySet<ProviderResolverVendor>
|
|
|
306
314
|
type ResolverChainEntry = {
|
|
307
315
|
readonly id: ProviderResolverVendor;
|
|
308
316
|
supports(kind: ProviderChallengeKind): boolean;
|
|
309
|
-
createAdapter(): ResolverVendorAdapter;
|
|
317
|
+
createAdapter(browserTelemetry?: BrowserTelemetrySink): ResolverVendorAdapter;
|
|
310
318
|
};
|
|
311
319
|
|
|
312
320
|
function normalizedEnvValue(env: EnvLike, key: string): string | undefined {
|
|
@@ -365,6 +373,7 @@ function createAdapter(
|
|
|
365
373
|
timeoutMs: number,
|
|
366
374
|
allowedHosts: readonly string[],
|
|
367
375
|
adapterFactories: Partial<Readonly<Record<ProviderResolverVendor, ResolverAdapterFactory>>>,
|
|
376
|
+
browserTelemetry?: BrowserTelemetrySink,
|
|
368
377
|
): ResolverVendorAdapter {
|
|
369
378
|
const factory = adapterFactories[vendor.vendor];
|
|
370
379
|
if (!factory && !KNOWN_UNIMPLEMENTED_RESOLVER_VENDORS.has(vendor.vendor)) {
|
|
@@ -377,7 +386,7 @@ function createAdapter(
|
|
|
377
386
|
}
|
|
378
387
|
|
|
379
388
|
if (factory) {
|
|
380
|
-
return factory(vendor.configuration, timeoutMs, allowedHosts);
|
|
389
|
+
return factory(vendor.configuration, timeoutMs, allowedHosts, browserTelemetry);
|
|
381
390
|
}
|
|
382
391
|
return createUnavailableAdapter(vendor.vendor, "not_implemented");
|
|
383
392
|
}
|
|
@@ -480,15 +489,26 @@ function sanitizeCauseMessage(message: string): string {
|
|
|
480
489
|
.slice(0, 512);
|
|
481
490
|
}
|
|
482
491
|
|
|
492
|
+
function assertResolverTransportLive(revoked: boolean): void {
|
|
493
|
+
if (!revoked) return;
|
|
494
|
+
throw new ProviderError("Resolver transport was revoked when the vendor solve settled", {
|
|
495
|
+
code: "RESOLVER_TRANSPORT_REVOKED",
|
|
496
|
+
fix: "Complete every bound-transport call before solve() settles; the transport is per-attempt and must not be retained.",
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
483
500
|
function restrictResolverTransport(
|
|
484
501
|
transport: ResolverVendorTransport,
|
|
485
502
|
allowedHosts: readonly string[],
|
|
486
|
-
): ResolverVendorTransport {
|
|
487
|
-
|
|
503
|
+
): { readonly transport: ResolverVendorTransport; revoke(): void } {
|
|
504
|
+
// A retained reference must fail closed once the adapter's solve has settled.
|
|
505
|
+
let revoked = false;
|
|
506
|
+
const restricted: ResolverVendorTransport = {
|
|
488
507
|
sessionHeaders: transport.sessionHeaders,
|
|
489
508
|
...(transport.getCookie
|
|
490
509
|
? {
|
|
491
510
|
getCookie(name, url) {
|
|
511
|
+
assertResolverTransportLive(revoked);
|
|
492
512
|
// Jar reads are gated like fetches: an adapter may only read state for declared hosts.
|
|
493
513
|
assertResolverHostAllowed(url, allowedHosts);
|
|
494
514
|
return transport.getCookie?.(name, url);
|
|
@@ -496,6 +516,7 @@ function restrictResolverTransport(
|
|
|
496
516
|
}
|
|
497
517
|
: {}),
|
|
498
518
|
async fetch(url, init) {
|
|
519
|
+
assertResolverTransportLive(revoked);
|
|
499
520
|
// Empty declarations remain deny-by-default, matching the adapter-factory/browser path.
|
|
500
521
|
assertResolverHostAllowed(url, allowedHosts);
|
|
501
522
|
const response = await transport.fetch(url, { ...init, redirect: "manual" });
|
|
@@ -511,6 +532,12 @@ function restrictResolverTransport(
|
|
|
511
532
|
return response;
|
|
512
533
|
},
|
|
513
534
|
};
|
|
535
|
+
return {
|
|
536
|
+
transport: restricted,
|
|
537
|
+
revoke() {
|
|
538
|
+
revoked = true;
|
|
539
|
+
},
|
|
540
|
+
};
|
|
514
541
|
}
|
|
515
542
|
|
|
516
543
|
function safeCause(error: ResolverVendorUnavailableError): ResolverChainAttempt["cause"] {
|
|
@@ -1042,7 +1069,8 @@ async function resolveResolverIdentity(
|
|
|
1042
1069
|
}
|
|
1043
1070
|
|
|
1044
1071
|
function createChainTelemetryBinding(options: Parameters<typeof createResolverChainClient>[0]) {
|
|
1045
|
-
return (telemetry: ResolverTelemetrySink
|
|
1072
|
+
return (telemetry: ResolverTelemetrySink, browserTelemetry?: BrowserTelemetrySink) =>
|
|
1073
|
+
createResolverChainClient({ ...options, telemetry, browserTelemetry });
|
|
1046
1074
|
}
|
|
1047
1075
|
|
|
1048
1076
|
function createResolverChainClient(options: {
|
|
@@ -1059,6 +1087,7 @@ function createResolverChainClient(options: {
|
|
|
1059
1087
|
readonly clientProfile?: string;
|
|
1060
1088
|
readonly allowedHosts?: readonly string[];
|
|
1061
1089
|
readonly telemetry?: ResolverTelemetrySink;
|
|
1090
|
+
readonly browserTelemetry?: BrowserTelemetrySink;
|
|
1062
1091
|
}): ResolverChainClient {
|
|
1063
1092
|
assertClientProfileTransportContract(options.clientProfile, options.transport);
|
|
1064
1093
|
const cache =
|
|
@@ -1167,7 +1196,7 @@ function createResolverChainClient(options: {
|
|
|
1167
1196
|
}
|
|
1168
1197
|
const attempts: ResolverChainAttempt[] = [];
|
|
1169
1198
|
for (const [entryIndex, entry] of supportingEntries.entries()) {
|
|
1170
|
-
const adapter = entry.createAdapter();
|
|
1199
|
+
const adapter = entry.createAdapter(options.browserTelemetry);
|
|
1171
1200
|
const attemptStartedAt = Date.now();
|
|
1172
1201
|
const diagnostics: ResolverAttemptDiagnostics = {};
|
|
1173
1202
|
const telemetryTraceRecorder = createResolverTelemetryTraceRecorder({
|
|
@@ -1179,7 +1208,11 @@ function createResolverChainClient(options: {
|
|
|
1179
1208
|
});
|
|
1180
1209
|
let solution: ChallengeSolution;
|
|
1181
1210
|
try {
|
|
1182
|
-
const solveAttempt = () => {
|
|
1211
|
+
const solveAttempt = async () => {
|
|
1212
|
+
// Boundary first: an overreaching declaration is a caller fault even when no
|
|
1213
|
+
// transport is configured, not a "missing_transport" vendor unavailability.
|
|
1214
|
+
const adapterHosts = adapter.transportAllowedHosts ?? [];
|
|
1215
|
+
assertResolverVendorTransportHosts(adapter.id, adapterHosts);
|
|
1183
1216
|
const requiresTransport = adapterRequiresTransport(adapter, challenge.kind);
|
|
1184
1217
|
const unrestrictedTransport =
|
|
1185
1218
|
options.transport ??
|
|
@@ -1192,10 +1225,10 @@ function createResolverChainClient(options: {
|
|
|
1192
1225
|
if (requiresTransport && unrestrictedTransport === undefined) {
|
|
1193
1226
|
throw new ResolverVendorUnavailableError(adapter.id, "missing_transport");
|
|
1194
1227
|
}
|
|
1195
|
-
const
|
|
1228
|
+
const boundTransport = unrestrictedTransport
|
|
1196
1229
|
? restrictResolverTransport(unrestrictedTransport, [
|
|
1197
1230
|
...(options.allowedHosts ?? []),
|
|
1198
|
-
...
|
|
1231
|
+
...adapterHosts,
|
|
1199
1232
|
])
|
|
1200
1233
|
: undefined;
|
|
1201
1234
|
const usage: ResolverPaidUsageContext = {
|
|
@@ -1209,14 +1242,18 @@ function createResolverChainClient(options: {
|
|
|
1209
1242
|
}
|
|
1210
1243
|
: {}),
|
|
1211
1244
|
};
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1245
|
+
try {
|
|
1246
|
+
return await adapter.solve(
|
|
1247
|
+
challenge,
|
|
1248
|
+
identity,
|
|
1249
|
+
signal,
|
|
1250
|
+
telemetryTraceRecorder,
|
|
1251
|
+
boundTransport?.transport,
|
|
1252
|
+
usage,
|
|
1253
|
+
);
|
|
1254
|
+
} finally {
|
|
1255
|
+
boundTransport?.revoke();
|
|
1256
|
+
}
|
|
1220
1257
|
};
|
|
1221
1258
|
solution = traceRecorder
|
|
1222
1259
|
? await traceRecorder.runSpan("resolver.vendor.attempt", solveAttempt, {
|
|
@@ -1334,7 +1371,7 @@ function createResolverChainClient(options: {
|
|
|
1334
1371
|
},
|
|
1335
1372
|
};
|
|
1336
1373
|
resolverCaches.set(client, cache ?? null);
|
|
1337
|
-
const reusableOptions = { ...options, telemetry: undefined };
|
|
1374
|
+
const reusableOptions = { ...options, telemetry: undefined, browserTelemetry: undefined };
|
|
1338
1375
|
registerResolverTelemetryBinding(client, createChainTelemetryBinding(reusableOptions));
|
|
1339
1376
|
return client;
|
|
1340
1377
|
}
|
|
@@ -1352,6 +1389,10 @@ export function createResolverClient(options: {
|
|
|
1352
1389
|
readonly allowedHosts?: readonly string[];
|
|
1353
1390
|
readonly telemetry?: ResolverTelemetrySink;
|
|
1354
1391
|
}): ResolverChainClient {
|
|
1392
|
+
for (const adapter of options.adapters) {
|
|
1393
|
+
// Fail at construction, not on the first solve, when a supplied adapter oversteps its vendor.
|
|
1394
|
+
assertResolverVendorTransportHosts(adapter.id, adapter.transportAllowedHosts ?? []);
|
|
1395
|
+
}
|
|
1355
1396
|
return createResolverChainClient({
|
|
1356
1397
|
kinds: options.kinds,
|
|
1357
1398
|
entries: options.adapters.map((adapter) => ({
|
|
@@ -1459,12 +1500,13 @@ function createResolverClientFromEnvInternal(
|
|
|
1459
1500
|
return {
|
|
1460
1501
|
id: vendor,
|
|
1461
1502
|
supports: (kind: ProviderChallengeKind) => resolverVendorSupports(vendor, kind),
|
|
1462
|
-
createAdapter: () =>
|
|
1503
|
+
createAdapter: (browserTelemetry) =>
|
|
1463
1504
|
createAdapter(
|
|
1464
1505
|
resolveVendorAvailability(vendor, env),
|
|
1465
1506
|
timeoutMs,
|
|
1466
1507
|
allowedHosts,
|
|
1467
1508
|
adapterFactories,
|
|
1509
|
+
browserTelemetry,
|
|
1468
1510
|
),
|
|
1469
1511
|
};
|
|
1470
1512
|
}),
|
|
@@ -1477,6 +1519,7 @@ function createResolverClientFromEnvInternal(
|
|
|
1477
1519
|
clientProfile: config.clientProfile,
|
|
1478
1520
|
allowedHosts,
|
|
1479
1521
|
telemetry: options.telemetry,
|
|
1522
|
+
browserTelemetry: options.browserTelemetry,
|
|
1480
1523
|
});
|
|
1481
1524
|
}
|
|
1482
1525
|
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ProviderRuntimeState,
|
|
3
|
+
ProviderStateNamespace,
|
|
4
|
+
StateNamespaceOptions,
|
|
5
|
+
} from "../types.js";
|
|
6
|
+
import { createTelemetryObserver } from "./http-telemetry-guard.js";
|
|
7
|
+
import {
|
|
8
|
+
type ClosedEnum,
|
|
9
|
+
closedEnum,
|
|
10
|
+
type SpanIndex,
|
|
11
|
+
type TelemetryContributor,
|
|
12
|
+
} from "./request-telemetry.js";
|
|
13
|
+
import { getStateViolation, isStateRedisNoop } from "./state.js";
|
|
14
|
+
|
|
15
|
+
export type StateTelemetryOperation =
|
|
16
|
+
| "list"
|
|
17
|
+
| "get"
|
|
18
|
+
| "set"
|
|
19
|
+
| "patch"
|
|
20
|
+
| "delete"
|
|
21
|
+
| "cas"
|
|
22
|
+
| "increment";
|
|
23
|
+
export type StateTelemetryBackend = "redis" | "memory" | "unsupported";
|
|
24
|
+
export type StateTelemetryViolation = "quota" | "ttl" | "size" | "unsupported" | "error";
|
|
25
|
+
|
|
26
|
+
export type StateTelemetrySample = {
|
|
27
|
+
key: string;
|
|
28
|
+
op: StateTelemetryOperation;
|
|
29
|
+
ms: number;
|
|
30
|
+
backend: StateTelemetryBackend;
|
|
31
|
+
};
|
|
32
|
+
export type StateTelemetryLogPayload = {
|
|
33
|
+
telemetryFailed?: true;
|
|
34
|
+
ops: {
|
|
35
|
+
list: number;
|
|
36
|
+
get: number;
|
|
37
|
+
set: number;
|
|
38
|
+
patch: number;
|
|
39
|
+
delete: number;
|
|
40
|
+
cas: number;
|
|
41
|
+
increment: number;
|
|
42
|
+
};
|
|
43
|
+
casConflicts: number;
|
|
44
|
+
violations: { quota: number; ttl: number; size: number; unsupported: number; error: number };
|
|
45
|
+
backend: ClosedEnum<StateTelemetryBackend>;
|
|
46
|
+
/** State fails closed on Redis errors, so this remains 0 until a fallback exists. */
|
|
47
|
+
redisFallbacks: number;
|
|
48
|
+
redisMode: ClosedEnum<"not_configured" | "configured" | "degraded">;
|
|
49
|
+
/** Successful state operations that touch Redis; each operation counts once, regardless of command count. */
|
|
50
|
+
redisRoundTrips: number;
|
|
51
|
+
ms: number;
|
|
52
|
+
samples: StateTelemetrySample[];
|
|
53
|
+
dropped: number;
|
|
54
|
+
};
|
|
55
|
+
export type StateTelemetryHeaderPayload = Omit<
|
|
56
|
+
StateTelemetryLogPayload,
|
|
57
|
+
"samples" | "telemetryFailed"
|
|
58
|
+
>;
|
|
59
|
+
|
|
60
|
+
export interface StateTelemetrySink {
|
|
61
|
+
markTelemetryFailed?(): void;
|
|
62
|
+
setRedisConfigured?(configured: boolean): void;
|
|
63
|
+
record(event: {
|
|
64
|
+
op: StateTelemetryOperation;
|
|
65
|
+
key?: string;
|
|
66
|
+
ms: number;
|
|
67
|
+
backend: StateTelemetryBackend;
|
|
68
|
+
ok: boolean;
|
|
69
|
+
conflict?: boolean;
|
|
70
|
+
violation?: StateTelemetryViolation;
|
|
71
|
+
/** False for successful Redis-backed operations that execute no Redis commands. */
|
|
72
|
+
redisTouched?: boolean;
|
|
73
|
+
}): void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const MAX_SAMPLES = 24;
|
|
77
|
+
const MAX_TEXT = 300;
|
|
78
|
+
const STATE_TELEMETRY_INSTRUMENTED = Symbol.for(
|
|
79
|
+
"@apifuse/provider-sdk/state-telemetry-instrumented",
|
|
80
|
+
);
|
|
81
|
+
function integer(value: number): number {
|
|
82
|
+
return Number.isFinite(value)
|
|
83
|
+
? Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(value)))
|
|
84
|
+
: Number.MAX_SAFE_INTEGER;
|
|
85
|
+
}
|
|
86
|
+
function add(a: number, b: number): number {
|
|
87
|
+
return Math.min(Number.MAX_SAFE_INTEGER, integer(a) + integer(b));
|
|
88
|
+
}
|
|
89
|
+
function keyText(value: string | undefined, redact?: (text: string) => string): string | undefined {
|
|
90
|
+
if (value === undefined) return undefined;
|
|
91
|
+
let result: string;
|
|
92
|
+
try {
|
|
93
|
+
result = redact?.(value) ?? value;
|
|
94
|
+
} catch {
|
|
95
|
+
result = "[REDACTION_FAILED]";
|
|
96
|
+
}
|
|
97
|
+
const length = Math.min(result.length, MAX_TEXT);
|
|
98
|
+
const units = new Uint16Array(length);
|
|
99
|
+
for (let index = 0; index < length; index += 1) units[index] = result.charCodeAt(index);
|
|
100
|
+
return String.fromCharCode(...units);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class StateTelemetryCollector
|
|
104
|
+
implements
|
|
105
|
+
TelemetryContributor<StateTelemetryLogPayload, StateTelemetryHeaderPayload>,
|
|
106
|
+
StateTelemetrySink
|
|
107
|
+
{
|
|
108
|
+
readonly key = "state" as const;
|
|
109
|
+
readonly #redact?: (text: string) => string;
|
|
110
|
+
#telemetryFailed = false;
|
|
111
|
+
#ops = { list: 0, get: 0, set: 0, patch: 0, delete: 0, cas: 0, increment: 0 };
|
|
112
|
+
#conflicts = 0;
|
|
113
|
+
#violations = { quota: 0, ttl: 0, size: 0, unsupported: 0, error: 0 };
|
|
114
|
+
#backend: StateTelemetryBackend = "unsupported";
|
|
115
|
+
#redisFallbacks = 0;
|
|
116
|
+
#configured: "not_configured" | "configured" | "degraded" = "not_configured";
|
|
117
|
+
#redisRoundTrips = 0;
|
|
118
|
+
#ms = 0;
|
|
119
|
+
#samples: StateTelemetrySample[] = [];
|
|
120
|
+
#dropped = 0;
|
|
121
|
+
constructor(options: { redact?: (text: string) => string } = {}) {
|
|
122
|
+
this.#redact = options.redact;
|
|
123
|
+
}
|
|
124
|
+
markTelemetryFailed(): void {
|
|
125
|
+
this.#telemetryFailed = true;
|
|
126
|
+
}
|
|
127
|
+
setRedisConfigured(configured: boolean): void {
|
|
128
|
+
if (configured && this.#configured === "not_configured") this.#configured = "configured";
|
|
129
|
+
}
|
|
130
|
+
record(event: {
|
|
131
|
+
op: StateTelemetryOperation;
|
|
132
|
+
key?: string;
|
|
133
|
+
ms: number;
|
|
134
|
+
backend: StateTelemetryBackend;
|
|
135
|
+
ok: boolean;
|
|
136
|
+
conflict?: boolean;
|
|
137
|
+
violation?: StateTelemetryViolation;
|
|
138
|
+
/** False for successful Redis-backed operations that execute no Redis commands. */
|
|
139
|
+
redisTouched?: boolean;
|
|
140
|
+
}): void {
|
|
141
|
+
if (
|
|
142
|
+
!["list", "get", "set", "patch", "delete", "cas", "increment"].includes(event.op) ||
|
|
143
|
+
!["redis", "memory", "unsupported"].includes(event.backend) ||
|
|
144
|
+
(event.violation !== undefined &&
|
|
145
|
+
!["quota", "ttl", "size", "unsupported", "error"].includes(event.violation))
|
|
146
|
+
) {
|
|
147
|
+
this.#telemetryFailed = true;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
this.#ops[event.op] = add(this.#ops[event.op], 1);
|
|
151
|
+
this.#backend = event.backend;
|
|
152
|
+
if (event.backend === "redis" && this.#configured === "not_configured")
|
|
153
|
+
this.#configured = "configured";
|
|
154
|
+
if (event.backend === "redis" && event.ok && event.redisTouched !== false)
|
|
155
|
+
this.#redisRoundTrips = add(this.#redisRoundTrips, 1);
|
|
156
|
+
if (event.backend === "redis" && !event.ok) this.#configured = "degraded";
|
|
157
|
+
this.#ms = add(this.#ms, event.ms);
|
|
158
|
+
if (event.conflict) this.#conflicts = add(this.#conflicts, 1);
|
|
159
|
+
if (event.violation)
|
|
160
|
+
this.#violations[event.violation] = add(this.#violations[event.violation], 1);
|
|
161
|
+
if (this.#samples.length < MAX_SAMPLES)
|
|
162
|
+
this.#samples.push({
|
|
163
|
+
key: keyText(event.key, this.#redact) ?? "",
|
|
164
|
+
op: event.op,
|
|
165
|
+
ms: integer(event.ms),
|
|
166
|
+
backend: event.backend,
|
|
167
|
+
});
|
|
168
|
+
else this.#dropped = add(this.#dropped, 1);
|
|
169
|
+
}
|
|
170
|
+
toLogPayload(_spans: SpanIndex): StateTelemetryLogPayload | undefined {
|
|
171
|
+
if (Object.values(this.#ops).every((value) => value === 0) && !this.#telemetryFailed)
|
|
172
|
+
return undefined;
|
|
173
|
+
return {
|
|
174
|
+
...(this.#telemetryFailed ? { telemetryFailed: true as const } : {}),
|
|
175
|
+
ops: { ...this.#ops },
|
|
176
|
+
casConflicts: this.#conflicts,
|
|
177
|
+
violations: { ...this.#violations },
|
|
178
|
+
backend: closedEnum(this.#backend),
|
|
179
|
+
redisFallbacks: this.#redisFallbacks,
|
|
180
|
+
redisMode: closedEnum(this.#configured),
|
|
181
|
+
redisRoundTrips: this.#redisRoundTrips,
|
|
182
|
+
ms: this.#ms,
|
|
183
|
+
samples: this.#samples.map((sample) => ({ ...sample })),
|
|
184
|
+
dropped: this.#dropped,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
toHeaderPayload(log: StateTelemetryLogPayload): StateTelemetryHeaderPayload {
|
|
188
|
+
return {
|
|
189
|
+
ops: log.ops,
|
|
190
|
+
casConflicts: log.casConflicts,
|
|
191
|
+
violations: log.violations,
|
|
192
|
+
backend: log.backend,
|
|
193
|
+
redisFallbacks: log.redisFallbacks,
|
|
194
|
+
redisMode: log.redisMode,
|
|
195
|
+
redisRoundTrips: log.redisRoundTrips,
|
|
196
|
+
ms: log.ms,
|
|
197
|
+
dropped: log.dropped,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function backendOf(state: ProviderRuntimeState): StateTelemetryBackend {
|
|
203
|
+
try {
|
|
204
|
+
const name = state.constructor?.name;
|
|
205
|
+
return name?.includes("Redis") ? "redis" : name?.includes("Memory") ? "memory" : "unsupported";
|
|
206
|
+
} catch {
|
|
207
|
+
return "unsupported";
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function violationOf(error: unknown): StateTelemetryViolation {
|
|
212
|
+
return getStateViolation(error) ?? "error";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function wrapNamespace(
|
|
216
|
+
namespace: ProviderStateNamespace,
|
|
217
|
+
sink: StateTelemetrySink,
|
|
218
|
+
backend: StateTelemetryBackend,
|
|
219
|
+
): ProviderStateNamespace {
|
|
220
|
+
// Compare-and-set records one event per attempt; a three-attempt loop therefore
|
|
221
|
+
// reports cas: 3 and casConflicts: 2 when the first two attempts conflict.
|
|
222
|
+
const observe = createTelemetryObserver(sink);
|
|
223
|
+
return new Proxy(namespace, {
|
|
224
|
+
get(target, property, receiver) {
|
|
225
|
+
const value = Reflect.get(target, property, receiver);
|
|
226
|
+
if (typeof value !== "function" || property === "constructor") return value;
|
|
227
|
+
const op =
|
|
228
|
+
property === "compareAndSet" ? "cas" : (String(property) as StateTelemetryOperation);
|
|
229
|
+
if (!(op in { list: 1, get: 1, set: 1, patch: 1, delete: 1, cas: 1, increment: 1 }))
|
|
230
|
+
return value;
|
|
231
|
+
return async (...args: unknown[]) => {
|
|
232
|
+
const started = Date.now();
|
|
233
|
+
const key = typeof args[0] === "string" ? args[0] : undefined;
|
|
234
|
+
try {
|
|
235
|
+
const result = await Reflect.apply(value, target, args);
|
|
236
|
+
observe(() =>
|
|
237
|
+
sink.record({
|
|
238
|
+
op,
|
|
239
|
+
key,
|
|
240
|
+
ms: Date.now() - started,
|
|
241
|
+
backend,
|
|
242
|
+
ok: true,
|
|
243
|
+
redisTouched: !isStateRedisNoop(result),
|
|
244
|
+
conflict:
|
|
245
|
+
op === "cas" &&
|
|
246
|
+
!!result &&
|
|
247
|
+
typeof result === "object" &&
|
|
248
|
+
"ok" in result &&
|
|
249
|
+
result.ok === false,
|
|
250
|
+
}),
|
|
251
|
+
);
|
|
252
|
+
return result;
|
|
253
|
+
} catch (error) {
|
|
254
|
+
observe(() =>
|
|
255
|
+
sink.record({
|
|
256
|
+
op,
|
|
257
|
+
key,
|
|
258
|
+
ms: Date.now() - started,
|
|
259
|
+
backend,
|
|
260
|
+
ok: false,
|
|
261
|
+
violation: violationOf(error),
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
},
|
|
268
|
+
}) as ProviderStateNamespace;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function instrumentProviderRuntimeState(
|
|
272
|
+
state: ProviderRuntimeState,
|
|
273
|
+
sink: StateTelemetrySink,
|
|
274
|
+
redact?: (text: string) => string,
|
|
275
|
+
): ProviderRuntimeState {
|
|
276
|
+
if (
|
|
277
|
+
(state as ProviderRuntimeState & { [STATE_TELEMETRY_INSTRUMENTED]?: boolean })[
|
|
278
|
+
STATE_TELEMETRY_INSTRUMENTED
|
|
279
|
+
]
|
|
280
|
+
)
|
|
281
|
+
return state;
|
|
282
|
+
const backend = backendOf(state);
|
|
283
|
+
const observe = createTelemetryObserver(sink);
|
|
284
|
+
observe(() => sink.setRedisConfigured?.(backend === "redis"));
|
|
285
|
+
return new Proxy(state, {
|
|
286
|
+
get(target, property, receiver) {
|
|
287
|
+
if (property === STATE_TELEMETRY_INSTRUMENTED) return true;
|
|
288
|
+
const value = Reflect.get(target, property, receiver);
|
|
289
|
+
if (property === "forConnection" && typeof value === "function")
|
|
290
|
+
return (id: string | undefined) =>
|
|
291
|
+
instrumentProviderRuntimeState(value.call(target, id), sink, redact);
|
|
292
|
+
if (property === "namespace" && typeof value === "function")
|
|
293
|
+
return (name: string, options: StateNamespaceOptions) =>
|
|
294
|
+
wrapNamespace(value.call(target, name, options), sink, backend);
|
|
295
|
+
return value;
|
|
296
|
+
},
|
|
297
|
+
}) as ProviderRuntimeState;
|
|
298
|
+
}
|